github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/builder/builder-next/reqbodyhandler.go (about)

     1  package buildkit
     2  
     3  import (
     4  	"io"
     5  	"net/http"
     6  	"strings"
     7  	"sync"
     8  
     9  	"github.com/moby/buildkit/identity"
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  const urlPrefix = "build-context-"
    14  
    15  type reqBodyHandler struct {
    16  	mu sync.Mutex
    17  	rt http.RoundTripper
    18  
    19  	requests map[string]io.ReadCloser
    20  }
    21  
    22  func newReqBodyHandler(rt http.RoundTripper) *reqBodyHandler {
    23  	return &reqBodyHandler{
    24  		rt:       rt,
    25  		requests: map[string]io.ReadCloser{},
    26  	}
    27  }
    28  
    29  func (h *reqBodyHandler) newRequest(rc io.ReadCloser) (string, func()) {
    30  	id := identity.NewID()
    31  	h.mu.Lock()
    32  	h.requests[id] = rc
    33  	h.mu.Unlock()
    34  	return "http://" + urlPrefix + id, func() {
    35  		h.mu.Lock()
    36  		delete(h.requests, id)
    37  		h.mu.Unlock()
    38  		rc.Close()
    39  	}
    40  }
    41  
    42  func (h *reqBodyHandler) RoundTrip(req *http.Request) (*http.Response, error) {
    43  	host := req.URL.Host
    44  	if strings.HasPrefix(host, urlPrefix) {
    45  		if req.Method != http.MethodGet {
    46  			return nil, errors.Errorf("invalid request")
    47  		}
    48  		id := strings.TrimPrefix(host, urlPrefix)
    49  		h.mu.Lock()
    50  		rc, ok := h.requests[id]
    51  		delete(h.requests, id)
    52  		h.mu.Unlock()
    53  
    54  		if !ok {
    55  			return nil, errors.Errorf("context not found")
    56  		}
    57  
    58  		resp := &http.Response{
    59  			Status:        "200 OK",
    60  			StatusCode:    http.StatusOK,
    61  			Body:          rc,
    62  			ContentLength: -1,
    63  		}
    64  
    65  		return resp, nil
    66  	}
    67  	return h.rt.RoundTrip(req)
    68  }