logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

media_proxy_controller_test.exs (10214B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
  5. use Pleroma.Web.ConnCase
  6. import Mock
  7. alias Pleroma.Web.MediaProxy
  8. alias Plug.Conn
  9. setup do
  10. on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
  11. end
  12. describe "Media Proxy" do
  13. setup do
  14. clear_config([:media_proxy, :enabled], true)
  15. clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
  16. [url: MediaProxy.encode_url("https://google.fn/test.png")]
  17. end
  18. test "it returns 404 when disabled", %{conn: conn} do
  19. clear_config([:media_proxy, :enabled], false)
  20. assert %Conn{
  21. status: 404,
  22. resp_body: "Not Found"
  23. } = get(conn, "/proxy/hhgfh/eeeee")
  24. assert %Conn{
  25. status: 404,
  26. resp_body: "Not Found"
  27. } = get(conn, "/proxy/hhgfh/eeee/fff")
  28. end
  29. test "it returns 403 for invalid signature", %{conn: conn, url: url} do
  30. Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")
  31. %{path: path} = URI.parse(url)
  32. assert %Conn{
  33. status: 403,
  34. resp_body: "Forbidden"
  35. } = get(conn, path)
  36. assert %Conn{
  37. status: 403,
  38. resp_body: "Forbidden"
  39. } = get(conn, "/proxy/hhgfh/eeee")
  40. assert %Conn{
  41. status: 403,
  42. resp_body: "Forbidden"
  43. } = get(conn, "/proxy/hhgfh/eeee/fff")
  44. end
  45. test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do
  46. invalid_url = String.replace(url, "test.png", "test-file.png")
  47. response = get(conn, invalid_url)
  48. assert response.status == 302
  49. assert redirected_to(response) == url
  50. end
  51. test "it performs ReverseProxy.call with valid signature", %{conn: conn, url: url} do
  52. with_mock Pleroma.ReverseProxy,
  53. call: fn _conn, _url, _opts -> %Conn{status: :success} end do
  54. assert %Conn{status: :success} = get(conn, url)
  55. end
  56. end
  57. test "it returns 404 when url is in banned_urls cache", %{conn: conn, url: url} do
  58. MediaProxy.put_in_banned_urls("https://google.fn/test.png")
  59. with_mock Pleroma.ReverseProxy,
  60. call: fn _conn, _url, _opts -> %Conn{status: :success} end do
  61. assert %Conn{status: 404, resp_body: "Not Found"} = get(conn, url)
  62. end
  63. end
  64. end
  65. describe "Media Preview Proxy" do
  66. setup do
  67. clear_config([:media_proxy, :enabled], true)
  68. clear_config([:media_preview_proxy, :enabled], true)
  69. clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
  70. original_url = "https://google.fn/test.png"
  71. [
  72. url: MediaProxy.encode_preview_url(original_url),
  73. media_proxy_url: MediaProxy.encode_url(original_url)
  74. ]
  75. end
  76. test "returns 404 when media proxy is disabled", %{conn: conn} do
  77. clear_config([:media_proxy, :enabled], false)
  78. assert %Conn{
  79. status: 404,
  80. resp_body: "Not Found"
  81. } = get(conn, "/proxy/preview/hhgfh/eeeee")
  82. assert %Conn{
  83. status: 404,
  84. resp_body: "Not Found"
  85. } = get(conn, "/proxy/preview/hhgfh/fff")
  86. end
  87. test "returns 404 when disabled", %{conn: conn} do
  88. clear_config([:media_preview_proxy, :enabled], false)
  89. assert %Conn{
  90. status: 404,
  91. resp_body: "Not Found"
  92. } = get(conn, "/proxy/preview/hhgfh/eeeee")
  93. assert %Conn{
  94. status: 404,
  95. resp_body: "Not Found"
  96. } = get(conn, "/proxy/preview/hhgfh/fff")
  97. end
  98. test "it returns 403 for invalid signature", %{conn: conn, url: url} do
  99. Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")
  100. %{path: path} = URI.parse(url)
  101. assert %Conn{
  102. status: 403,
  103. resp_body: "Forbidden"
  104. } = get(conn, path)
  105. assert %Conn{
  106. status: 403,
  107. resp_body: "Forbidden"
  108. } = get(conn, "/proxy/preview/hhgfh/eeee")
  109. assert %Conn{
  110. status: 403,
  111. resp_body: "Forbidden"
  112. } = get(conn, "/proxy/preview/hhgfh/eeee/fff")
  113. end
  114. test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do
  115. invalid_url = String.replace(url, "test.png", "test-file.png")
  116. response = get(conn, invalid_url)
  117. assert response.status == 302
  118. assert redirected_to(response) == url
  119. end
  120. test "responds with 424 Failed Dependency if HEAD request to media proxy fails", %{
  121. conn: conn,
  122. url: url,
  123. media_proxy_url: media_proxy_url
  124. } do
  125. Tesla.Mock.mock(fn
  126. %{method: "head", url: ^media_proxy_url} ->
  127. %Tesla.Env{status: 500, body: ""}
  128. end)
  129. response = get(conn, url)
  130. assert response.status == 424
  131. assert response.resp_body == "Can't fetch HTTP headers (HTTP 500)."
  132. end
  133. test "redirects to media proxy URI on unsupported content type", %{
  134. conn: conn,
  135. url: url,
  136. media_proxy_url: media_proxy_url
  137. } do
  138. Tesla.Mock.mock(fn
  139. %{method: "head", url: ^media_proxy_url} ->
  140. %Tesla.Env{status: 200, body: "", headers: [{"content-type", "application/pdf"}]}
  141. end)
  142. response = get(conn, url)
  143. assert response.status == 302
  144. assert redirected_to(response) == media_proxy_url
  145. end
  146. test "with `static=true` and GIF image preview requested, responds with JPEG image", %{
  147. conn: conn,
  148. url: url,
  149. media_proxy_url: media_proxy_url
  150. } do
  151. # Setting a high :min_content_length to ensure this scenario is not affected by its logic
  152. clear_config([:media_preview_proxy, :min_content_length], 1_000_000_000)
  153. Tesla.Mock.mock(fn
  154. %{method: "head", url: ^media_proxy_url} ->
  155. %Tesla.Env{
  156. status: 200,
  157. body: "",
  158. headers: [{"content-type", "image/gif"}, {"content-length", "1001718"}]
  159. }
  160. %{method: :get, url: ^media_proxy_url} ->
  161. %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.gif")}
  162. end)
  163. response = get(conn, url <> "?static=true")
  164. assert response.status == 200
  165. assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"]
  166. assert response.resp_body != ""
  167. end
  168. test "with GIF image preview requested and no `static` param, redirects to media proxy URI",
  169. %{
  170. conn: conn,
  171. url: url,
  172. media_proxy_url: media_proxy_url
  173. } do
  174. Tesla.Mock.mock(fn
  175. %{method: "head", url: ^media_proxy_url} ->
  176. %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/gif"}]}
  177. end)
  178. response = get(conn, url)
  179. assert response.status == 302
  180. assert redirected_to(response) == media_proxy_url
  181. end
  182. test "with `static` param and non-GIF image preview requested, " <>
  183. "redirects to media preview proxy URI without `static` param",
  184. %{
  185. conn: conn,
  186. url: url,
  187. media_proxy_url: media_proxy_url
  188. } do
  189. Tesla.Mock.mock(fn
  190. %{method: "head", url: ^media_proxy_url} ->
  191. %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]}
  192. end)
  193. response = get(conn, url <> "?static=true")
  194. assert response.status == 302
  195. assert redirected_to(response) == url
  196. end
  197. test "with :min_content_length setting not matched by Content-Length header, " <>
  198. "redirects to media proxy URI",
  199. %{
  200. conn: conn,
  201. url: url,
  202. media_proxy_url: media_proxy_url
  203. } do
  204. clear_config([:media_preview_proxy, :min_content_length], 100_000)
  205. Tesla.Mock.mock(fn
  206. %{method: "head", url: ^media_proxy_url} ->
  207. %Tesla.Env{
  208. status: 200,
  209. body: "",
  210. headers: [{"content-type", "image/gif"}, {"content-length", "5000"}]
  211. }
  212. end)
  213. response = get(conn, url)
  214. assert response.status == 302
  215. assert redirected_to(response) == media_proxy_url
  216. end
  217. test "thumbnails PNG images into PNG", %{
  218. conn: conn,
  219. url: url,
  220. media_proxy_url: media_proxy_url
  221. } do
  222. Tesla.Mock.mock(fn
  223. %{method: "head", url: ^media_proxy_url} ->
  224. %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/png"}]}
  225. %{method: :get, url: ^media_proxy_url} ->
  226. %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.png")}
  227. end)
  228. response = get(conn, url)
  229. assert response.status == 200
  230. assert Conn.get_resp_header(response, "content-type") == ["image/png"]
  231. assert response.resp_body != ""
  232. end
  233. test "thumbnails JPEG images into JPEG", %{
  234. conn: conn,
  235. url: url,
  236. media_proxy_url: media_proxy_url
  237. } do
  238. Tesla.Mock.mock(fn
  239. %{method: "head", url: ^media_proxy_url} ->
  240. %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]}
  241. %{method: :get, url: ^media_proxy_url} ->
  242. %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")}
  243. end)
  244. response = get(conn, url)
  245. assert response.status == 200
  246. assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"]
  247. assert response.resp_body != ""
  248. end
  249. test "redirects to media proxy URI in case of thumbnailing error", %{
  250. conn: conn,
  251. url: url,
  252. media_proxy_url: media_proxy_url
  253. } do
  254. Tesla.Mock.mock(fn
  255. %{method: "head", url: ^media_proxy_url} ->
  256. %Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]}
  257. %{method: :get, url: ^media_proxy_url} ->
  258. %Tesla.Env{status: 200, body: "<html><body>error</body></html>"}
  259. end)
  260. response = get(conn, url)
  261. assert response.status == 302
  262. assert redirected_to(response) == media_proxy_url
  263. end
  264. end
  265. end