dotcloud/docker

View on GitHub
builder/builder-next/reqbodyhandler.go

Summary

Maintainability
A
0 mins
Test Coverage
package buildkit

import (
    "io"
    "net/http"
    "strings"
    "sync"

    "github.com/moby/buildkit/identity"
    "github.com/pkg/errors"
)

const urlPrefix = "build-context-"

type reqBodyHandler struct {
    mu sync.Mutex
    rt http.RoundTripper

    requests map[string]io.ReadCloser
}

func newReqBodyHandler(rt http.RoundTripper) *reqBodyHandler {
    return &reqBodyHandler{
        rt:       rt,
        requests: map[string]io.ReadCloser{},
    }
}

func (h *reqBodyHandler) newRequest(rc io.ReadCloser) (string, func()) {
    id := identity.NewID()
    h.mu.Lock()
    h.requests[id] = rc
    h.mu.Unlock()
    return "http://" + urlPrefix + id, func() {
        h.mu.Lock()
        delete(h.requests, id)
        h.mu.Unlock()
        rc.Close()
    }
}

func (h *reqBodyHandler) RoundTrip(req *http.Request) (*http.Response, error) {
    host := req.URL.Host
    if strings.HasPrefix(host, urlPrefix) {
        if req.Method != http.MethodGet {
            return nil, errors.Errorf("invalid request")
        }
        id := strings.TrimPrefix(host, urlPrefix)
        h.mu.Lock()
        rc, ok := h.requests[id]
        delete(h.requests, id)
        h.mu.Unlock()

        if !ok {
            return nil, errors.Errorf("context not found")
        }

        resp := &http.Response{
            Status:        "200 OK",
            StatusCode:    http.StatusOK,
            Body:          rc,
            ContentLength: -1,
        }

        return resp, nil
    }
    return h.rt.RoundTrip(req)
}