Files
buildx/vendor/github.com/moby/buildkit/util/testutil/httpserver/server.go
T
2026-01-14 09:33:49 -08:00

114 lines
2.1 KiB
Go

package httpserver
import (
"bytes"
"io"
"net/http"
"net/http/httptest"
"slices"
"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.ContentDisposition != "" {
w.Header().Set("Content-Disposition", resp.ContentDisposition)
}
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
ContentDisposition 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] = slices.Clone(v)
}
return Request{
Method: r.Method,
Header: headers,
}
}