processing_handler_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. package integration
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/http/httptest"
  6. "regexp"
  7. "testing"
  8. "time"
  9. "github.com/imgproxy/imgproxy/v3/config"
  10. "github.com/imgproxy/imgproxy/v3/config/configurators"
  11. "github.com/imgproxy/imgproxy/v3/fetcher"
  12. "github.com/imgproxy/imgproxy/v3/httpheaders"
  13. "github.com/imgproxy/imgproxy/v3/imagedata"
  14. "github.com/imgproxy/imgproxy/v3/imagetype"
  15. "github.com/imgproxy/imgproxy/v3/svg"
  16. "github.com/imgproxy/imgproxy/v3/testutil"
  17. "github.com/imgproxy/imgproxy/v3/vips"
  18. "github.com/stretchr/testify/suite"
  19. )
  20. // ProcessingHandlerTestSuite is a test suite for testing image processing handler
  21. type ProcessingHandlerTestSuite struct {
  22. Suite
  23. }
  24. func (s *ProcessingHandlerTestSuite) SetupTest() {
  25. config.Reset() // We reset config only at the start of each test
  26. s.Config().Fetcher.Transport.HTTP.AllowLoopbackSourceAddresses = true
  27. }
  28. func (s *ProcessingHandlerTestSuite) SetupSubTest() {
  29. // We use t.Run() a lot, so we need to reset lazy objects at the beginning of each subtest
  30. s.ResetLazyObjects()
  31. }
  32. func (s *ProcessingHandlerTestSuite) TestSignatureValidationFailure() {
  33. config.Keys = [][]byte{[]byte("test-key")}
  34. config.Salts = [][]byte{[]byte("test-salt")}
  35. tt := []struct {
  36. name string
  37. url string
  38. statusCode int
  39. }{
  40. {
  41. name: "NoSignature",
  42. url: "/unsafe/rs:fill:4:4/plain/local:///test1.png",
  43. statusCode: http.StatusForbidden,
  44. },
  45. {
  46. name: "BadSignature",
  47. url: "/bad-signature/rs:fill:4:4/plain/local:///test1.png",
  48. statusCode: http.StatusForbidden,
  49. },
  50. {
  51. name: "ValidSignature",
  52. url: "/My9d3xq_PYpVHsPrCyww0Kh1w5KZeZhIlWhsa4az1TI/rs:fill:4:4/plain/local:///test1.png",
  53. statusCode: http.StatusOK,
  54. },
  55. }
  56. for _, tc := range tt {
  57. s.Run(tc.name, func() {
  58. res := s.GET(tc.url)
  59. s.Require().Equal(tc.statusCode, res.StatusCode)
  60. })
  61. }
  62. }
  63. func (s *ProcessingHandlerTestSuite) TestSourceValidation() {
  64. imagedata.RedirectAllRequestsTo("local:///test1.png")
  65. defer imagedata.StopRedirectingRequests()
  66. tt := []struct {
  67. name string
  68. allowedSources []string
  69. requestPath string
  70. expectedError bool
  71. }{
  72. {
  73. name: "match http URL without wildcard",
  74. allowedSources: []string{"local://", "http://images.dev/"},
  75. requestPath: "/unsafe/plain/http://images.dev/lorem/ipsum.jpg",
  76. },
  77. {
  78. name: "match http URL with wildcard in hostname single level",
  79. allowedSources: []string{"local://", "http://*.mycdn.dev/"},
  80. requestPath: "/unsafe/plain/http://a-1.mycdn.dev/lorem/ipsum.jpg",
  81. },
  82. {
  83. name: "match http URL with wildcard in hostname multiple levels",
  84. allowedSources: []string{"local://", "http://*.mycdn.dev/"},
  85. requestPath: "/unsafe/plain/http://a-1.b-2.mycdn.dev/lorem/ipsum.jpg",
  86. },
  87. {
  88. name: "no match s3 URL with allowed local and http URLs",
  89. allowedSources: []string{"local://", "http://images.dev/"},
  90. requestPath: "/unsafe/plain/s3://images/lorem/ipsum.jpg",
  91. expectedError: true,
  92. },
  93. {
  94. name: "no match http URL with wildcard in hostname including slash",
  95. allowedSources: []string{"local://", "http://*.mycdn.dev/"},
  96. requestPath: "/unsafe/plain/http://other.dev/.mycdn.dev/lorem/ipsum.jpg",
  97. expectedError: true,
  98. },
  99. }
  100. for _, tc := range tt {
  101. s.Run(tc.name, func() {
  102. config.AllowedSources = make([]*regexp.Regexp, len(tc.allowedSources))
  103. for i, pattern := range tc.allowedSources {
  104. config.AllowedSources[i] = configurators.RegexpFromPattern(pattern)
  105. }
  106. res := s.GET(tc.requestPath)
  107. if tc.expectedError {
  108. s.Require().Equal(http.StatusNotFound, res.StatusCode)
  109. } else {
  110. s.Require().Equal(http.StatusOK, res.StatusCode)
  111. }
  112. })
  113. }
  114. }
  115. func (s *ProcessingHandlerTestSuite) TestSourceNetworkValidation() {
  116. data := s.TestData.Read("test1.png")
  117. server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  118. rw.WriteHeader(200)
  119. rw.Write(data)
  120. }))
  121. defer server.Close()
  122. url := fmt.Sprintf("/unsafe/rs:fill:4:4/plain/%s/test1.png", server.URL)
  123. // We wrap this in a subtest to reset s.router()
  124. s.Run("AllowLoopbackSourceAddressesTrue", func() {
  125. s.Config().Fetcher.Transport.HTTP.AllowLoopbackSourceAddresses = true
  126. res := s.GET(url)
  127. s.Require().Equal(http.StatusOK, res.StatusCode)
  128. })
  129. s.Run("AllowLoopbackSourceAddressesFalse", func() {
  130. s.Config().Fetcher.Transport.HTTP.AllowLoopbackSourceAddresses = false
  131. res := s.GET(url)
  132. s.Require().Equal(http.StatusNotFound, res.StatusCode)
  133. })
  134. }
  135. func (s *ProcessingHandlerTestSuite) TestSourceFormatNotSupported() {
  136. vips.DisableLoadSupport(imagetype.PNG)
  137. defer vips.ResetLoadSupport()
  138. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.png")
  139. s.Require().Equal(http.StatusUnprocessableEntity, res.StatusCode)
  140. }
  141. func (s *ProcessingHandlerTestSuite) TestResultingFormatNotSupported() {
  142. vips.DisableSaveSupport(imagetype.PNG)
  143. defer vips.ResetSaveSupport()
  144. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.png@png")
  145. s.Require().Equal(http.StatusUnprocessableEntity, res.StatusCode)
  146. }
  147. func (s *ProcessingHandlerTestSuite) TestSkipProcessingConfig() {
  148. s.Config().Options.SkipProcessingFormats = []imagetype.Type{imagetype.PNG}
  149. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.png")
  150. s.Require().Equal(http.StatusOK, res.StatusCode)
  151. s.Require().True(s.TestData.FileEqualsToReader("test1.png", res.Body))
  152. }
  153. func (s *ProcessingHandlerTestSuite) TestSkipProcessingPO() {
  154. res := s.GET("/unsafe/rs:fill:4:4/skp:png/plain/local:///test1.png")
  155. s.Require().Equal(http.StatusOK, res.StatusCode)
  156. s.Require().True(s.TestData.FileEqualsToReader("test1.png", res.Body))
  157. }
  158. func (s *ProcessingHandlerTestSuite) TestSkipProcessingSameFormat() {
  159. s.Config().Options.SkipProcessingFormats = []imagetype.Type{imagetype.PNG}
  160. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.png@png")
  161. s.Require().Equal(http.StatusOK, res.StatusCode)
  162. s.Require().True(s.TestData.FileEqualsToReader("test1.png", res.Body))
  163. }
  164. func (s *ProcessingHandlerTestSuite) TestSkipProcessingDifferentFormat() {
  165. s.Config().Options.SkipProcessingFormats = []imagetype.Type{imagetype.PNG}
  166. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.png@jpg")
  167. s.Require().Equal(http.StatusOK, res.StatusCode)
  168. s.Require().False(s.TestData.FileEqualsToReader("test1.png", res.Body))
  169. }
  170. func (s *ProcessingHandlerTestSuite) TestSkipProcessingSVG() {
  171. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.svg")
  172. s.Require().Equal(http.StatusOK, res.StatusCode)
  173. c := fetcher.NewDefaultConfig()
  174. f, err := fetcher.New(&c)
  175. s.Require().NoError(err)
  176. idf := imagedata.NewFactory(f)
  177. data, err := idf.NewFromBytes(s.TestData.Read("test1.svg"))
  178. s.Require().NoError(err)
  179. expected, err := svg.Sanitize(data)
  180. s.Require().NoError(err)
  181. s.Require().True(testutil.ReadersEqual(s.T(), expected.Reader(), res.Body))
  182. }
  183. func (s *ProcessingHandlerTestSuite) TestNotSkipProcessingSVGToJPG() {
  184. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.svg@jpg")
  185. s.Require().Equal(http.StatusOK, res.StatusCode)
  186. s.Require().False(s.TestData.FileEqualsToReader("test1.svg", res.Body))
  187. }
  188. func (s *ProcessingHandlerTestSuite) TestErrorSavingToSVG() {
  189. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.png@svg")
  190. s.Require().Equal(http.StatusUnprocessableEntity, res.StatusCode)
  191. }
  192. func (s *ProcessingHandlerTestSuite) TestCacheControlPassthroughCacheControl() {
  193. s.Config().Server.ResponseWriter.CacheControlPassthrough = true
  194. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  195. rw.Header().Set(httpheaders.CacheControl, "max-age=1234, public")
  196. rw.Header().Set(httpheaders.Expires, time.Now().Add(time.Hour).UTC().Format(http.TimeFormat))
  197. rw.WriteHeader(200)
  198. rw.Write(s.TestData.Read("test1.png"))
  199. }))
  200. defer ts.Close()
  201. res := s.GET("/unsafe/rs:fill:4:4/plain/" + ts.URL)
  202. s.Require().Equal(http.StatusOK, res.StatusCode)
  203. s.Require().Equal("max-age=1234, public", res.Header.Get(httpheaders.CacheControl))
  204. s.Require().Empty(res.Header.Get(httpheaders.Expires))
  205. }
  206. func (s *ProcessingHandlerTestSuite) TestCacheControlPassthroughExpires() {
  207. s.Config().Server.ResponseWriter.CacheControlPassthrough = true
  208. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  209. rw.Header().Set(httpheaders.Expires, time.Now().Add(1239*time.Second).UTC().Format(http.TimeFormat))
  210. rw.WriteHeader(200)
  211. rw.Write(s.TestData.Read("test1.png"))
  212. }))
  213. defer ts.Close()
  214. res := s.GET("/unsafe/rs:fill:4:4/plain/" + ts.URL)
  215. // Use regex to allow some delay
  216. s.Require().Regexp("max-age=123[0-9], public", res.Header.Get(httpheaders.CacheControl))
  217. s.Require().Empty(res.Header.Get(httpheaders.Expires))
  218. }
  219. func (s *ProcessingHandlerTestSuite) TestCacheControlPassthroughDisabled() {
  220. s.Config().Server.ResponseWriter.CacheControlPassthrough = false
  221. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  222. rw.Header().Set(httpheaders.CacheControl, "max-age=1234, public")
  223. rw.Header().Set(httpheaders.Expires, time.Now().Add(time.Hour).UTC().Format(http.TimeFormat))
  224. rw.WriteHeader(200)
  225. rw.Write(s.TestData.Read("test1.png"))
  226. }))
  227. defer ts.Close()
  228. res := s.GET("/unsafe/rs:fill:4:4/plain/" + ts.URL)
  229. s.Require().NotEqual("max-age=1234, public", res.Header.Get(httpheaders.CacheControl))
  230. s.Require().Empty(res.Header.Get(httpheaders.Expires))
  231. }
  232. func (s *ProcessingHandlerTestSuite) TestETagDisabled() {
  233. s.Config().Handlers.Processing.ETagEnabled = false
  234. res := s.GET("/unsafe/rs:fill:4:4/plain/local:///test1.png")
  235. s.Require().Equal(200, res.StatusCode)
  236. s.Require().Empty(res.Header.Get(httpheaders.Etag))
  237. }
  238. func (s *ProcessingHandlerTestSuite) TestETagDataMatch() {
  239. s.Config().Handlers.Processing.ETagEnabled = true
  240. etag := `"loremipsumdolor"`
  241. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  242. s.NotEmpty(r.Header.Get(httpheaders.IfNoneMatch))
  243. rw.Header().Set(httpheaders.Etag, etag)
  244. rw.WriteHeader(http.StatusNotModified)
  245. }))
  246. defer ts.Close()
  247. header := make(http.Header)
  248. header.Set(httpheaders.IfNoneMatch, etag)
  249. res := s.GET(fmt.Sprintf("/unsafe/plain/%s", ts.URL), header)
  250. s.Require().Equal(304, res.StatusCode)
  251. s.Require().Equal(etag, res.Header.Get(httpheaders.Etag))
  252. }
  253. func (s *ProcessingHandlerTestSuite) TestLastModifiedEnabled() {
  254. s.Config().Handlers.Processing.LastModifiedEnabled = true
  255. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  256. rw.Header().Set(httpheaders.LastModified, "Wed, 21 Oct 2015 07:28:00 GMT")
  257. rw.WriteHeader(200)
  258. rw.Write(s.TestData.Read("test1.png"))
  259. }))
  260. defer ts.Close()
  261. res := s.GET("/unsafe/rs:fill:4:4/plain/" + ts.URL)
  262. s.Require().Equal("Wed, 21 Oct 2015 07:28:00 GMT", res.Header.Get(httpheaders.LastModified))
  263. }
  264. func (s *ProcessingHandlerTestSuite) TestLastModifiedDisabled() {
  265. s.Config().Handlers.Processing.LastModifiedEnabled = false
  266. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  267. rw.Header().Set(httpheaders.LastModified, "Wed, 21 Oct 2015 07:28:00 GMT")
  268. rw.WriteHeader(200)
  269. rw.Write(s.TestData.Read("test1.png"))
  270. }))
  271. defer ts.Close()
  272. res := s.GET("/unsafe/rs:fill:4:4/plain/" + ts.URL)
  273. s.Require().Empty(res.Header.Get(httpheaders.LastModified))
  274. }
  275. func (s *ProcessingHandlerTestSuite) TestModifiedSinceReqExactMatchLastModifiedDisabled() {
  276. s.Config().Handlers.Processing.LastModifiedEnabled = false
  277. data := s.TestData.Read("test1.png")
  278. lastModified := "Wed, 21 Oct 2015 07:28:00 GMT"
  279. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  280. modifiedSince := r.Header.Get(httpheaders.IfModifiedSince)
  281. s.Empty(modifiedSince)
  282. rw.WriteHeader(200)
  283. rw.Write(data)
  284. }))
  285. defer ts.Close()
  286. header := make(http.Header)
  287. header.Set(httpheaders.IfModifiedSince, lastModified)
  288. res := s.GET(fmt.Sprintf("/unsafe/plain/%s", ts.URL), header)
  289. s.Require().Equal(200, res.StatusCode)
  290. }
  291. func (s *ProcessingHandlerTestSuite) TestModifiedSinceReqExactMatchLastModifiedEnabled() {
  292. s.Config().Handlers.Processing.LastModifiedEnabled = true
  293. lastModified := "Wed, 21 Oct 2015 07:28:00 GMT"
  294. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  295. modifiedSince := r.Header.Get(httpheaders.IfModifiedSince)
  296. s.Equal(lastModified, modifiedSince)
  297. rw.WriteHeader(304)
  298. }))
  299. defer ts.Close()
  300. header := make(http.Header)
  301. header.Set(httpheaders.IfModifiedSince, lastModified)
  302. res := s.GET(fmt.Sprintf("/unsafe/plain/%s", ts.URL), header)
  303. s.Require().Equal(304, res.StatusCode)
  304. }
  305. func (s *ProcessingHandlerTestSuite) TestModifiedSinceReqCompareMoreRecentLastModifiedDisabled() {
  306. data := s.TestData.Read("test1.png")
  307. s.Config().Handlers.Processing.LastModifiedEnabled = false
  308. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  309. modifiedSince := r.Header.Get(httpheaders.IfModifiedSince)
  310. s.Empty(modifiedSince)
  311. rw.WriteHeader(200)
  312. rw.Write(data)
  313. }))
  314. defer ts.Close()
  315. recentTimestamp := "Thu, 25 Feb 2021 01:45:00 GMT"
  316. header := make(http.Header)
  317. header.Set(httpheaders.IfModifiedSince, recentTimestamp)
  318. res := s.GET(fmt.Sprintf("/unsafe/plain/%s", ts.URL), header)
  319. s.Require().Equal(200, res.StatusCode)
  320. }
  321. func (s *ProcessingHandlerTestSuite) TestModifiedSinceReqCompareMoreRecentLastModifiedEnabled() {
  322. s.Config().Handlers.Processing.LastModifiedEnabled = true
  323. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  324. fileLastModified, _ := time.Parse(http.TimeFormat, "Wed, 21 Oct 2015 07:28:00 GMT")
  325. modifiedSince := r.Header.Get(httpheaders.IfModifiedSince)
  326. parsedModifiedSince, err := time.Parse(http.TimeFormat, modifiedSince)
  327. s.NoError(err)
  328. s.True(fileLastModified.Before(parsedModifiedSince))
  329. rw.WriteHeader(304)
  330. }))
  331. defer ts.Close()
  332. recentTimestamp := "Thu, 25 Feb 2021 01:45:00 GMT"
  333. header := make(http.Header)
  334. header.Set(httpheaders.IfModifiedSince, recentTimestamp)
  335. res := s.GET(fmt.Sprintf("/unsafe/plain/%s", ts.URL), header)
  336. s.Require().Equal(304, res.StatusCode)
  337. }
  338. func (s *ProcessingHandlerTestSuite) TestModifiedSinceReqCompareTooOldLastModifiedDisabled() {
  339. s.Config().Handlers.Processing.LastModifiedEnabled = false
  340. data := s.TestData.Read("test1.png")
  341. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  342. modifiedSince := r.Header.Get(httpheaders.IfModifiedSince)
  343. s.Empty(modifiedSince)
  344. rw.WriteHeader(200)
  345. rw.Write(data)
  346. }))
  347. defer ts.Close()
  348. oldTimestamp := "Tue, 01 Oct 2013 17:31:00 GMT"
  349. header := make(http.Header)
  350. header.Set(httpheaders.IfModifiedSince, oldTimestamp)
  351. res := s.GET(fmt.Sprintf("/unsafe/plain/%s", ts.URL), header)
  352. s.Require().Equal(200, res.StatusCode)
  353. }
  354. func (s *ProcessingHandlerTestSuite) TestModifiedSinceReqCompareTooOldLastModifiedEnabled() {
  355. s.Config().Handlers.Processing.LastModifiedEnabled = true
  356. data := s.TestData.Read("test1.png")
  357. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  358. fileLastModified, _ := time.Parse(http.TimeFormat, "Wed, 21 Oct 2015 07:28:00 GMT")
  359. modifiedSince := r.Header.Get(httpheaders.IfModifiedSince)
  360. parsedModifiedSince, err := time.Parse(http.TimeFormat, modifiedSince)
  361. s.NoError(err)
  362. s.True(fileLastModified.After(parsedModifiedSince))
  363. rw.WriteHeader(200)
  364. rw.Write(data)
  365. }))
  366. defer ts.Close()
  367. oldTimestamp := "Tue, 01 Oct 2013 17:31:00 GMT"
  368. header := make(http.Header)
  369. header.Set(httpheaders.IfModifiedSince, oldTimestamp)
  370. res := s.GET(fmt.Sprintf("/unsafe/plain/%s", ts.URL), header)
  371. s.Require().Equal(200, res.StatusCode)
  372. }
  373. func (s *ProcessingHandlerTestSuite) TestAlwaysRasterizeSvg() {
  374. config.AlwaysRasterizeSvg = true
  375. res := s.GET("/unsafe/rs:fill:40:40/plain/local:///test1.svg")
  376. s.Require().Equal(200, res.StatusCode)
  377. s.Require().Equal("image/png", res.Header.Get(httpheaders.ContentType))
  378. }
  379. func (s *ProcessingHandlerTestSuite) TestAlwaysRasterizeSvgWithEnforceAvif() {
  380. config.AlwaysRasterizeSvg = true
  381. s.Config().Options.EnforceWebp = true
  382. res := s.GET("/unsafe/plain/local:///test1.svg", http.Header{"Accept": []string{"image/webp"}})
  383. s.Require().Equal(200, res.StatusCode)
  384. s.Require().Equal("image/webp", res.Header.Get(httpheaders.ContentType))
  385. }
  386. func (s *ProcessingHandlerTestSuite) TestAlwaysRasterizeSvgDisabled() {
  387. config.AlwaysRasterizeSvg = false
  388. s.Config().Options.EnforceWebp = true
  389. res := s.GET("/unsafe/plain/local:///test1.svg")
  390. s.Require().Equal(200, res.StatusCode)
  391. s.Require().Equal("image/svg+xml", res.Header.Get(httpheaders.ContentType))
  392. }
  393. func (s *ProcessingHandlerTestSuite) TestAlwaysRasterizeSvgWithFormat() {
  394. config.AlwaysRasterizeSvg = true
  395. s.Config().Options.SkipProcessingFormats = []imagetype.Type{imagetype.SVG}
  396. res := s.GET("/unsafe/plain/local:///test1.svg@svg")
  397. s.Require().Equal(200, res.StatusCode)
  398. s.Require().Equal("image/svg+xml", res.Header.Get(httpheaders.ContentType))
  399. }
  400. func (s *ProcessingHandlerTestSuite) TestMaxSrcFileSizeGlobal() {
  401. s.Config().Security.DefaultOptions.MaxSrcFileSize = 1
  402. ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
  403. rw.WriteHeader(200)
  404. rw.Write(s.TestData.Read("test1.png"))
  405. }))
  406. defer ts.Close()
  407. res := s.GET("/unsafe/rs:fill:4:4/plain/" + ts.URL)
  408. s.Require().Equal(422, res.StatusCode)
  409. }
  410. func TestProcessingHandler(t *testing.T) {
  411. suite.Run(t, new(ProcessingHandlerTestSuite))
  412. }