processing_handler_test.go 17 KB

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