tests: add http policy integration tests
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
+113
@@ -0,0 +1,113 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user