mirror of
https://github.com/moby/buildkit.git
synced 2026-11-06 13:26:48 +00:00
The go http library will normally implicitly set an Accept-Encoding of gzip to requests and then transparently decompress the response body. However, if the Accept-Encoding header is explicitly set by the caller it will no longer transparently decompress the body. This was causing HTTP LLB sources to have unexpectedly compressed contents. The fix here just unsets the Accept-Encoding header after the HEAD request. Another possible fix would be to do our own gzip decompression after reading the body if it was gzipped, but this approach seemed slightly simpler. Signed-off-by: Erik Sipsma <erik@sipsma.dev>
108 lines
2.0 KiB
Go
108 lines
2.0 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type TestServer struct {
|
|
*httptest.Server
|
|
mu sync.Mutex
|
|
routes map[string]Response
|
|
stats map[string]*Stat
|
|
}
|
|
|
|
func NewTestServer(routes map[string]Response) *TestServer {
|
|
ts := &TestServer{
|
|
routes: routes,
|
|
stats: map[string]*Stat{},
|
|
}
|
|
ts.Server = httptest.NewServer(ts)
|
|
return ts
|
|
}
|
|
|
|
func (s *TestServer) SetRoute(name string, resp Response) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.routes[name] = resp
|
|
}
|
|
|
|
func (s *TestServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
s.mu.Lock()
|
|
resp, ok := s.routes[r.URL.Path]
|
|
if !ok {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
s.mu.Unlock()
|
|
return
|
|
}
|
|
|
|
if _, ok := s.stats[r.URL.Path]; !ok {
|
|
s.stats[r.URL.Path] = &Stat{}
|
|
}
|
|
|
|
s.stats[r.URL.Path].AllRequests++
|
|
s.stats[r.URL.Path].Requests = append(s.stats[r.URL.Path].Requests, newRequest(r))
|
|
|
|
if resp.LastModified != nil {
|
|
w.Header().Set("Last-Modified", resp.LastModified.Format(time.RFC850))
|
|
}
|
|
|
|
if resp.ContentEncoding != "" {
|
|
w.Header().Set("Content-Encoding", resp.ContentEncoding)
|
|
}
|
|
|
|
if resp.Etag != "" {
|
|
w.Header().Set("ETag", resp.Etag)
|
|
if match := r.Header.Get("If-None-Match"); match == resp.Etag {
|
|
w.WriteHeader(http.StatusNotModified)
|
|
s.stats[r.URL.Path].CachedRequests++
|
|
s.mu.Unlock()
|
|
return
|
|
}
|
|
}
|
|
|
|
s.mu.Unlock()
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
io.Copy(w, bytes.NewReader(resp.Content))
|
|
}
|
|
|
|
func (s *TestServer) Stats(name string) (st Stat) {
|
|
if st, ok := s.stats[name]; ok {
|
|
return *st
|
|
}
|
|
return
|
|
}
|
|
|
|
type Response struct {
|
|
Content []byte
|
|
Etag string
|
|
LastModified *time.Time
|
|
ContentEncoding string
|
|
}
|
|
|
|
type Stat struct {
|
|
AllRequests, CachedRequests int
|
|
Requests []Request
|
|
}
|
|
|
|
type Request struct {
|
|
Method string
|
|
Header http.Header
|
|
}
|
|
|
|
func newRequest(r *http.Request) Request {
|
|
headers := http.Header{}
|
|
for k, v := range r.Header {
|
|
headers[k] = append([]string{}, v...)
|
|
}
|
|
return Request{
|
|
Method: r.Method,
|
|
Header: headers,
|
|
}
|
|
}
|