media_proxy_test.go 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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.NewParser()
  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. var err error
  251. parser := config.NewParser()
  252. config.Opts, err = parser.ParseEnvironmentVariables()
  253. if err != nil {
  254. t.Fatalf(`Parsing failure: %v`, err)
  255. }
  256. r := mux.NewRouter()
  257. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  258. input := `<p><img src="http://website/folder/image.png" alt="Test"/></p>`
  259. output := RewriteDocumentWithRelativeProxyURL(r, input)
  260. expected := `<p><img src="/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" alt="Test"/></p>`
  261. if expected != output {
  262. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  263. }
  264. }
  265. func TestProxyFilterWithHttpsInvalid(t *testing.T) {
  266. os.Clearenv()
  267. os.Setenv("MEDIA_PROXY_MODE", "invalid")
  268. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  269. var err error
  270. parser := config.NewParser()
  271. config.Opts, err = parser.ParseEnvironmentVariables()
  272. if err != nil {
  273. t.Fatalf(`Parsing failure: %v`, err)
  274. }
  275. r := mux.NewRouter()
  276. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  277. input := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  278. output := RewriteDocumentWithRelativeProxyURL(r, input)
  279. expected := `<p><img src="https://website/folder/image.png" alt="Test"/></p>`
  280. if expected != output {
  281. t.Errorf(`Not expected output: got %q instead of %q`, output, expected)
  282. }
  283. }
  284. func TestProxyFilterWithSrcset(t *testing.T) {
  285. os.Clearenv()
  286. os.Setenv("MEDIA_PROXY_MODE", "all")
  287. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  288. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  289. var err error
  290. parser := config.NewParser()
  291. config.Opts, err = parser.ParseEnvironmentVariables()
  292. if err != nil {
  293. t.Fatalf(`Parsing failure: %v`, err)
  294. }
  295. r := mux.NewRouter()
  296. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  297. 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>`
  298. expected := `<p><img src="/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" srcset="/proxy/aY5Hb4urDnUCly2vTJ7ExQeeaVS-52O7kjUr2v9VrAs=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMi5wbmc= 656w, /proxy/QgAmrJWiAud_nNAsz3F8OTxaIofwAiO36EDzH_YfMzo=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMy5wbmc= 360w" alt="test"/></p>`
  299. output := RewriteDocumentWithRelativeProxyURL(r, input)
  300. if expected != output {
  301. t.Errorf(`Not expected output: got %s`, output)
  302. }
  303. }
  304. func TestProxyFilterWithEmptySrcset(t *testing.T) {
  305. os.Clearenv()
  306. os.Setenv("MEDIA_PROXY_MODE", "all")
  307. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  308. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  309. var err error
  310. parser := config.NewParser()
  311. config.Opts, err = parser.ParseEnvironmentVariables()
  312. if err != nil {
  313. t.Fatalf(`Parsing failure: %v`, err)
  314. }
  315. r := mux.NewRouter()
  316. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  317. input := `<p><img src="http://website/folder/image.png" srcset="" alt="test"></p>`
  318. expected := `<p><img src="/proxy/okK5PsdNY8F082UMQEAbLPeUFfbe2WnNfInNmR9T4WA=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlLnBuZw==" srcset="" alt="test"/></p>`
  319. output := RewriteDocumentWithRelativeProxyURL(r, input)
  320. if expected != output {
  321. t.Errorf(`Not expected output: got %s`, output)
  322. }
  323. }
  324. func TestProxyFilterWithPictureSource(t *testing.T) {
  325. os.Clearenv()
  326. os.Setenv("MEDIA_PROXY_MODE", "all")
  327. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  328. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  329. var err error
  330. parser := config.NewParser()
  331. config.Opts, err = parser.ParseEnvironmentVariables()
  332. if err != nil {
  333. t.Fatalf(`Parsing failure: %v`, err)
  334. }
  335. r := mux.NewRouter()
  336. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  337. input := `<picture><source srcset="http://website/folder/image2.png 656w, http://website/folder/image3.png 360w, https://website/some,image.png 2x"></picture>`
  338. expected := `<picture><source srcset="/proxy/aY5Hb4urDnUCly2vTJ7ExQeeaVS-52O7kjUr2v9VrAs=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMi5wbmc= 656w, /proxy/QgAmrJWiAud_nNAsz3F8OTxaIofwAiO36EDzH_YfMzo=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMy5wbmc= 360w, /proxy/ZIw0hv8WhSTls5aSqhnFaCXlUrKIqTnBRaY0-NaLnds=/aHR0cHM6Ly93ZWJzaXRlL3NvbWUsaW1hZ2UucG5n 2x"/></picture>`
  339. output := RewriteDocumentWithRelativeProxyURL(r, input)
  340. if expected != output {
  341. t.Errorf(`Not expected output: got %s`, output)
  342. }
  343. }
  344. func TestProxyFilterOnlyNonHTTPWithPictureSource(t *testing.T) {
  345. os.Clearenv()
  346. os.Setenv("MEDIA_PROXY_MODE", "https")
  347. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  348. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  349. var err error
  350. parser := config.NewParser()
  351. config.Opts, err = parser.ParseEnvironmentVariables()
  352. if err != nil {
  353. t.Fatalf(`Parsing failure: %v`, err)
  354. }
  355. r := mux.NewRouter()
  356. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  357. input := `<picture><source srcset="http://website/folder/image2.png 656w, https://website/some,image.png 2x"></picture>`
  358. expected := `<picture><source srcset="/proxy/aY5Hb4urDnUCly2vTJ7ExQeeaVS-52O7kjUr2v9VrAs=/aHR0cDovL3dlYnNpdGUvZm9sZGVyL2ltYWdlMi5wbmc= 656w, https://website/some,image.png 2x"/></picture>`
  359. output := RewriteDocumentWithRelativeProxyURL(r, input)
  360. if expected != output {
  361. t.Errorf(`Not expected output: got %s`, output)
  362. }
  363. }
  364. func TestProxyWithImageDataURL(t *testing.T) {
  365. os.Clearenv()
  366. os.Setenv("MEDIA_PROXY_MODE", "all")
  367. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  368. var err error
  369. parser := config.NewParser()
  370. config.Opts, err = parser.ParseEnvironmentVariables()
  371. if err != nil {
  372. t.Fatalf(`Parsing failure: %v`, err)
  373. }
  374. r := mux.NewRouter()
  375. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  376. input := `<img src="data:image/gif;base64,test">`
  377. expected := `<img src="data:image/gif;base64,test"/>`
  378. output := RewriteDocumentWithRelativeProxyURL(r, input)
  379. if expected != output {
  380. t.Errorf(`Not expected output: got %s`, output)
  381. }
  382. }
  383. func TestProxyWithImageSourceDataURL(t *testing.T) {
  384. os.Clearenv()
  385. os.Setenv("MEDIA_PROXY_MODE", "all")
  386. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  387. var err error
  388. parser := config.NewParser()
  389. config.Opts, err = parser.ParseEnvironmentVariables()
  390. if err != nil {
  391. t.Fatalf(`Parsing failure: %v`, err)
  392. }
  393. r := mux.NewRouter()
  394. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  395. input := `<picture><source srcset="data:image/gif;base64,test"/></picture>`
  396. expected := `<picture><source srcset="data:image/gif;base64,test"/></picture>`
  397. output := RewriteDocumentWithRelativeProxyURL(r, input)
  398. if expected != output {
  399. t.Errorf(`Not expected output: got %s`, output)
  400. }
  401. }
  402. func TestProxyFilterWithVideo(t *testing.T) {
  403. os.Clearenv()
  404. os.Setenv("MEDIA_PROXY_MODE", "all")
  405. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "video")
  406. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  407. var err error
  408. parser := config.NewParser()
  409. config.Opts, err = parser.ParseEnvironmentVariables()
  410. if err != nil {
  411. t.Fatalf(`Parsing failure: %v`, err)
  412. }
  413. r := mux.NewRouter()
  414. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  415. input := `<video poster="https://example.com/img.png" src="https://example.com/video.mp4"></video>`
  416. expected := `<video poster="/proxy/aDFfroYL57q5XsojIzATT6OYUCkuVSPXYJQAVrotnLw=/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWcucG5n" src="/proxy/0y3LR8zlx8S8qJkj1qWFOO6x3a-5yf2gLWjGIJV5yyc=/aHR0cHM6Ly9leGFtcGxlLmNvbS92aWRlby5tcDQ="></video>`
  417. output := RewriteDocumentWithRelativeProxyURL(r, input)
  418. if expected != output {
  419. t.Errorf(`Not expected output: got %s`, output)
  420. }
  421. }
  422. func TestProxyFilterVideoPoster(t *testing.T) {
  423. os.Clearenv()
  424. os.Setenv("MEDIA_PROXY_MODE", "all")
  425. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image")
  426. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  427. var err error
  428. parser := config.NewParser()
  429. config.Opts, err = parser.ParseEnvironmentVariables()
  430. if err != nil {
  431. t.Fatalf(`Parsing failure: %v`, err)
  432. }
  433. r := mux.NewRouter()
  434. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  435. input := `<video poster="https://example.com/img.png" src="https://example.com/video.mp4"></video>`
  436. expected := `<video poster="/proxy/aDFfroYL57q5XsojIzATT6OYUCkuVSPXYJQAVrotnLw=/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWcucG5n" src="https://example.com/video.mp4"></video>`
  437. output := RewriteDocumentWithRelativeProxyURL(r, input)
  438. if expected != output {
  439. t.Errorf(`Not expected output: got %s`, output)
  440. }
  441. }
  442. func TestProxyFilterVideoPosterOnce(t *testing.T) {
  443. os.Clearenv()
  444. os.Setenv("MEDIA_PROXY_MODE", "all")
  445. os.Setenv("MEDIA_PROXY_RESOURCE_TYPES", "image,video")
  446. os.Setenv("MEDIA_PROXY_PRIVATE_KEY", "test")
  447. var err error
  448. parser := config.NewParser()
  449. config.Opts, err = parser.ParseEnvironmentVariables()
  450. if err != nil {
  451. t.Fatalf(`Parsing failure: %v`, err)
  452. }
  453. r := mux.NewRouter()
  454. r.HandleFunc("/proxy/{encodedDigest}/{encodedURL}", func(w http.ResponseWriter, r *http.Request) {}).Name("proxy")
  455. input := `<video poster="https://example.com/img.png" src="https://example.com/video.mp4"></video>`
  456. expected := `<video poster="/proxy/aDFfroYL57q5XsojIzATT6OYUCkuVSPXYJQAVrotnLw=/aHR0cHM6Ly9leGFtcGxlLmNvbS9pbWcucG5n" src="/proxy/0y3LR8zlx8S8qJkj1qWFOO6x3a-5yf2gLWjGIJV5yyc=/aHR0cHM6Ly9leGFtcGxlLmNvbS92aWRlby5tcDQ="></video>`
  457. output := RewriteDocumentWithRelativeProxyURL(r, input)
  458. if expected != output {
  459. t.Errorf(`Not expected output: got %s`, output)
  460. }
  461. }
  462. func TestShouldProxifyURLWithMimeType(t *testing.T) {
  463. testCases := []struct {
  464. name string
  465. mediaURL string
  466. mediaMimeType string
  467. mediaProxyOption string
  468. mediaProxyResourceTypes []string
  469. expected bool
  470. }{
  471. {
  472. name: "Empty URL should not be proxified",
  473. mediaURL: "",
  474. mediaMimeType: "image/jpeg",
  475. mediaProxyOption: "all",
  476. mediaProxyResourceTypes: []string{"image"},
  477. expected: false,
  478. },
  479. {
  480. name: "Data URL should not be proxified",
  481. mediaURL: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==",
  482. mediaMimeType: "image/png",
  483. mediaProxyOption: "all",
  484. mediaProxyResourceTypes: []string{"image"},
  485. expected: false,
  486. },
  487. {
  488. name: "HTTP URL with all mode and matching MIME type should be proxified",
  489. mediaURL: "http://example.com/image.jpg",
  490. mediaMimeType: "image/jpeg",
  491. mediaProxyOption: "all",
  492. mediaProxyResourceTypes: []string{"image"},
  493. expected: true,
  494. },
  495. {
  496. name: "HTTPS URL with all mode and matching MIME type should be proxified",
  497. mediaURL: "https://example.com/image.jpg",
  498. mediaMimeType: "image/jpeg",
  499. mediaProxyOption: "all",
  500. mediaProxyResourceTypes: []string{"image"},
  501. expected: true,
  502. },
  503. {
  504. name: "HTTP URL with http-only mode and matching MIME type should be proxified",
  505. mediaURL: "http://example.com/image.jpg",
  506. mediaMimeType: "image/jpeg",
  507. mediaProxyOption: "http-only",
  508. mediaProxyResourceTypes: []string{"image"},
  509. expected: true,
  510. },
  511. {
  512. name: "HTTPS URL with http-only mode should not be proxified",
  513. mediaURL: "https://example.com/image.jpg",
  514. mediaMimeType: "image/jpeg",
  515. mediaProxyOption: "http-only",
  516. mediaProxyResourceTypes: []string{"image"},
  517. expected: false,
  518. },
  519. {
  520. name: "URL with none mode should not be proxified",
  521. mediaURL: "http://example.com/image.jpg",
  522. mediaMimeType: "image/jpeg",
  523. mediaProxyOption: "none",
  524. mediaProxyResourceTypes: []string{"image"},
  525. expected: false,
  526. },
  527. {
  528. name: "URL with matching MIME type should be proxified",
  529. mediaURL: "http://example.com/video.mp4",
  530. mediaMimeType: "video/mp4",
  531. mediaProxyOption: "all",
  532. mediaProxyResourceTypes: []string{"video"},
  533. expected: true,
  534. },
  535. {
  536. name: "URL with non-matching MIME type should not be proxified",
  537. mediaURL: "http://example.com/video.mp4",
  538. mediaMimeType: "video/mp4",
  539. mediaProxyOption: "all",
  540. mediaProxyResourceTypes: []string{"image"},
  541. expected: false,
  542. },
  543. {
  544. name: "URL with multiple resource types and matching MIME type should be proxified",
  545. mediaURL: "http://example.com/audio.mp3",
  546. mediaMimeType: "audio/mp3",
  547. mediaProxyOption: "all",
  548. mediaProxyResourceTypes: []string{"image", "audio", "video"},
  549. expected: true,
  550. },
  551. {
  552. name: "URL with multiple resource types but non-matching MIME type should not be proxified",
  553. mediaURL: "http://example.com/document.pdf",
  554. mediaMimeType: "application/pdf",
  555. mediaProxyOption: "all",
  556. mediaProxyResourceTypes: []string{"image", "audio", "video"},
  557. expected: false,
  558. },
  559. {
  560. name: "URL with empty resource types should not be proxified",
  561. mediaURL: "http://example.com/image.jpg",
  562. mediaMimeType: "image/jpeg",
  563. mediaProxyOption: "all",
  564. mediaProxyResourceTypes: []string{},
  565. expected: false,
  566. },
  567. {
  568. name: "URL with partial MIME type match should be proxified",
  569. mediaURL: "http://example.com/image.jpg",
  570. mediaMimeType: "image/jpeg",
  571. mediaProxyOption: "all",
  572. mediaProxyResourceTypes: []string{"image"},
  573. expected: true,
  574. },
  575. {
  576. name: "URL with audio MIME type and audio resource type should be proxified",
  577. mediaURL: "http://example.com/song.ogg",
  578. mediaMimeType: "audio/ogg",
  579. mediaProxyOption: "all",
  580. mediaProxyResourceTypes: []string{"audio"},
  581. expected: true,
  582. },
  583. {
  584. name: "URL with video MIME type and video resource type should be proxified",
  585. mediaURL: "http://example.com/movie.webm",
  586. mediaMimeType: "video/webm",
  587. mediaProxyOption: "all",
  588. mediaProxyResourceTypes: []string{"video"},
  589. expected: true,
  590. },
  591. }
  592. for _, tc := range testCases {
  593. t.Run(tc.name, func(t *testing.T) {
  594. result := ShouldProxifyURLWithMimeType(tc.mediaURL, tc.mediaMimeType, tc.mediaProxyOption, tc.mediaProxyResourceTypes)
  595. if result != tc.expected {
  596. t.Errorf("Expected %v, got %v for URL: %s, MIME type: %s, proxy option: %s, resource types: %v",
  597. tc.expected, result, tc.mediaURL, tc.mediaMimeType, tc.mediaProxyOption, tc.mediaProxyResourceTypes)
  598. }
  599. })
  600. }
  601. }