reqbodyhandler.go 1.3 KB

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