media_proxy_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package mediaproxy // import "miniflux.app/v2/internal/mediaproxy"
  4. import (
  5. "net/http"
  6. "os"
  7. "testing"
  8. "github.com/gorilla/mux"
  9. "miniflux.app/v2/internal/config"
  10. )
  11. func TestProxyFilterWithHttpDefault(t *testing.T) {
  12. os.Clearenv()
  13. os.Setenv("MEDIA_PROXY_MODE", "http-only")
  14. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  15. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  16. var err error
  17. parser := config.NewConfigParser()
  18. config.Opts, err = parser.ParseEnvironmentVariables()
  19. if err != nil {
  20. t.Fatalf(`Parsing failure: %v`, err)
  21. }
  22. r := mux.NewRouter()
  23. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  24. input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
  25. output := RewriteDocumentWithRelativeProxyURL(r, input)
  26. expected := `<p><img src="/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
  27. if expected != output {
  28. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  29. }
  30. }
  31. func TestProxyFilterWithHttpsDefault(t *testing.T) {
  32. os.Clearenv()
  33. os.Setenv("MEDIA_PROXY_MODE", "http-only")
  34. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  35. var err error
  36. parser := config.NewConfigParser()
  37. config.Opts, err = parser.ParseEnvironmentVariables()
  38. if err != nil {
  39. t.Fatalf(`Parsing failure: %v`, err)
  40. }
  41. r := mux.NewRouter()
  42. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  43. input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  44. output := RewriteDocumentWithRelativeProxyURL(r, input)
  45. expected := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  46. if expected != output {
  47. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  48. }
  49. }
  50. func TestProxyFilterWithHttpNever(t *testing.T) {
  51. os.Clearenv()
  52. os.Setenv("MEDIA_PROXY_MODE", "none")
  53. var err error
  54. parser := config.NewConfigParser()
  55. config.Opts, err = parser.ParseEnvironmentVariables()
  56. if err != nil {
  57. t.Fatalf(`Parsing failure: %v`, err)
  58. }
  59. r := mux.NewRouter()
  60. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  61. input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
  62. output := RewriteDocumentWithRelativeProxyURL(r, input)
  63. expected := input
  64. if expected != output {
  65. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  66. }
  67. }
  68. func TestProxyFilterWithHttpsNever(t *testing.T) {
  69. os.Clearenv()
  70. os.Setenv("MEDIA_PROXY_MODE", "none")
  71. var err error
  72. parser := config.NewConfigParser()
  73. config.Opts, err = parser.ParseEnvironmentVariables()
  74. if err != nil {
  75. t.Fatalf(`Parsing failure: %v`, err)
  76. }
  77. r := mux.NewRouter()
  78. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  79. input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  80. output := RewriteDocumentWithRelativeProxyURL(r, input)
  81. expected := input
  82. if expected != output {
  83. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  84. }
  85. }
  86. func TestProxyFilterWithHttpAlways(t *testing.T) {
  87. os.Clearenv()
  88. os.Setenv("MEDIA_PROXY_MODE", "all")
  89. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  90. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  91. var err error
  92. parser := config.NewConfigParser()
  93. config.Opts, err = parser.ParseEnvironmentVariables()
  94. if err != nil {
  95. t.Fatalf(`Parsing failure: %v`, err)
  96. }
  97. r := mux.NewRouter()
  98. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  99. input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
  100. output := RewriteDocumentWithRelativeProxyURL(r, input)
  101. expected := `<p><img src="/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
  102. if expected != output {
  103. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  104. }
  105. }
  106. func TestProxyFilterWithHttpsAlways(t *testing.T) {
  107. os.Clearenv()
  108. os.Setenv("MEDIA_PROXY_MODE", "all")
  109. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  110. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  111. var err error
  112. parser := config.NewConfigParser()
  113. config.Opts, err = parser.ParseEnvironmentVariables()
  114. if err != nil {
  115. t.Fatalf(`Parsing failure: %v`, err)
  116. }
  117. r := mux.NewRouter()
  118. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  119. input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  120. output := RewriteDocumentWithRelativeProxyURL(r, input)
  121. expected := `<p><img src="/proxy/LdPNR1GBDigeeNp2ArUQRyZsVqT_PWLfHGjYFrrWWIY=/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
  122. if expected != output {
  123. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  124. }
  125. }
  126. func TestAbsoluteProxyFilterWithHttpsAlways(t *testing.T) {
  127. os.Clearenv()
  128. os.Setenv("MEDIA_PROXY_MODE", "all")
  129. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  130. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  131. var err error
  132. parser := config.NewConfigParser()
  133. config.Opts, err = parser.ParseEnvironmentVariables()
  134. if err != nil {
  135. t.Fatalf(`Parsing failure: %v`, err)
  136. }
  137. r := mux.NewRouter()
  138. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  139. input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  140. output := RewriteDocumentWithAbsoluteProxyURL(r, input)
  141. expected := `<p><img src="http://localhost/proxy/LdPNR1GBDigeeNp2ArUQRyZsVqT_PWLfHGjYFrrWWIY=/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
  142. if expected != output {
  143. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  144. }
  145. }
  146. func TestAbsoluteProxyFilterWithCustomPortAndSubfolderInBaseURL(t *testing.T) {
  147. os.Clearenv()
  148. os.Setenv("BASE_URL", "http://example.org:88/folder/")
  149. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  150. var err error
  151. parser := config.NewConfigParser()
  152. config.Opts, err = parser.ParseEnvironmentVariables()
  153. if err != nil {
  154. t.Fatalf(`Parsing failure: %v`, err)
  155. }
  156. if config.Opts.BaseURL() != "http://example.org:88/folder" {
  157. t.Fatalf(`Unexpected base URL, got "%s"`, config.Opts.BaseURL())
  158. }
  159. if config.Opts.RootURL() != "http://example.org:88" {
  160. t.Fatalf(`Unexpected root URL, got "%s"`, config.Opts.RootURL())
  161. }
  162. router := mux.NewRouter()
  163. if config.Opts.BasePath() != "" {
  164. router = router.PathPrefix(config.Opts.BasePath()).Subrouter()
  165. }
  166. router.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  167. input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
  168. output := RewriteDocumentWithAbsoluteProxyURL(router, input)
  169. expected := `<p><img src="http://example.org:88/folder/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
  170. if expected != output {
  171. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  172. }
  173. }
  174. func TestAbsoluteProxyFilterWithHttpsAlwaysAndAudioTag(t *testing.T) {
  175. os.Clearenv()
  176. os.Setenv("MEDIA_PROXY_MODE", "all")
  177. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "audio")
  178. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  179. var err error
  180. parser := config.NewConfigParser()
  181. config.Opts, err = parser.ParseEnvironmentVariables()
  182. if err != nil {
  183. t.Fatalf(`Parsing failure: %v`, err)
  184. }
  185. r := mux.NewRouter()
  186. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  187. input := `<audio src="https://website/folder/audio.mp3"></audio>`
  188. output := RewriteDocumentWithAbsoluteProxyURL(r, input)
  189. expected := `<audio src="http://localhost/proxy/EmBTvmU5B17wGuONkeknkptYopW_Tl6Y6_W8oYbN_Xs=/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9hdWRpby5tcDM="></audio>`
  190. if expected != output {
  191. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  192. }
  193. }
  194. func TestProxyFilterWithHttpsAlwaysAndCustomProxyServer(t *testing.T) {
  195. os.Clearenv()
  196. os.Setenv("MEDIA_PROXY_MODE", "all")
  197. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  198. os.Setenv("MEDIA_PROXY_CUSTOM_URL", "https://proxy-example/proxy")
  199. var err error
  200. parser := config.NewConfigParser()
  201. config.Opts, err = parser.ParseEnvironmentVariables()
  202. if err != nil {
  203. t.Fatalf(`Parsing failure: %v`, err)
  204. }
  205. r := mux.NewRouter()
  206. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  207. input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  208. output := RewriteDocumentWithRelativeProxyURL(r, input)
  209. expected := `<p><img src="https://proxy-example/proxy/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
  210. if expected != output {
  211. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  212. }
  213. }
  214. func TestProxyFilterWithHttpsAlwaysAndIncorrectCustomProxyServer(t *testing.T) {
  215. os.Clearenv()
  216. os.Setenv("MEDIA_PROXY_MODE", "all")
  217. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  218. os.Setenv("MEDIA_PROXY_CUSTOM_URL", "http://:8080example.com")
  219. var err error
  220. parser := config.NewConfigParser()
  221. config.Opts, err = parser.ParseEnvironmentVariables()
  222. if err == nil {
  223. t.Fatalf(`Incorrect proxy URL silently accepted (MEDIA_PROXY_CUSTOM_URL=%q): %q`, os.Getenv("MEDIA_PROXY_CUSTOM_URL"), config.Opts.MediaCustomProxyURL())
  224. }
  225. }
  226. func TestAbsoluteProxyFilterWithHttpsAlwaysAndCustomProxyServer(t *testing.T) {
  227. os.Clearenv()
  228. os.Setenv("MEDIA_PROXY_MODE", "all")
  229. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  230. os.Setenv("MEDIA_PROXY_CUSTOM_URL", "https://proxy-example/proxy")
  231. var err error
  232. parser := config.NewConfigParser()
  233. config.Opts, err = parser.ParseEnvironmentVariables()
  234. if err != nil {
  235. t.Fatalf(`Parsing failure: %v`, err)
  236. }
  237. r := mux.NewRouter()
  238. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  239. input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  240. output := RewriteDocumentWithAbsoluteProxyURL(r, input)
  241. expected := `<p><img src="https://proxy-example/proxy/aHR0cHM6Ly93ZWJzaXRlL2ZvbGRlci9pbWFnZS5wbmc=" alt="Test"/></p>`
  242. if expected != output {
  243. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  244. }
  245. }
  246. func TestProxyFilterWithHttpInvalid(t *testing.T) {
  247. os.Clearenv()
  248. os.Setenv("MEDIA_PROXY_MODE", "invalid")
  249. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  250. if _, err := config.NewConfigParser().ParseEnvironmentVariables(); err == nil {
  251. t.Fatalf(`Parsing should have failed (MEDIA_PROXY_MODE=%q): %q`, os.Getenv("MEDIA_PROXY_MODE"), config.Opts.MediaProxyMode())
  252. }
  253. }
  254. func TestProxyFilterWithSrcset(t *testing.T) {
  255. os.Clearenv()
  256. os.Setenv("MEDIA_PROXY_MODE", "all")
  257. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  258. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  259. var err error
  260. parser := config.NewConfigParser()
  261. config.Opts, err = parser.ParseEnvironmentVariables()
  262. if err != nil {
  263. t.Fatalf(`Parsing failure: %v`, err)
  264. }
  265. r := mux.NewRouter()
  266. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  267. input := `<p><img src="http://website/folder/image.png" srcset="http://website/folder/image2.png 656w, http://website/folder/image3.png 360w" alt="test"></p>`
  268. expected := `<p><img src="/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" srcset="/proxy/aY5Hb4urDnUCly2vTJ7ExQeeaVS-52O7kjUr2v9VrAs=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMi5wbmc= 656w, /proxy/QgAmrJWiAud_nNAsz3F8OTxaIofwAiO36EDzH_YfMzo=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMy5wbmc= 360w" alt="test"/></p>`
  269. output := RewriteDocumentWithRelativeProxyURL(r, input)
  270. if expected != output {
  271. t.Errorf(`Not expected output: got %s`, output)
  272. }
  273. }
  274. func TestProxyFilterWithEmptySrcset(t *testing.T) {
  275. os.Clearenv()
  276. os.Setenv("MEDIA_PROXY_MODE", "all")
  277. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  278. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  279. var err error
  280. parser := config.NewConfigParser()
  281. config.Opts, err = parser.ParseEnvironmentVariables()
  282. if err != nil {
  283. t.Fatalf(`Parsing failure: %v`, err)
  284. }
  285. r := mux.NewRouter()
  286. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  287. input := `<p><img src="http://website/folder/image.png" srcset="" alt="test"></p>`
  288. expected := `<p><img src="/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" srcset="" alt="test"/></p>`
  289. output := RewriteDocumentWithRelativeProxyURL(r, input)
  290. if expected != output {
  291. t.Errorf(`Not expected output: got %s`, output)
  292. }
  293. }
  294. func TestProxyFilterWithPictureSource(t *testing.T) {
  295. os.Clearenv()
  296. os.Setenv("MEDIA_PROXY_MODE", "all")
  297. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  298. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  299. var err error
  300. parser := config.NewConfigParser()
  301. config.Opts, err = parser.ParseEnvironmentVariables()
  302. if err != nil {
  303. t.Fatalf(`Parsing failure: %v`, err)
  304. }
  305. r := mux.NewRouter()
  306. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  307. input := `<picture><source srcset="http://website/folder/image2.png 656w, http://website/folder/image3.png 360w, https://website/some,image.png 2x"></picture>`
  308. expected := `<picture><source srcset="/proxy/aY5Hb4urDnUCly2vTJ7ExQeeaVS-52O7kjUr2v9VrAs=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMi5wbmc= 656w, /proxy/QgAmrJWiAud_nNAsz3F8OTxaIofwAiO36EDzH_YfMzo=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMy5wbmc= 360w, /proxy/ZIw0hv8WhSTls5aSqhnFaCXlUrKIqTnBRaY0-NaLnds=/aHR0cHM6Ly93ZWJzaXRlL3NvbWUsaW1hZ2UucG5n 2x"/></picture>`
  309. output := RewriteDocumentWithRelativeProxyURL(r, input)
  310. if expected != output {
  311. t.Errorf(`Not expected output: got %s`, output)
  312. }
  313. }
  314. func TestProxyFilterOnlyNonHTTPWithPictureSource(t *testing.T) {
  315. os.Clearenv()
  316. os.Setenv("MEDIA_PROXY_MODE", "http-only")
  317. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  318. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  319. var err error
  320. parser := config.NewConfigParser()
  321. config.Opts, err = parser.ParseEnvironmentVariables()
  322. if err != nil {
  323. t.Fatalf(`Parsing failure: %v`, err)
  324. }
  325. r := mux.NewRouter()
  326. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  327. input := `<picture><source srcset="http://website/folder/image2.png 656w, https://website/some,image.png 2x"></picture>`
  328. expected := `<picture><source srcset="/proxy/aY5Hb4urDnUCly2vTJ7ExQeeaVS-52O7kjUr2v9VrAs=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMi5wbmc= 656w, https://website/some,image.png 2x"/></picture>`
  329. output := RewriteDocumentWithRelativeProxyURL(r, input)
  330. if expected != output {
  331. t.Errorf(`Not expected output: got %s`, output)
  332. }
  333. }
  334. func TestProxyWithImageDataURL(t *testing.T) {
  335. os.Clearenv()
  336. os.Setenv("MEDIA_PROXY_MODE", "all")
  337. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  338. var err error
  339. parser := config.NewConfigParser()
  340. config.Opts, err = parser.ParseEnvironmentVariables()
  341. if err != nil {
  342. t.Fatalf(`Parsing failure: %v`, err)
  343. }
  344. r := mux.NewRouter()
  345. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  346. input := `<img src="data:image/gif;base64,test">`
  347. expected := `<img src="data:image/gif;base64,test"/>`
  348. output := RewriteDocumentWithRelativeProxyURL(r, input)
  349. if expected != output {
  350. t.Errorf(`Not expected output: got %s`, output)
  351. }
  352. }
  353. func TestProxyWithImageSourceDataURL(t *testing.T) {
  354. os.Clearenv()
  355. os.Setenv("MEDIA_PROXY_MODE", "all")
  356. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  357. var err error
  358. parser := config.NewConfigParser()
  359. config.Opts, err = parser.ParseEnvironmentVariables()
  360. if err != nil {
  361. t.Fatalf(`Parsing failure: %v`, err)
  362. }
  363. r := mux.NewRouter()
  364. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  365. input := `<picture><source srcset="data:image/gif;base64,test"/></picture>`
  366. expected := `<picture><source srcset="data:image/gif;base64,test"/></picture>`
  367. output := RewriteDocumentWithRelativeProxyURL(r, input)
  368. if expected != output {
  369. t.Errorf(`Not expected output: got %s`, output)
  370. }
  371. }
  372. func TestProxyFilterWithVideo(t *testing.T) {
  373. os.Clearenv()
  374. os.Setenv("MEDIA_PROXY_MODE", "all")
  375. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "video")
  376. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  377. var err error
  378. parser := config.NewConfigParser()
  379. config.Opts, err = parser.ParseEnvironmentVariables()
  380. if err != nil {
  381. t.Fatalf(`Parsing failure: %v`, err)
  382. }
  383. r := mux.NewRouter()
  384. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  385. input := `<video poster="https://example.com/img.png" src="https://example.com/video.mp4"></video>`
  386. expected := `<video poster="/proxy/aDFfroYL57q5XsojIzATT6OYUCkuVSPXYJQAVrotnLw=/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWcucG5n" src="/proxy/0y3LR8zlx8S8qJkj1qWFOO6x3a-5yf2gLWjGIJV5yyc=/aHR0cHM6Ly9leGFtcGxlLmNvbS92aWRlby5tcDQ="></video>`
  387. output := RewriteDocumentWithRelativeProxyURL(r, input)
  388. if expected != output {
  389. t.Errorf(`Not expected output: got %s`, output)
  390. }
  391. }
  392. func TestProxyFilterVideoPoster(t *testing.T) {
  393. os.Clearenv()
  394. os.Setenv("MEDIA_PROXY_MODE", "all")
  395. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  396. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  397. var err error
  398. parser := config.NewConfigParser()
  399. config.Opts, err = parser.ParseEnvironmentVariables()
  400. if err != nil {
  401. t.Fatalf(`Parsing failure: %v`, err)
  402. }
  403. r := mux.NewRouter()
  404. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  405. input := `<video poster="https://example.com/img.png" src="https://example.com/video.mp4"></video>`
  406. expected := `<video poster="/proxy/aDFfroYL57q5XsojIzATT6OYUCkuVSPXYJQAVrotnLw=/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWcucG5n" src="https://example.com/video.mp4"></video>`
  407. output := RewriteDocumentWithRelativeProxyURL(r, input)
  408. if expected != output {
  409. t.Errorf(`Not expected output: got %s`, output)
  410. }
  411. }
  412. func TestProxyFilterVideoPosterOnce(t *testing.T) {
  413. os.Clearenv()
  414. os.Setenv("MEDIA_PROXY_MODE", "all")
  415. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image,video")
  416. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  417. var err error
  418. parser := config.NewConfigParser()
  419. config.Opts, err = parser.ParseEnvironmentVariables()
  420. if err != nil {
  421. t.Fatalf(`Parsing failure: %v`, err)
  422. }
  423. r := mux.NewRouter()
  424. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  425. input := `<video poster="https://example.com/img.png" src="https://example.com/video.mp4"></video>`
  426. expected := `<video poster="/proxy/aDFfroYL57q5XsojIzATT6OYUCkuVSPXYJQAVrotnLw=/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWcucG5n" src="/proxy/0y3LR8zlx8S8qJkj1qWFOO6x3a-5yf2gLWjGIJV5yyc=/aHR0cHM6Ly9leGFtcGxlLmNvbS92aWRlby5tcDQ="></video>`
  427. output := RewriteDocumentWithRelativeProxyURL(r, input)
  428. if expected != output {
  429. t.Errorf(`Not expected output: got %s`, output)
  430. }
  431. }
  432. func TestShouldProxifyURLWithMimeType(t *testing.T) {
  433. testCases := []struct {
  434. name string
  435. mediaURL string
  436. mediaMimeType string
  437. mediaProxyOption string
  438. mediaProxyResourceTypes []string
  439. expected bool
  440. }{
  441. {
  442. name: "Empty URL should not be proxified",
  443. mediaURL: "",
  444. mediaMimeType: "image/jpeg",
  445. mediaProxyOption: "all",
  446. mediaProxyResourceTypes: []string{"image"},
  447. expected: false,
  448. },
  449. {
  450. name: "Data URL should not be proxified",
  451. mediaURL: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==",
  452. mediaMimeType: "image/png",
  453. mediaProxyOption: "all",
  454. mediaProxyResourceTypes: []string{"image"},
  455. expected: false,
  456. },
  457. {
  458. name: "HTTP URL with all mode and matching MIME type should be proxified",
  459. mediaURL: "http://example.com/image.jpg",
  460. mediaMimeType: "image/jpeg",
  461. mediaProxyOption: "all",
  462. mediaProxyResourceTypes: []string{"image"},
  463. expected: true,
  464. },
  465. {
  466. name: "HTTPS URL with all mode and matching MIME type should be proxified",
  467. mediaURL: "https://example.com/image.jpg",
  468. mediaMimeType: "image/jpeg",
  469. mediaProxyOption: "all",
  470. mediaProxyResourceTypes: []string{"image"},
  471. expected: true,
  472. },
  473. {
  474. name: "HTTP URL with http-only mode and matching MIME type should be proxified",
  475. mediaURL: "http://example.com/image.jpg",
  476. mediaMimeType: "image/jpeg",
  477. mediaProxyOption: "http-only",
  478. mediaProxyResourceTypes: []string{"image"},
  479. expected: true,
  480. },
  481. {
  482. name: "HTTPS URL with http-only mode should not be proxified",
  483. mediaURL: "https://example.com/image.jpg",
  484. mediaMimeType: "image/jpeg",
  485. mediaProxyOption: "http-only",
  486. mediaProxyResourceTypes: []string{"image"},
  487. expected: false,
  488. },
  489. {
  490. name: "URL with none mode should not be proxified",
  491. mediaURL: "http://example.com/image.jpg",
  492. mediaMimeType: "image/jpeg",
  493. mediaProxyOption: "none",
  494. mediaProxyResourceTypes: []string{"image"},
  495. expected: false,
  496. },
  497. {
  498. name: "URL with matching MIME type should be proxified",
  499. mediaURL: "http://example.com/video.mp4",
  500. mediaMimeType: "video/mp4",
  501. mediaProxyOption: "all",
  502. mediaProxyResourceTypes: []string{"video"},
  503. expected: true,
  504. },
  505. {
  506. name: "URL with non-matching MIME type should not be proxified",
  507. mediaURL: "http://example.com/video.mp4",
  508. mediaMimeType: "video/mp4",
  509. mediaProxyOption: "all",
  510. mediaProxyResourceTypes: []string{"image"},
  511. expected: false,
  512. },
  513. {
  514. name: "URL with multiple resource types and matching MIME type should be proxified",
  515. mediaURL: "http://example.com/audio.mp3",
  516. mediaMimeType: "audio/mp3",
  517. mediaProxyOption: "all",
  518. mediaProxyResourceTypes: []string{"image", "audio", "video"},
  519. expected: true,
  520. },
  521. {
  522. name: "URL with multiple resource types but non-matching MIME type should not be proxified",
  523. mediaURL: "http://example.com/document.pdf",
  524. mediaMimeType: "application/pdf",
  525. mediaProxyOption: "all",
  526. mediaProxyResourceTypes: []string{"image", "audio", "video"},
  527. expected: false,
  528. },
  529. {
  530. name: "URL with empty resource types should not be proxified",
  531. mediaURL: "http://example.com/image.jpg",
  532. mediaMimeType: "image/jpeg",
  533. mediaProxyOption: "all",
  534. mediaProxyResourceTypes: []string{},
  535. expected: false,
  536. },
  537. {
  538. name: "URL with partial MIME type match should be proxified",
  539. mediaURL: "http://example.com/image.jpg",
  540. mediaMimeType: "image/jpeg",
  541. mediaProxyOption: "all",
  542. mediaProxyResourceTypes: []string{"image"},
  543. expected: true,
  544. },
  545. {
  546. name: "URL with audio MIME type and audio resource type should be proxified",
  547. mediaURL: "http://example.com/song.ogg",
  548. mediaMimeType: "audio/ogg",
  549. mediaProxyOption: "all",
  550. mediaProxyResourceTypes: []string{"audio"},
  551. expected: true,
  552. },
  553. {
  554. name: "URL with video MIME type and video resource type should be proxified",
  555. mediaURL: "http://example.com/movie.webm",
  556. mediaMimeType: "video/webm",
  557. mediaProxyOption: "all",
  558. mediaProxyResourceTypes: []string{"video"},
  559. expected: true,
  560. },
  561. }
  562. for _, tc := range testCases {
  563. t.Run(tc.name, func(t *testing.T) {
  564. result := ShouldProxifyURLWithMimeType(tc.mediaURL, tc.mediaMimeType, tc.mediaProxyOption, tc.mediaProxyResourceTypes)
  565. if result != tc.expected {
  566. t.Errorf("Expected %v, got %v for URL: %s, MIME type: %s, proxy option: %s, resource types: %v",
  567. tc.expected, result, tc.mediaURL, tc.mediaMimeType, tc.mediaProxyOption, tc.mediaProxyResourceTypes)
  568. }
  569. })
  570. }
  571. }