processing_handler_test.go 17 KB

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