Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
528 lines
15 KiB
Go
528 lines
15 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package imageproxy
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/httpservice"
|
|
"github.com/mattermost/mattermost/server/v8/channels/utils/testutils"
|
|
)
|
|
|
|
func makeTestLocalProxy() *ImageProxy {
|
|
configService := &testutils.StaticConfigService{
|
|
Cfg: &model.Config{
|
|
ServiceSettings: model.ServiceSettings{
|
|
SiteURL: new("https://mattermost.example.com"),
|
|
AllowedUntrustedInternalConnections: new("127.0.0.1"),
|
|
},
|
|
ImageProxySettings: model.ImageProxySettings{
|
|
Enable: new(true),
|
|
ImageProxyType: model.NewPointer(model.ImageProxyTypeLocal),
|
|
},
|
|
},
|
|
}
|
|
|
|
return MakeImageProxy(configService, httpservice.MakeHTTPService(configService), nil)
|
|
}
|
|
|
|
func TestLocalBackend_GetImage(t *testing.T) {
|
|
t.Run("image", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Cache-Control", "max-age=2592000, private")
|
|
w.Header().Set("Content-Type", "image/png")
|
|
w.Header().Set("Content-Length", "10")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("1111111111"))
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, _ := http.NewRequest(http.MethodGet, "", nil)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
assert.Equal(t, "max-age=2592000, private", resp.Header.Get("Cache-Control"))
|
|
assert.Equal(t, "10", resp.Header.Get("Content-Length"))
|
|
|
|
respBody, _ := io.ReadAll(resp.Body)
|
|
assert.Equal(t, []byte("1111111111"), respBody)
|
|
})
|
|
|
|
t.Run("not an image", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotAcceptable)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, _ := http.NewRequest(http.MethodGet, "", nil)
|
|
proxy.GetImage(recorder, request, mock.URL+"/file.pdf")
|
|
resp := recorder.Result()
|
|
|
|
require.Equal(t, http.StatusNotAcceptable, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("not an image, but remote server ignores accept header", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Cache-Control", "max-age=2592000, private")
|
|
w.Header().Set("Content-Type", "application/pdf")
|
|
w.Header().Set("Content-Length", "10")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("1111111111"))
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, _ := http.NewRequest(http.MethodGet, "", nil)
|
|
proxy.GetImage(recorder, request, mock.URL+"/file.pdf")
|
|
resp := recorder.Result()
|
|
|
|
require.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("not found", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, _ := http.NewRequest(http.MethodGet, "", nil)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
require.Equal(t, http.StatusNotFound, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("other server error", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, _ := http.NewRequest(http.MethodGet, "", nil)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
require.Equal(t, http.StatusInternalServerError, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("timeout", func(t *testing.T) {
|
|
wait := make(chan bool, 1)
|
|
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
<-wait
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
// Modify the timeout to be much shorter than the default 30 seconds
|
|
proxy.backend.(*LocalBackend).client.Timeout = time.Millisecond
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, _ := http.NewRequest(http.MethodGet, "", nil)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
require.Equal(t, http.StatusGatewayTimeout, resp.StatusCode)
|
|
|
|
wait <- true
|
|
})
|
|
|
|
t.Run("unsupported SVG content type", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Cache-Control", "max-age=2592000, private")
|
|
w.Header().Set("Content-Type", "image/svg+xml")
|
|
w.Header().Set("Content-Length", "10")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("1111111111"))
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, err := http.NewRequest(http.MethodGet, "", nil)
|
|
require.NoError(t, err)
|
|
proxy.GetImage(recorder, request, mock.URL+"/test.svg")
|
|
resp := recorder.Result()
|
|
|
|
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("SVG body with image/png content type", func(t *testing.T) {
|
|
body := []byte(`<svg xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100"/></svg>`)
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(body)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, err := http.NewRequest(http.MethodGet, "", nil)
|
|
require.NoError(t, err)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("XML-based SVG with image/png content type", func(t *testing.T) {
|
|
body := []byte(`<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"><rect/></svg>`)
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(body)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, err := http.NewRequest(http.MethodGet, "", nil)
|
|
require.NoError(t, err)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("UTF-16 LE BOM SVG with image/png content type", func(t *testing.T) {
|
|
// Build a UTF-16 LE payload with BOM: 0xFF 0xFE followed by each ASCII
|
|
// character of the SVG tag as a two-byte little-endian code unit.
|
|
svgASCII := `<svg xmlns="http://www.w3.org/2000/svg"><rect/></svg>`
|
|
body := []byte{0xFF, 0xFE} // UTF-16 LE BOM
|
|
for _, c := range svgASCII {
|
|
body = append(body, byte(c), 0x00)
|
|
}
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(body)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, err := http.NewRequest(http.MethodGet, "", nil)
|
|
require.NoError(t, err)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("UTF-16 BE BOM SVG with image/png content type", func(t *testing.T) {
|
|
// Build a UTF-16 BE payload with BOM: 0xFE 0xFF followed by each ASCII
|
|
// character as a two-byte big-endian code unit.
|
|
svgASCII := `<svg xmlns="http://www.w3.org/2000/svg"><rect/></svg>`
|
|
body := []byte{0xFE, 0xFF} // UTF-16 BE BOM
|
|
for _, c := range svgASCII {
|
|
body = append(body, 0x00, byte(c))
|
|
}
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(body)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, err := http.NewRequest(http.MethodGet, "", nil)
|
|
require.NoError(t, err)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("SVG body with leading whitespace prefix", func(t *testing.T) {
|
|
prefix := bytes.Repeat([]byte(" "), 600)
|
|
body := append(prefix, []byte(`<svg xmlns="http://www.w3.org/2000/svg"><rect/></svg>`)...)
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(body)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, err := http.NewRequest(http.MethodGet, "", nil)
|
|
require.NoError(t, err)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
|
|
})
|
|
|
|
t.Run("Redirect", func(t *testing.T) {
|
|
var mock *httptest.Server
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch r.URL.Path {
|
|
case "/image.png":
|
|
w.Header().Set("Location", mock.URL+"/image2.png")
|
|
w.WriteHeader(http.StatusMovedPermanently)
|
|
case "/image2.png":
|
|
w.Header().Set("Cache-Control", "max-age=2592000, private")
|
|
w.Header().Set("Content-Type", "image/png")
|
|
w.Header().Set("Content-Length", "10")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("1111111111"))
|
|
}
|
|
})
|
|
|
|
mock = httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
recorder := httptest.NewRecorder()
|
|
request, _ := http.NewRequest(http.MethodGet, "", nil)
|
|
proxy.GetImage(recorder, request, mock.URL+"/image.png")
|
|
resp := recorder.Result()
|
|
|
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
|
assert.Equal(t, "10", resp.Header.Get("Content-Length"))
|
|
})
|
|
}
|
|
|
|
func TestLocalBackend_GetImageDirect(t *testing.T) {
|
|
t.Run("image", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Cache-Control", "max-age=2592000, private")
|
|
w.Header().Set("Content-Type", "image/png")
|
|
w.Header().Set("Content-Length", "10")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("1111111111"))
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "image/png", contentType)
|
|
|
|
respBody, _ := io.ReadAll(body)
|
|
assert.Equal(t, []byte("1111111111"), respBody)
|
|
})
|
|
|
|
t.Run("not an image", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotAcceptable)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/file.pdf")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "", contentType)
|
|
assert.Equal(t, ErrLocalRequestFailed, err)
|
|
assert.Nil(t, body)
|
|
})
|
|
|
|
t.Run("not an image, but remote server ignores accept header", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Cache-Control", "max-age=2592000, private")
|
|
w.Header().Set("Content-Type", "application/pdf")
|
|
w.Header().Set("Content-Length", "10")
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("1111111111"))
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/file.pdf")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "", contentType)
|
|
assert.Equal(t, ErrLocalRequestFailed, err)
|
|
assert.Nil(t, body)
|
|
})
|
|
|
|
t.Run("not found", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "", contentType)
|
|
assert.Equal(t, ErrLocalRequestFailed, err)
|
|
assert.Nil(t, body)
|
|
})
|
|
|
|
t.Run("other server error", func(t *testing.T) {
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "", contentType)
|
|
assert.Equal(t, ErrLocalRequestFailed, err)
|
|
assert.Nil(t, body)
|
|
})
|
|
|
|
t.Run("timeout", func(t *testing.T) {
|
|
wait := make(chan bool, 1)
|
|
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
<-wait
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
// Modify the timeout to be much shorter than the default 30 seconds
|
|
proxy.backend.(*LocalBackend).client.Timeout = time.Millisecond
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "", contentType)
|
|
assert.Equal(t, ErrLocalRequestFailed, err)
|
|
assert.Nil(t, body)
|
|
|
|
wait <- true
|
|
})
|
|
|
|
t.Run("image exceeds max size", func(t *testing.T) {
|
|
originalMaxImageSize := maxImageSize
|
|
maxImageSize = 10
|
|
defer func() { maxImageSize = originalMaxImageSize }()
|
|
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(bytes.Repeat([]byte("1"), int(maxImageSize)+1))
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
|
|
|
|
assert.Error(t, err)
|
|
assert.Equal(t, ErrImageTooLarge, err)
|
|
assert.Equal(t, "", contentType)
|
|
assert.Nil(t, body)
|
|
})
|
|
|
|
t.Run("image within max size is unaffected", func(t *testing.T) {
|
|
originalMaxImageSize := maxImageSize
|
|
maxImageSize = 10
|
|
defer func() { maxImageSize = originalMaxImageSize }()
|
|
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "image/png")
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write(bytes.Repeat([]byte("1"), int(maxImageSize)))
|
|
})
|
|
|
|
mock := httptest.NewServer(handler)
|
|
defer mock.Close()
|
|
|
|
proxy := makeTestLocalProxy()
|
|
|
|
body, contentType, err := proxy.GetImageDirect(mock.URL + "/image.png")
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "image/png", contentType)
|
|
|
|
respBody, _ := io.ReadAll(body)
|
|
assert.Equal(t, bytes.Repeat([]byte("1"), int(maxImageSize)), respBody)
|
|
})
|
|
}
|