|
@@ -6,7 +6,6 @@ import (
|
|
|
"net/http"
|
|
|
"net/http/httptest"
|
|
|
"os"
|
|
|
- "path/filepath"
|
|
|
"strconv"
|
|
|
"testing"
|
|
|
"time"
|
|
@@ -22,23 +21,24 @@ import (
|
|
|
"github.com/imgproxy/imgproxy/v3/testutil"
|
|
|
)
|
|
|
|
|
|
-const (
|
|
|
- testDataPath = "../../testdata"
|
|
|
-)
|
|
|
-
|
|
|
type HandlerTestSuite struct {
|
|
|
testutil.LazySuite
|
|
|
|
|
|
+ testData *testutil.TestDataProvider
|
|
|
+
|
|
|
rwConf testutil.LazyObj[*responsewriter.Config]
|
|
|
rwFactory testutil.LazyObj[*responsewriter.Factory]
|
|
|
|
|
|
config testutil.LazyObj[*Config]
|
|
|
handler testutil.LazyObj[*Handler]
|
|
|
+
|
|
|
+ testServer testutil.LazyTestServer
|
|
|
}
|
|
|
|
|
|
func (s *HandlerTestSuite) SetupSuite() {
|
|
|
config.Reset()
|
|
|
- config.AllowLoopbackSourceAddresses = true
|
|
|
+
|
|
|
+ s.testData = testutil.NewTestDataProvider(s.T)
|
|
|
|
|
|
s.rwConf, _ = testutil.NewLazySuiteObj(
|
|
|
s,
|
|
@@ -67,6 +67,7 @@ func (s *HandlerTestSuite) SetupSuite() {
|
|
|
s,
|
|
|
func() (*Handler, error) {
|
|
|
fc := fetcher.NewDefaultConfig()
|
|
|
+ fc.Transport.HTTP.AllowLoopbackSourceAddresses = true
|
|
|
|
|
|
fetcher, err := fetcher.New(&fc)
|
|
|
s.Require().NoError(err)
|
|
@@ -75,36 +76,27 @@ func (s *HandlerTestSuite) SetupSuite() {
|
|
|
},
|
|
|
)
|
|
|
|
|
|
+ s.testServer, _ = testutil.NewLazySuiteTestServer(s)
|
|
|
+
|
|
|
// Silence logs during tests
|
|
|
logrus.SetOutput(io.Discard)
|
|
|
}
|
|
|
|
|
|
func (s *HandlerTestSuite) TearDownSuite() {
|
|
|
- config.Reset()
|
|
|
logrus.SetOutput(os.Stdout)
|
|
|
}
|
|
|
|
|
|
-func (s *HandlerTestSuite) SetupTest() {
|
|
|
- config.Reset()
|
|
|
- config.AllowLoopbackSourceAddresses = true
|
|
|
-}
|
|
|
-
|
|
|
func (s *HandlerTestSuite) SetupSubTest() {
|
|
|
// We use t.Run() a lot, so we need to reset lazy objects at the beginning of each subtest
|
|
|
s.ResetLazyObjects()
|
|
|
}
|
|
|
|
|
|
-func (s *HandlerTestSuite) readTestFile(name string) []byte {
|
|
|
- data, err := os.ReadFile(filepath.Join(testDataPath, name))
|
|
|
- s.Require().NoError(err)
|
|
|
- return data
|
|
|
-}
|
|
|
-
|
|
|
func (s *HandlerTestSuite) execute(
|
|
|
imageURL string,
|
|
|
header http.Header,
|
|
|
po *options.ProcessingOptions,
|
|
|
-) *httptest.ResponseRecorder {
|
|
|
+) *http.Response {
|
|
|
+ imageURL = s.testServer().URL() + imageURL
|
|
|
req := httptest.NewRequest("GET", "/", nil)
|
|
|
httpheaders.CopyAll(header, req.Header, true)
|
|
|
|
|
@@ -115,51 +107,42 @@ func (s *HandlerTestSuite) execute(
|
|
|
err := s.handler().Execute(ctx, req, imageURL, "test-req-id", po, rww)
|
|
|
s.Require().NoError(err)
|
|
|
|
|
|
- return rw
|
|
|
+ return rw.Result()
|
|
|
}
|
|
|
|
|
|
// TestHandlerBasicRequest checks basic streaming request
|
|
|
func (s *HandlerTestSuite) TestHandlerBasicRequest() {
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- w.Header().Set(httpheaders.ContentType, "image/png")
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().SetHeaders(httpheaders.ContentType, "image/png").SetBody(data)
|
|
|
|
|
|
- rw := s.execute(ts.URL, nil, &options.ProcessingOptions{})
|
|
|
+ res := s.execute("", nil, &options.ProcessingOptions{})
|
|
|
|
|
|
- res := rw.Result()
|
|
|
s.Require().Equal(200, res.StatusCode)
|
|
|
s.Require().Equal("image/png", res.Header.Get(httpheaders.ContentType))
|
|
|
|
|
|
// Verify we get the original image data
|
|
|
- actual := rw.Body.Bytes()
|
|
|
+ actual, err := io.ReadAll(res.Body)
|
|
|
+ s.Require().NoError(err)
|
|
|
s.Require().Equal(data, actual)
|
|
|
}
|
|
|
|
|
|
// TestHandlerResponseHeadersPassthrough checks that original response headers are
|
|
|
// passed through to the client
|
|
|
func (s *HandlerTestSuite) TestHandlerResponseHeadersPassthrough() {
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
contentLength := len(data)
|
|
|
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- w.Header().Set(httpheaders.ContentType, "image/png")
|
|
|
- w.Header().Set(httpheaders.ContentLength, strconv.Itoa(contentLength))
|
|
|
- w.Header().Set(httpheaders.AcceptRanges, "bytes")
|
|
|
- w.Header().Set(httpheaders.Etag, "etag")
|
|
|
- w.Header().Set(httpheaders.LastModified, "Wed, 21 Oct 2015 07:28:00 GMT")
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().SetHeaders(
|
|
|
+ httpheaders.ContentType, "image/png",
|
|
|
+ httpheaders.ContentLength, strconv.Itoa(contentLength),
|
|
|
+ httpheaders.AcceptRanges, "bytes",
|
|
|
+ httpheaders.Etag, "etag",
|
|
|
+ httpheaders.LastModified, "Wed, 21 Oct 2015 07:28:00 GMT",
|
|
|
+ ).SetBody(data)
|
|
|
|
|
|
- rw := s.execute(ts.URL, nil, &options.ProcessingOptions{})
|
|
|
+ res := s.execute("", nil, &options.ProcessingOptions{})
|
|
|
|
|
|
- res := rw.Result()
|
|
|
s.Require().Equal(200, res.StatusCode)
|
|
|
s.Require().Equal("image/png", res.Header.Get(httpheaders.ContentType))
|
|
|
s.Require().Equal(strconv.Itoa(contentLength), res.Header.Get(httpheaders.ContentLength))
|
|
@@ -172,42 +155,34 @@ func (s *HandlerTestSuite) TestHandlerResponseHeadersPassthrough() {
|
|
|
// to the server
|
|
|
func (s *HandlerTestSuite) TestHandlerRequestHeadersPassthrough() {
|
|
|
etag := `"test-etag-123"`
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
-
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- // Verify that If-None-Match header is passed through
|
|
|
- s.Equal(etag, r.Header.Get(httpheaders.IfNoneMatch))
|
|
|
- s.Equal("gzip", r.Header.Get(httpheaders.AcceptEncoding))
|
|
|
- s.Equal("bytes=*", r.Header.Get(httpheaders.Range))
|
|
|
-
|
|
|
- w.Header().Set(httpheaders.Etag, etag)
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
+
|
|
|
+ s.testServer().
|
|
|
+ SetBody(data).
|
|
|
+ SetHeaders(httpheaders.Etag, etag).
|
|
|
+ SetHook(func(r *http.Request, rw http.ResponseWriter) {
|
|
|
+ // Verify that If-None-Match header is passed through
|
|
|
+ s.Equal(etag, r.Header.Get(httpheaders.IfNoneMatch))
|
|
|
+ s.Equal("gzip", r.Header.Get(httpheaders.AcceptEncoding))
|
|
|
+ s.Equal("bytes=*", r.Header.Get(httpheaders.Range))
|
|
|
+ })
|
|
|
|
|
|
h := make(http.Header)
|
|
|
h.Set(httpheaders.IfNoneMatch, etag)
|
|
|
h.Set(httpheaders.AcceptEncoding, "gzip")
|
|
|
h.Set(httpheaders.Range, "bytes=*")
|
|
|
|
|
|
- rw := s.execute(ts.URL, h, &options.ProcessingOptions{})
|
|
|
+ res := s.execute("", h, &options.ProcessingOptions{})
|
|
|
|
|
|
- res := rw.Result()
|
|
|
s.Require().Equal(200, res.StatusCode)
|
|
|
s.Require().Equal(etag, res.Header.Get(httpheaders.Etag))
|
|
|
}
|
|
|
|
|
|
// TestHandlerContentDisposition checks that Content-Disposition header is set correctly
|
|
|
func (s *HandlerTestSuite) TestHandlerContentDisposition() {
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- w.Header().Set(httpheaders.ContentType, "image/png")
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().SetHeaders(httpheaders.ContentType, "image/png").SetBody(data)
|
|
|
|
|
|
po := &options.ProcessingOptions{
|
|
|
Filename: "custom_name",
|
|
@@ -215,10 +190,8 @@ func (s *HandlerTestSuite) TestHandlerContentDisposition() {
|
|
|
}
|
|
|
|
|
|
// Use a URL with a .png extension to help content disposition logic
|
|
|
- imageURL := ts.URL + "/test.png"
|
|
|
- rw := s.execute(imageURL, nil, po)
|
|
|
+ res := s.execute("/test.png", nil, po)
|
|
|
|
|
|
- res := rw.Result()
|
|
|
s.Require().Equal(200, res.StatusCode)
|
|
|
s.Require().Contains(res.Header.Get(httpheaders.ContentDisposition), "custom_name.png")
|
|
|
s.Require().Contains(res.Header.Get(httpheaders.ContentDisposition), "attachment")
|
|
@@ -229,7 +202,7 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
type testCase struct {
|
|
|
name string
|
|
|
cacheControlPassthrough bool
|
|
|
- setupOriginHeaders func(http.ResponseWriter)
|
|
|
+ setupOriginHeaders func()
|
|
|
timestampOffset *time.Duration // nil for no timestamp, otherwise the offset from now
|
|
|
expectedStatusCode int
|
|
|
validate func(*testing.T, *http.Response)
|
|
@@ -250,8 +223,8 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "Passthrough",
|
|
|
cacheControlPassthrough: true,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {
|
|
|
- w.Header().Set(httpheaders.CacheControl, "max-age=3600, public")
|
|
|
+ setupOriginHeaders: func() {
|
|
|
+ s.testServer().SetHeaders(httpheaders.CacheControl, "max-age=3600, public")
|
|
|
},
|
|
|
timestampOffset: nil,
|
|
|
expectedStatusCode: 200,
|
|
@@ -263,8 +236,8 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "ExpiresPassthrough",
|
|
|
cacheControlPassthrough: true,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {
|
|
|
- w.Header().Set(httpheaders.Expires, time.Now().Add(oneHour).UTC().Format(http.TimeFormat))
|
|
|
+ setupOriginHeaders: func() {
|
|
|
+ s.testServer().SetHeaders(httpheaders.Expires, time.Now().Add(oneHour).UTC().Format(http.TimeFormat))
|
|
|
},
|
|
|
timestampOffset: nil,
|
|
|
expectedStatusCode: 200,
|
|
@@ -278,8 +251,8 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "PassthroughDisabled",
|
|
|
cacheControlPassthrough: false,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {
|
|
|
- w.Header().Set(httpheaders.CacheControl, "max-age=3600, public")
|
|
|
+ setupOriginHeaders: func() {
|
|
|
+ s.testServer().SetHeaders(httpheaders.CacheControl, "max-age=3600, public")
|
|
|
},
|
|
|
timestampOffset: nil,
|
|
|
expectedStatusCode: 200,
|
|
@@ -291,7 +264,6 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "WithProcessingOptionsExpires",
|
|
|
cacheControlPassthrough: false,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {}, // No origin headers
|
|
|
timestampOffset: &oneHour,
|
|
|
expectedStatusCode: 200,
|
|
|
validate: func(t *testing.T, res *http.Response) {
|
|
@@ -303,9 +275,9 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "ProcessingOptionsOverridesOrigin",
|
|
|
cacheControlPassthrough: true,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {
|
|
|
+ setupOriginHeaders: func() {
|
|
|
// Origin has a longer cache time
|
|
|
- w.Header().Set(httpheaders.CacheControl, "max-age=7200, public")
|
|
|
+ s.testServer().SetHeaders(httpheaders.CacheControl, "max-age=7200, public")
|
|
|
},
|
|
|
timestampOffset: &thirtyMinutes,
|
|
|
expectedStatusCode: 200,
|
|
@@ -318,10 +290,10 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "BothHeadersPassthroughEnabled",
|
|
|
cacheControlPassthrough: true,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {
|
|
|
+ setupOriginHeaders: func() {
|
|
|
// Origin has both Cache-Control and Expires headers
|
|
|
- w.Header().Set(httpheaders.CacheControl, "max-age=1800, public")
|
|
|
- w.Header().Set(httpheaders.Expires, time.Now().Add(oneHour).UTC().Format(http.TimeFormat))
|
|
|
+ s.testServer().SetHeaders(httpheaders.CacheControl, "max-age=1800, public")
|
|
|
+ s.testServer().SetHeaders(httpheaders.Expires, time.Now().Add(oneHour).UTC().Format(http.TimeFormat))
|
|
|
},
|
|
|
timestampOffset: nil,
|
|
|
expectedStatusCode: 200,
|
|
@@ -336,10 +308,10 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "ProcessingOptionsOverridesBothOriginHeaders",
|
|
|
cacheControlPassthrough: true,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {
|
|
|
+ setupOriginHeaders: func() {
|
|
|
// Origin has both Cache-Control and Expires headers with longer cache times
|
|
|
- w.Header().Set(httpheaders.CacheControl, "max-age=7200, public")
|
|
|
- w.Header().Set(httpheaders.Expires, time.Now().Add(twoHours).UTC().Format(http.TimeFormat))
|
|
|
+ s.testServer().SetHeaders(httpheaders.CacheControl, "max-age=7200, public")
|
|
|
+ s.testServer().SetHeaders(httpheaders.Expires, time.Now().Add(twoHours).UTC().Format(http.TimeFormat))
|
|
|
},
|
|
|
timestampOffset: &fortyFiveMinutes, // Shorter than origin headers
|
|
|
expectedStatusCode: 200,
|
|
@@ -352,7 +324,6 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
{
|
|
|
name: "NoOriginHeaders",
|
|
|
cacheControlPassthrough: false,
|
|
|
- setupOriginHeaders: func(w http.ResponseWriter) {}, // Origin has no cache headers
|
|
|
timestampOffset: nil,
|
|
|
expectedStatusCode: 200,
|
|
|
validate: func(t *testing.T, res *http.Response) {
|
|
@@ -363,15 +334,13 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
s.Run(tc.name, func() {
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
+
|
|
|
+ if tc.setupOriginHeaders != nil {
|
|
|
+ tc.setupOriginHeaders()
|
|
|
+ }
|
|
|
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- tc.setupOriginHeaders(w)
|
|
|
- w.Header().Set(httpheaders.ContentType, "image/png")
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().SetHeaders(httpheaders.ContentType, "image/png").SetBody(data)
|
|
|
|
|
|
s.rwConf().CacheControlPassthrough = tc.cacheControlPassthrough
|
|
|
s.rwConf().DefaultTTL = 4242
|
|
@@ -383,9 +352,7 @@ func (s *HandlerTestSuite) TestHandlerCacheControl() {
|
|
|
po.Expires = &expires
|
|
|
}
|
|
|
|
|
|
- rw := s.execute(ts.URL, nil, po)
|
|
|
-
|
|
|
- res := rw.Result()
|
|
|
+ res := s.execute("", nil, po)
|
|
|
s.Require().Equal(tc.expectedStatusCode, res.StatusCode)
|
|
|
tc.validate(s.T(), res)
|
|
|
})
|
|
@@ -405,85 +372,64 @@ func (s *HandlerTestSuite) maxAgeValue(res *http.Response) time.Duration {
|
|
|
|
|
|
// TestHandlerSecurityHeaders tests the security headers set by the streaming service.
|
|
|
func (s *HandlerTestSuite) TestHandlerSecurityHeaders() {
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- w.Header().Set(httpheaders.ContentType, "image/png")
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().SetHeaders(httpheaders.ContentType, "image/png").SetBody(data)
|
|
|
|
|
|
- rw := s.execute(ts.URL, nil, &options.ProcessingOptions{})
|
|
|
+ res := s.execute("", nil, &options.ProcessingOptions{})
|
|
|
|
|
|
- res := rw.Result()
|
|
|
- s.Require().Equal(200, res.StatusCode)
|
|
|
+ s.Require().Equal(http.StatusOK, res.StatusCode)
|
|
|
s.Require().Equal("script-src 'none'", res.Header.Get(httpheaders.ContentSecurityPolicy))
|
|
|
}
|
|
|
|
|
|
// TestHandlerErrorResponse tests the error responses from the streaming service.
|
|
|
func (s *HandlerTestSuite) TestHandlerErrorResponse() {
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- w.WriteHeader(404)
|
|
|
- w.Write([]byte("Not Found"))
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().SetStatusCode(http.StatusNotFound).SetBody([]byte("Not Found"))
|
|
|
|
|
|
- rw := s.execute(ts.URL, nil, &options.ProcessingOptions{})
|
|
|
+ res := s.execute("", nil, &options.ProcessingOptions{})
|
|
|
|
|
|
- res := rw.Result()
|
|
|
- s.Require().Equal(404, res.StatusCode)
|
|
|
+ s.Require().Equal(http.StatusNotFound, res.StatusCode)
|
|
|
}
|
|
|
|
|
|
// TestHandlerCookiePassthrough tests the cookie passthrough behavior of the streaming service.
|
|
|
func (s *HandlerTestSuite) TestHandlerCookiePassthrough() {
|
|
|
s.config().CookiePassthrough = true
|
|
|
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- // Verify cookies are passed through
|
|
|
- cookie, cerr := r.Cookie("test_cookie")
|
|
|
- if cerr == nil {
|
|
|
- s.Equal("test_value", cookie.Value)
|
|
|
- }
|
|
|
-
|
|
|
- w.Header().Set(httpheaders.ContentType, "image/png")
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().
|
|
|
+ SetHeaders(httpheaders.Cookie, "test_cookie=test_value").
|
|
|
+ SetHook(func(r *http.Request, rw http.ResponseWriter) {
|
|
|
+ // Verify cookies are passed through
|
|
|
+ cookie, cerr := r.Cookie("test_cookie")
|
|
|
+ if cerr == nil {
|
|
|
+ s.Equal("test_value", cookie.Value)
|
|
|
+ }
|
|
|
+ }).SetBody(data)
|
|
|
|
|
|
h := make(http.Header)
|
|
|
h.Set(httpheaders.Cookie, "test_cookie=test_value")
|
|
|
|
|
|
- rw := s.execute(ts.URL, h, &options.ProcessingOptions{})
|
|
|
+ res := s.execute("", h, &options.ProcessingOptions{})
|
|
|
|
|
|
- res := rw.Result()
|
|
|
s.Require().Equal(200, res.StatusCode)
|
|
|
}
|
|
|
|
|
|
// TestHandlerCanonicalHeader tests that the canonical header is set correctly
|
|
|
func (s *HandlerTestSuite) TestHandlerCanonicalHeader() {
|
|
|
- data := s.readTestFile("test1.png")
|
|
|
+ data := s.testData.Read("test1.png")
|
|
|
|
|
|
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
- w.Header().Set(httpheaders.ContentType, "image/png")
|
|
|
- w.WriteHeader(200)
|
|
|
- w.Write(data)
|
|
|
- }))
|
|
|
- defer ts.Close()
|
|
|
+ s.testServer().SetHeaders(httpheaders.ContentType, "image/png").SetBody(data)
|
|
|
|
|
|
for _, sc := range []bool{true, false} {
|
|
|
s.rwConf().SetCanonicalHeader = sc
|
|
|
|
|
|
- rw := s.execute(ts.URL, nil, &options.ProcessingOptions{})
|
|
|
+ res := s.execute("", nil, &options.ProcessingOptions{})
|
|
|
|
|
|
- res := rw.Result()
|
|
|
s.Require().Equal(200, res.StatusCode)
|
|
|
|
|
|
if sc {
|
|
|
- s.Require().Contains(res.Header.Get(httpheaders.Link), fmt.Sprintf(`<%s>; rel="canonical"`, ts.URL))
|
|
|
+ s.Require().Contains(res.Header.Get(httpheaders.Link), fmt.Sprintf(`<%s>; rel="canonical"`, s.testServer().URL()))
|
|
|
} else {
|
|
|
s.Require().Empty(res.Header.Get(httpheaders.Link))
|
|
|
}
|