77 lines
2.0 KiB
Go
77 lines
2.0 KiB
Go
package httpfetcher
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
// TestFetch_SendsConditionalHeadersAndHandlesNotModified checks that Fetch
|
|
// sends a non-empty ifNoneMatch and ifModifiedSince as request headers, that
|
|
// upstream's 304 to such a request is a result with status 304 and no
|
|
// content, and that a 304 to a request with neither is ErrUpstreamError.
|
|
func TestFetch_SendsConditionalHeadersAndHandlesNotModified(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const (
|
|
etag = `"abc"`
|
|
lastModified = "Mon, 02 Nov 2026 10:00:00 GMT"
|
|
)
|
|
|
|
var (
|
|
mu sync.Mutex
|
|
received http.Header
|
|
)
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
mu.Lock()
|
|
received = r.Header.Clone()
|
|
mu.Unlock()
|
|
|
|
w.WriteHeader(http.StatusNotModified)
|
|
}))
|
|
t.Cleanup(srv.Close)
|
|
|
|
f, _ := newServerFetcher(t, srv, nil)
|
|
|
|
res, err := f.Fetch(testContext(t), upstreamSource("/image"), etag, lastModified)
|
|
if err != nil {
|
|
t.Fatalf("conditional Fetch() error = %v", err)
|
|
}
|
|
|
|
body, err := io.ReadAll(res.Content)
|
|
_ = res.Content.Close()
|
|
|
|
mu.Lock()
|
|
t.Logf("status = %d, body = %q, request headers = %v", res.StatusCode, body, received)
|
|
gotIfNoneMatch := received.Get("If-None-Match")
|
|
gotIfModifiedSince := received.Get("If-Modified-Since")
|
|
mu.Unlock()
|
|
|
|
if err != nil || len(body) != 0 {
|
|
t.Errorf("304 content = %q, error = %v; want empty", body, err)
|
|
}
|
|
|
|
if res.StatusCode != http.StatusNotModified {
|
|
t.Errorf("StatusCode = %d, want 304", res.StatusCode)
|
|
}
|
|
|
|
if gotIfNoneMatch != etag || gotIfModifiedSince != lastModified {
|
|
t.Errorf("If-None-Match = %q, If-Modified-Since = %q; want %q and %q",
|
|
gotIfNoneMatch, gotIfModifiedSince, etag, lastModified)
|
|
}
|
|
|
|
if held := len(f.allHostsSemaphore); held != 0 {
|
|
t.Errorf("connection still held after the 304: %d held", held)
|
|
}
|
|
|
|
_, err = f.Fetch(testContext(t), upstreamSource("/image"), "", "")
|
|
if !errors.Is(err, ErrUpstreamError) {
|
|
t.Errorf("unconditional Fetch() answered 304: error = %v, want ErrUpstreamError", err)
|
|
}
|
|
}
|