processing_options_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. package main
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "regexp"
  9. "testing"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/stretchr/testify/require"
  12. "github.com/stretchr/testify/suite"
  13. )
  14. type ProcessingOptionsTestSuite struct{ MainTestSuite }
  15. func (s *ProcessingOptionsTestSuite) getRequest(uri string) *http.Request {
  16. return &http.Request{Method: "GET", RequestURI: uri, Header: make(http.Header)}
  17. }
  18. func (s *ProcessingOptionsTestSuite) TestParseBase64URL() {
  19. imageURL := "http://images.dev/lorem/ipsum.jpg?param=value"
  20. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/%s.png", base64.RawURLEncoding.EncodeToString([]byte(imageURL))))
  21. ctx, err := parsePath(context.Background(), req)
  22. require.Nil(s.T(), err)
  23. assert.Equal(s.T(), imageURL, getImageURL(ctx))
  24. assert.Equal(s.T(), imageTypePNG, getProcessingOptions(ctx).Format)
  25. }
  26. func (s *ProcessingOptionsTestSuite) TestParseBase64URLWithoutExtension() {
  27. imageURL := "http://images.dev/lorem/ipsum.jpg?param=value"
  28. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/%s", base64.RawURLEncoding.EncodeToString([]byte(imageURL))))
  29. ctx, err := parsePath(context.Background(), req)
  30. require.Nil(s.T(), err)
  31. assert.Equal(s.T(), imageURL, getImageURL(ctx))
  32. assert.Equal(s.T(), imageTypeUnknown, getProcessingOptions(ctx).Format)
  33. }
  34. func (s *ProcessingOptionsTestSuite) TestParseBase64URLWithBase() {
  35. conf.BaseURL = "http://images.dev/"
  36. imageURL := "lorem/ipsum.jpg?param=value"
  37. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/%s.png", base64.RawURLEncoding.EncodeToString([]byte(imageURL))))
  38. ctx, err := parsePath(context.Background(), req)
  39. require.Nil(s.T(), err)
  40. assert.Equal(s.T(), fmt.Sprintf("%s%s", conf.BaseURL, imageURL), getImageURL(ctx))
  41. assert.Equal(s.T(), imageTypePNG, getProcessingOptions(ctx).Format)
  42. }
  43. func (s *ProcessingOptionsTestSuite) TestParsePlainURL() {
  44. imageURL := "http://images.dev/lorem/ipsum.jpg"
  45. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/plain/%s@png", imageURL))
  46. ctx, err := parsePath(context.Background(), req)
  47. require.Nil(s.T(), err)
  48. assert.Equal(s.T(), imageURL, getImageURL(ctx))
  49. assert.Equal(s.T(), imageTypePNG, getProcessingOptions(ctx).Format)
  50. }
  51. func (s *ProcessingOptionsTestSuite) TestParsePlainURLWithoutExtension() {
  52. imageURL := "http://images.dev/lorem/ipsum.jpg"
  53. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/plain/%s", imageURL))
  54. ctx, err := parsePath(context.Background(), req)
  55. require.Nil(s.T(), err)
  56. assert.Equal(s.T(), imageURL, getImageURL(ctx))
  57. assert.Equal(s.T(), imageTypeUnknown, getProcessingOptions(ctx).Format)
  58. }
  59. func (s *ProcessingOptionsTestSuite) TestParsePlainURLEscaped() {
  60. imageURL := "http://images.dev/lorem/ipsum.jpg?param=value"
  61. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/plain/%s@png", url.PathEscape(imageURL)))
  62. ctx, err := parsePath(context.Background(), req)
  63. require.Nil(s.T(), err)
  64. assert.Equal(s.T(), imageURL, getImageURL(ctx))
  65. assert.Equal(s.T(), imageTypePNG, getProcessingOptions(ctx).Format)
  66. }
  67. func (s *ProcessingOptionsTestSuite) TestParsePlainURLWithBase() {
  68. conf.BaseURL = "http://images.dev/"
  69. imageURL := "lorem/ipsum.jpg"
  70. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/plain/%s@png", imageURL))
  71. ctx, err := parsePath(context.Background(), req)
  72. require.Nil(s.T(), err)
  73. assert.Equal(s.T(), fmt.Sprintf("%s%s", conf.BaseURL, imageURL), getImageURL(ctx))
  74. assert.Equal(s.T(), imageTypePNG, getProcessingOptions(ctx).Format)
  75. }
  76. func (s *ProcessingOptionsTestSuite) TestParsePlainURLEscapedWithBase() {
  77. conf.BaseURL = "http://images.dev/"
  78. imageURL := "lorem/ipsum.jpg?param=value"
  79. req := s.getRequest(fmt.Sprintf("/unsafe/size:100:100/plain/%s@png", url.PathEscape(imageURL)))
  80. ctx, err := parsePath(context.Background(), req)
  81. require.Nil(s.T(), err)
  82. assert.Equal(s.T(), fmt.Sprintf("%s%s", conf.BaseURL, imageURL), getImageURL(ctx))
  83. assert.Equal(s.T(), imageTypePNG, getProcessingOptions(ctx).Format)
  84. }
  85. func (s *ProcessingOptionsTestSuite) TestParseURLAllowedSources() {
  86. tt := []struct {
  87. name string
  88. allowedSources []string
  89. requestPath string
  90. expectedError bool
  91. }{
  92. {
  93. name: "match http URL without wildcard",
  94. allowedSources: []string{"local://", "http://images.dev/"},
  95. requestPath: "/unsafe/plain/http://images.dev/lorem/ipsum.jpg",
  96. expectedError: false,
  97. },
  98. {
  99. name: "match http URL with wildcard in hostname single level",
  100. allowedSources: []string{"local://", "http://*.mycdn.dev/"},
  101. requestPath: "/unsafe/plain/http://a-1.mycdn.dev/lorem/ipsum.jpg",
  102. expectedError: false,
  103. },
  104. {
  105. name: "match http URL with wildcard in hostname multiple levels",
  106. allowedSources: []string{"local://", "http://*.mycdn.dev/"},
  107. requestPath: "/unsafe/plain/http://a-1.b-2.mycdn.dev/lorem/ipsum.jpg",
  108. expectedError: false,
  109. },
  110. {
  111. name: "no match s3 URL with allowed local and http URLs",
  112. allowedSources: []string{"local://", "http://images.dev/"},
  113. requestPath: "/unsafe/plain/s3://images/lorem/ipsum.jpg",
  114. expectedError: true,
  115. },
  116. {
  117. name: "no match http URL with wildcard in hostname including slash",
  118. allowedSources: []string{"local://", "http://*.mycdn.dev/"},
  119. requestPath: "/unsafe/plain/http://other.dev/.mycdn.dev/lorem/ipsum.jpg",
  120. expectedError: true,
  121. },
  122. }
  123. for _, tc := range tt {
  124. s.T().Run(tc.name, func(t *testing.T) {
  125. exps := make([]*regexp.Regexp, len(tc.allowedSources))
  126. for i, pattern := range tc.allowedSources {
  127. exps[i] = regexpFromPattern(pattern)
  128. }
  129. conf.AllowedSources = exps
  130. req := s.getRequest(tc.requestPath)
  131. _, err := parsePath(context.Background(), req)
  132. if tc.expectedError {
  133. require.Error(t, err)
  134. } else {
  135. require.NoError(t, err)
  136. }
  137. })
  138. }
  139. }
  140. func (s *ProcessingOptionsTestSuite) TestParsePathBasic() {
  141. req := s.getRequest("/unsafe/fill/100/200/noea/1/plain/http://images.dev/lorem/ipsum.jpg@png")
  142. ctx, err := parsePath(context.Background(), req)
  143. require.Nil(s.T(), err)
  144. po := getProcessingOptions(ctx)
  145. assert.Equal(s.T(), resizeFill, po.ResizingType)
  146. assert.Equal(s.T(), 100, po.Width)
  147. assert.Equal(s.T(), 200, po.Height)
  148. assert.Equal(s.T(), gravityNorthEast, po.Gravity.Type)
  149. assert.True(s.T(), po.Enlarge)
  150. assert.Equal(s.T(), imageTypePNG, po.Format)
  151. }
  152. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedFormat() {
  153. req := s.getRequest("/unsafe/format:webp/plain/http://images.dev/lorem/ipsum.jpg")
  154. ctx, err := parsePath(context.Background(), req)
  155. require.Nil(s.T(), err)
  156. po := getProcessingOptions(ctx)
  157. assert.Equal(s.T(), imageTypeWEBP, po.Format)
  158. }
  159. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedResize() {
  160. req := s.getRequest("/unsafe/resize:fill:100:200:1/plain/http://images.dev/lorem/ipsum.jpg")
  161. ctx, err := parsePath(context.Background(), req)
  162. require.Nil(s.T(), err)
  163. po := getProcessingOptions(ctx)
  164. assert.Equal(s.T(), resizeFill, po.ResizingType)
  165. assert.Equal(s.T(), 100, po.Width)
  166. assert.Equal(s.T(), 200, po.Height)
  167. assert.True(s.T(), po.Enlarge)
  168. }
  169. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedResizingType() {
  170. req := s.getRequest("/unsafe/resizing_type:fill/plain/http://images.dev/lorem/ipsum.jpg")
  171. ctx, err := parsePath(context.Background(), req)
  172. require.Nil(s.T(), err)
  173. po := getProcessingOptions(ctx)
  174. assert.Equal(s.T(), resizeFill, po.ResizingType)
  175. }
  176. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedSize() {
  177. req := s.getRequest("/unsafe/size:100:200:1/plain/http://images.dev/lorem/ipsum.jpg")
  178. ctx, err := parsePath(context.Background(), req)
  179. require.Nil(s.T(), err)
  180. po := getProcessingOptions(ctx)
  181. assert.Equal(s.T(), 100, po.Width)
  182. assert.Equal(s.T(), 200, po.Height)
  183. assert.True(s.T(), po.Enlarge)
  184. }
  185. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedWidth() {
  186. req := s.getRequest("/unsafe/width:100/plain/http://images.dev/lorem/ipsum.jpg")
  187. ctx, err := parsePath(context.Background(), req)
  188. require.Nil(s.T(), err)
  189. po := getProcessingOptions(ctx)
  190. assert.Equal(s.T(), 100, po.Width)
  191. }
  192. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedHeight() {
  193. req := s.getRequest("/unsafe/height:100/plain/http://images.dev/lorem/ipsum.jpg")
  194. ctx, err := parsePath(context.Background(), req)
  195. require.Nil(s.T(), err)
  196. po := getProcessingOptions(ctx)
  197. assert.Equal(s.T(), 100, po.Height)
  198. }
  199. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedEnlarge() {
  200. req := s.getRequest("/unsafe/enlarge:1/plain/http://images.dev/lorem/ipsum.jpg")
  201. ctx, err := parsePath(context.Background(), req)
  202. require.Nil(s.T(), err)
  203. po := getProcessingOptions(ctx)
  204. assert.True(s.T(), po.Enlarge)
  205. }
  206. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedExtend() {
  207. req := s.getRequest("/unsafe/extend:1:so:10:20/plain/http://images.dev/lorem/ipsum.jpg")
  208. ctx, err := parsePath(context.Background(), req)
  209. require.Nil(s.T(), err)
  210. po := getProcessingOptions(ctx)
  211. assert.Equal(s.T(), true, po.Extend.Enabled)
  212. assert.Equal(s.T(), gravitySouth, po.Extend.Gravity.Type)
  213. assert.Equal(s.T(), 10.0, po.Extend.Gravity.X)
  214. assert.Equal(s.T(), 20.0, po.Extend.Gravity.Y)
  215. }
  216. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedGravity() {
  217. req := s.getRequest("/unsafe/gravity:soea/plain/http://images.dev/lorem/ipsum.jpg")
  218. ctx, err := parsePath(context.Background(), req)
  219. require.Nil(s.T(), err)
  220. po := getProcessingOptions(ctx)
  221. assert.Equal(s.T(), gravitySouthEast, po.Gravity.Type)
  222. }
  223. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedGravityFocuspoint() {
  224. req := s.getRequest("/unsafe/gravity:fp:0.5:0.75/plain/http://images.dev/lorem/ipsum.jpg")
  225. ctx, err := parsePath(context.Background(), req)
  226. require.Nil(s.T(), err)
  227. po := getProcessingOptions(ctx)
  228. assert.Equal(s.T(), gravityFocusPoint, po.Gravity.Type)
  229. assert.Equal(s.T(), 0.5, po.Gravity.X)
  230. assert.Equal(s.T(), 0.75, po.Gravity.Y)
  231. }
  232. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedQuality() {
  233. req := s.getRequest("/unsafe/quality:55/plain/http://images.dev/lorem/ipsum.jpg")
  234. ctx, err := parsePath(context.Background(), req)
  235. require.Nil(s.T(), err)
  236. po := getProcessingOptions(ctx)
  237. assert.Equal(s.T(), 55, po.Quality)
  238. }
  239. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedBackground() {
  240. req := s.getRequest("/unsafe/background:128:129:130/plain/http://images.dev/lorem/ipsum.jpg")
  241. ctx, err := parsePath(context.Background(), req)
  242. require.Nil(s.T(), err)
  243. po := getProcessingOptions(ctx)
  244. assert.True(s.T(), po.Flatten)
  245. assert.Equal(s.T(), uint8(128), po.Background.R)
  246. assert.Equal(s.T(), uint8(129), po.Background.G)
  247. assert.Equal(s.T(), uint8(130), po.Background.B)
  248. }
  249. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedBackgroundHex() {
  250. req := s.getRequest("/unsafe/background:ffddee/plain/http://images.dev/lorem/ipsum.jpg")
  251. ctx, err := parsePath(context.Background(), req)
  252. require.Nil(s.T(), err)
  253. po := getProcessingOptions(ctx)
  254. assert.True(s.T(), po.Flatten)
  255. assert.Equal(s.T(), uint8(0xff), po.Background.R)
  256. assert.Equal(s.T(), uint8(0xdd), po.Background.G)
  257. assert.Equal(s.T(), uint8(0xee), po.Background.B)
  258. }
  259. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedBackgroundDisable() {
  260. req := s.getRequest("/unsafe/background:fff/background:/plain/http://images.dev/lorem/ipsum.jpg")
  261. ctx, err := parsePath(context.Background(), req)
  262. require.Nil(s.T(), err)
  263. po := getProcessingOptions(ctx)
  264. assert.False(s.T(), po.Flatten)
  265. }
  266. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedBlur() {
  267. req := s.getRequest("/unsafe/blur:0.2/plain/http://images.dev/lorem/ipsum.jpg")
  268. ctx, err := parsePath(context.Background(), req)
  269. require.Nil(s.T(), err)
  270. po := getProcessingOptions(ctx)
  271. assert.Equal(s.T(), float32(0.2), po.Blur)
  272. }
  273. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedSharpen() {
  274. req := s.getRequest("/unsafe/sharpen:0.2/plain/http://images.dev/lorem/ipsum.jpg")
  275. ctx, err := parsePath(context.Background(), req)
  276. require.Nil(s.T(), err)
  277. po := getProcessingOptions(ctx)
  278. assert.Equal(s.T(), float32(0.2), po.Sharpen)
  279. }
  280. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedDpr() {
  281. req := s.getRequest("/unsafe/dpr:2/plain/http://images.dev/lorem/ipsum.jpg")
  282. ctx, err := parsePath(context.Background(), req)
  283. require.Nil(s.T(), err)
  284. po := getProcessingOptions(ctx)
  285. assert.Equal(s.T(), 2.0, po.Dpr)
  286. }
  287. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedWatermark() {
  288. req := s.getRequest("/unsafe/watermark:0.5:soea:10:20:0.6/plain/http://images.dev/lorem/ipsum.jpg")
  289. ctx, err := parsePath(context.Background(), req)
  290. require.Nil(s.T(), err)
  291. po := getProcessingOptions(ctx)
  292. assert.True(s.T(), po.Watermark.Enabled)
  293. assert.Equal(s.T(), gravitySouthEast, po.Watermark.Gravity.Type)
  294. assert.Equal(s.T(), 10.0, po.Watermark.Gravity.X)
  295. assert.Equal(s.T(), 20.0, po.Watermark.Gravity.Y)
  296. assert.Equal(s.T(), 0.6, po.Watermark.Scale)
  297. }
  298. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedPreset() {
  299. conf.Presets["test1"] = urlOptions{
  300. urlOption{Name: "resizing_type", Args: []string{"fill"}},
  301. }
  302. conf.Presets["test2"] = urlOptions{
  303. urlOption{Name: "blur", Args: []string{"0.2"}},
  304. urlOption{Name: "quality", Args: []string{"50"}},
  305. }
  306. req := s.getRequest("/unsafe/preset:test1:test2/plain/http://images.dev/lorem/ipsum.jpg")
  307. ctx, err := parsePath(context.Background(), req)
  308. require.Nil(s.T(), err)
  309. po := getProcessingOptions(ctx)
  310. assert.Equal(s.T(), resizeFill, po.ResizingType)
  311. assert.Equal(s.T(), float32(0.2), po.Blur)
  312. assert.Equal(s.T(), 50, po.Quality)
  313. }
  314. func (s *ProcessingOptionsTestSuite) TestParsePathPresetDefault() {
  315. conf.Presets["default"] = urlOptions{
  316. urlOption{Name: "resizing_type", Args: []string{"fill"}},
  317. urlOption{Name: "blur", Args: []string{"0.2"}},
  318. urlOption{Name: "quality", Args: []string{"50"}},
  319. }
  320. req := s.getRequest("/unsafe/quality:70/plain/http://images.dev/lorem/ipsum.jpg")
  321. ctx, err := parsePath(context.Background(), req)
  322. require.Nil(s.T(), err)
  323. po := getProcessingOptions(ctx)
  324. assert.Equal(s.T(), resizeFill, po.ResizingType)
  325. assert.Equal(s.T(), float32(0.2), po.Blur)
  326. assert.Equal(s.T(), 70, po.Quality)
  327. }
  328. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedPresetLoopDetection() {
  329. conf.Presets["test1"] = urlOptions{
  330. urlOption{Name: "resizing_type", Args: []string{"fill"}},
  331. }
  332. conf.Presets["test2"] = urlOptions{
  333. urlOption{Name: "blur", Args: []string{"0.2"}},
  334. urlOption{Name: "quality", Args: []string{"50"}},
  335. }
  336. req := s.getRequest("/unsafe/preset:test1:test2:test1/plain/http://images.dev/lorem/ipsum.jpg")
  337. ctx, err := parsePath(context.Background(), req)
  338. require.Nil(s.T(), err)
  339. po := getProcessingOptions(ctx)
  340. require.ElementsMatch(s.T(), po.UsedPresets, []string{"test1", "test2"})
  341. }
  342. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedCachebuster() {
  343. req := s.getRequest("/unsafe/cachebuster:123/plain/http://images.dev/lorem/ipsum.jpg")
  344. ctx, err := parsePath(context.Background(), req)
  345. require.Nil(s.T(), err)
  346. po := getProcessingOptions(ctx)
  347. assert.Equal(s.T(), "123", po.CacheBuster)
  348. }
  349. func (s *ProcessingOptionsTestSuite) TestParsePathAdvancedStripMetadata() {
  350. req := s.getRequest("/unsafe/strip_metadata:true/plain/http://images.dev/lorem/ipsum.jpg")
  351. ctx, err := parsePath(context.Background(), req)
  352. require.Nil(s.T(), err)
  353. po := getProcessingOptions(ctx)
  354. assert.True(s.T(), po.StripMetadata)
  355. }
  356. func (s *ProcessingOptionsTestSuite) TestParsePathWebpDetection() {
  357. conf.EnableWebpDetection = true
  358. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg")
  359. req.Header.Set("Accept", "image/webp")
  360. ctx, err := parsePath(context.Background(), req)
  361. require.Nil(s.T(), err)
  362. po := getProcessingOptions(ctx)
  363. assert.Equal(s.T(), true, po.PreferWebP)
  364. assert.Equal(s.T(), false, po.EnforceWebP)
  365. }
  366. func (s *ProcessingOptionsTestSuite) TestParsePathWebpEnforce() {
  367. conf.EnforceWebp = true
  368. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg@png")
  369. req.Header.Set("Accept", "image/webp")
  370. ctx, err := parsePath(context.Background(), req)
  371. require.Nil(s.T(), err)
  372. po := getProcessingOptions(ctx)
  373. assert.Equal(s.T(), true, po.PreferWebP)
  374. assert.Equal(s.T(), true, po.EnforceWebP)
  375. }
  376. func (s *ProcessingOptionsTestSuite) TestParsePathWidthHeader() {
  377. conf.EnableClientHints = true
  378. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg@png")
  379. req.Header.Set("Width", "100")
  380. ctx, err := parsePath(context.Background(), req)
  381. require.Nil(s.T(), err)
  382. po := getProcessingOptions(ctx)
  383. assert.Equal(s.T(), 100, po.Width)
  384. }
  385. func (s *ProcessingOptionsTestSuite) TestParsePathWidthHeaderDisabled() {
  386. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg@png")
  387. req.Header.Set("Width", "100")
  388. ctx, err := parsePath(context.Background(), req)
  389. require.Nil(s.T(), err)
  390. po := getProcessingOptions(ctx)
  391. assert.Equal(s.T(), 0, po.Width)
  392. }
  393. func (s *ProcessingOptionsTestSuite) TestParsePathWidthHeaderRedefine() {
  394. conf.EnableClientHints = true
  395. req := s.getRequest("/unsafe/width:150/plain/http://images.dev/lorem/ipsum.jpg@png")
  396. req.Header.Set("Width", "100")
  397. ctx, err := parsePath(context.Background(), req)
  398. require.Nil(s.T(), err)
  399. po := getProcessingOptions(ctx)
  400. assert.Equal(s.T(), 150, po.Width)
  401. }
  402. func (s *ProcessingOptionsTestSuite) TestParsePathViewportWidthHeader() {
  403. conf.EnableClientHints = true
  404. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg@png")
  405. req.Header.Set("Viewport-Width", "100")
  406. ctx, err := parsePath(context.Background(), req)
  407. require.Nil(s.T(), err)
  408. po := getProcessingOptions(ctx)
  409. assert.Equal(s.T(), 100, po.Width)
  410. }
  411. func (s *ProcessingOptionsTestSuite) TestParsePathViewportWidthHeaderDisabled() {
  412. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg@png")
  413. req.Header.Set("Viewport-Width", "100")
  414. ctx, err := parsePath(context.Background(), req)
  415. require.Nil(s.T(), err)
  416. po := getProcessingOptions(ctx)
  417. assert.Equal(s.T(), 0, po.Width)
  418. }
  419. func (s *ProcessingOptionsTestSuite) TestParsePathViewportWidthHeaderRedefine() {
  420. conf.EnableClientHints = true
  421. req := s.getRequest("/unsafe/width:150/plain/http://images.dev/lorem/ipsum.jpg@png")
  422. req.Header.Set("Viewport-Width", "100")
  423. ctx, err := parsePath(context.Background(), req)
  424. require.Nil(s.T(), err)
  425. po := getProcessingOptions(ctx)
  426. assert.Equal(s.T(), 150, po.Width)
  427. }
  428. func (s *ProcessingOptionsTestSuite) TestParsePathDprHeader() {
  429. conf.EnableClientHints = true
  430. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg@png")
  431. req.Header.Set("DPR", "2")
  432. ctx, err := parsePath(context.Background(), req)
  433. require.Nil(s.T(), err)
  434. po := getProcessingOptions(ctx)
  435. assert.Equal(s.T(), 2.0, po.Dpr)
  436. }
  437. func (s *ProcessingOptionsTestSuite) TestParsePathDprHeaderDisabled() {
  438. req := s.getRequest("/unsafe/plain/http://images.dev/lorem/ipsum.jpg@png")
  439. req.Header.Set("DPR", "2")
  440. ctx, err := parsePath(context.Background(), req)
  441. require.Nil(s.T(), err)
  442. po := getProcessingOptions(ctx)
  443. assert.Equal(s.T(), 1.0, po.Dpr)
  444. }
  445. func (s *ProcessingOptionsTestSuite) TestParsePathSigned() {
  446. conf.Keys = []securityKey{securityKey("test-key")}
  447. conf.Salts = []securityKey{securityKey("test-salt")}
  448. conf.AllowInsecure = false
  449. req := s.getRequest("/HcvNognEV1bW6f8zRqxNYuOkV0IUf1xloRb57CzbT4g/width:150/plain/http://images.dev/lorem/ipsum.jpg@png")
  450. _, err := parsePath(context.Background(), req)
  451. require.Nil(s.T(), err)
  452. }
  453. func (s *ProcessingOptionsTestSuite) TestParsePathSignedInvalid() {
  454. conf.Keys = []securityKey{securityKey("test-key")}
  455. conf.Salts = []securityKey{securityKey("test-salt")}
  456. conf.AllowInsecure = false
  457. req := s.getRequest("/unsafe/width:150/plain/http://images.dev/lorem/ipsum.jpg@png")
  458. _, err := parsePath(context.Background(), req)
  459. require.Error(s.T(), err)
  460. assert.Equal(s.T(), errInvalidSignature.Error(), err.Error())
  461. }
  462. func (s *ProcessingOptionsTestSuite) TestParsePathOnlyPresets() {
  463. conf.OnlyPresets = true
  464. conf.Presets["test1"] = urlOptions{
  465. urlOption{Name: "blur", Args: []string{"0.2"}},
  466. }
  467. conf.Presets["test2"] = urlOptions{
  468. urlOption{Name: "quality", Args: []string{"50"}},
  469. }
  470. req := s.getRequest("/unsafe/test1:test2/plain/http://images.dev/lorem/ipsum.jpg")
  471. ctx, err := parsePath(context.Background(), req)
  472. require.Nil(s.T(), err)
  473. po := getProcessingOptions(ctx)
  474. assert.Equal(s.T(), float32(0.2), po.Blur)
  475. assert.Equal(s.T(), 50, po.Quality)
  476. }
  477. func (s *ProcessingOptionsTestSuite) TestParseBase64URLOnlyPresets() {
  478. conf.OnlyPresets = true
  479. conf.Presets["test1"] = urlOptions{
  480. urlOption{Name: "blur", Args: []string{"0.2"}},
  481. }
  482. conf.Presets["test2"] = urlOptions{
  483. urlOption{Name: "quality", Args: []string{"50"}},
  484. }
  485. imageURL := "http://images.dev/lorem/ipsum.jpg?param=value"
  486. req := s.getRequest(fmt.Sprintf("/unsafe/test1:test2/%s.png", base64.RawURLEncoding.EncodeToString([]byte(imageURL))))
  487. ctx, err := parsePath(context.Background(), req)
  488. require.Nil(s.T(), err)
  489. po := getProcessingOptions(ctx)
  490. assert.Equal(s.T(), float32(0.2), po.Blur)
  491. assert.Equal(s.T(), 50, po.Quality)
  492. }
  493. func TestProcessingOptions(t *testing.T) {
  494. suite.Run(t, new(ProcessingOptionsTestSuite))
  495. }