forked from AkkomaGang/akkoma
[#2497] Configurability of :min_content_length (preview proxy). Refactoring, documentation, tests.
This commit is contained in:
parent
a781f41f96
commit
7cdbd91d83
8 changed files with 329 additions and 63 deletions
|
@ -444,7 +444,8 @@
|
||||||
enabled: false,
|
enabled: false,
|
||||||
thumbnail_max_width: 600,
|
thumbnail_max_width: 600,
|
||||||
thumbnail_max_height: 600,
|
thumbnail_max_height: 600,
|
||||||
image_quality: 85
|
image_quality: 85,
|
||||||
|
min_content_length: 100 * 1024
|
||||||
|
|
||||||
config :pleroma, :chat, enabled: true
|
config :pleroma, :chat, enabled: true
|
||||||
|
|
||||||
|
|
|
@ -1961,17 +1961,25 @@
|
||||||
%{
|
%{
|
||||||
key: :thumbnail_max_width,
|
key: :thumbnail_max_width,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Max width of preview thumbnail."
|
description:
|
||||||
|
"Max width of preview thumbnail for images (video preview always has original dimensions)."
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :thumbnail_max_height,
|
key: :thumbnail_max_height,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Max height of preview thumbnail."
|
description:
|
||||||
|
"Max height of preview thumbnail for images (video preview always has original dimensions)."
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
key: :image_quality,
|
key: :image_quality,
|
||||||
type: :integer,
|
type: :integer,
|
||||||
description: "Quality of the output. Ranges from 0 (min quality) to 100 (max quality)."
|
description: "Quality of the output. Ranges from 0 (min quality) to 100 (max quality)."
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :min_content_length,
|
||||||
|
type: :integer,
|
||||||
|
description:
|
||||||
|
"Min content length to perform preview, in bytes. If greater than 0, media smaller in size will be served as is, without thumbnailing."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -314,6 +314,14 @@ This section describe PWA manifest instance-specific values. Currently this opti
|
||||||
* `enabled`: Enables purge cache
|
* `enabled`: Enables purge cache
|
||||||
* `provider`: Which one of the [purge cache strategy](#purge-cache-strategy) to use.
|
* `provider`: Which one of the [purge cache strategy](#purge-cache-strategy) to use.
|
||||||
|
|
||||||
|
## :media_preview_proxy
|
||||||
|
|
||||||
|
* `enabled`: Enables proxying of remote media preview to the instance’s proxy. Requires enabled media proxy (`media_proxy/enabled`).
|
||||||
|
* `thumbnail_max_width`: Max width of preview thumbnail for images (video preview always has original dimensions).
|
||||||
|
* `thumbnail_max_height`: Max height of preview thumbnail for images (video preview always has original dimensions).
|
||||||
|
* `image_quality`: Quality of the output. Ranges from 0 (min quality) to 100 (max quality).
|
||||||
|
* `min_content_length`: Min content length to perform preview, in bytes. If greater than 0, media smaller in size will be served as is, without thumbnailing.
|
||||||
|
|
||||||
### Purge cache strategy
|
### Purge cache strategy
|
||||||
|
|
||||||
#### Pleroma.Web.MediaProxy.Invalidation.Script
|
#### Pleroma.Web.MediaProxy.Invalidation.Script
|
||||||
|
|
|
@ -58,6 +58,7 @@ defp prepare_image_resize_args(%{max_width: max_width, max_height: max_height} =
|
||||||
|
|
||||||
defp prepare_image_resize_args(_), do: {:error, :missing_options}
|
defp prepare_image_resize_args(_), do: {:error, :missing_options}
|
||||||
|
|
||||||
|
# Note: video thumbnail is intentionally not resized (always has original dimensions)
|
||||||
def video_framegrab(url) do
|
def video_framegrab(url) do
|
||||||
with executable when is_binary(executable) <- System.find_executable("ffmpeg"),
|
with executable when is_binary(executable) <- System.find_executable("ffmpeg"),
|
||||||
{:ok, env} <- HTTP.get(url, [], pool: :media),
|
{:ok, env} <- HTTP.get(url, [], pool: :media),
|
||||||
|
|
|
@ -12,8 +12,6 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyController do
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
alias Plug.Conn
|
alias Plug.Conn
|
||||||
|
|
||||||
@min_content_length_for_preview 100 * 1024
|
|
||||||
|
|
||||||
def remote(conn, %{"sig" => sig64, "url" => url64}) do
|
def remote(conn, %{"sig" => sig64, "url" => url64}) do
|
||||||
with {_, true} <- {:enabled, MediaProxy.enabled?()},
|
with {_, true} <- {:enabled, MediaProxy.enabled?()},
|
||||||
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
|
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
|
||||||
|
@ -37,7 +35,8 @@ def remote(conn, %{"sig" => sig64, "url" => url64}) do
|
||||||
|
|
||||||
def preview(%Conn{} = conn, %{"sig" => sig64, "url" => url64}) do
|
def preview(%Conn{} = conn, %{"sig" => sig64, "url" => url64}) do
|
||||||
with {_, true} <- {:enabled, MediaProxy.preview_enabled?()},
|
with {_, true} <- {:enabled, MediaProxy.preview_enabled?()},
|
||||||
{:ok, url} <- MediaProxy.decode_url(sig64, url64) do
|
{:ok, url} <- MediaProxy.decode_url(sig64, url64),
|
||||||
|
:ok <- MediaProxy.verify_request_path_and_url(conn, url) do
|
||||||
handle_preview(conn, url)
|
handle_preview(conn, url)
|
||||||
else
|
else
|
||||||
{:enabled, false} ->
|
{:enabled, false} ->
|
||||||
|
@ -59,8 +58,25 @@ defp handle_preview(conn, url) do
|
||||||
content_type = Tesla.get_header(head_response, "content-type")
|
content_type = Tesla.get_header(head_response, "content-type")
|
||||||
content_length = Tesla.get_header(head_response, "content-length")
|
content_length = Tesla.get_header(head_response, "content-length")
|
||||||
content_length = content_length && String.to_integer(content_length)
|
content_length = content_length && String.to_integer(content_length)
|
||||||
|
static = conn.params["static"] in ["true", true]
|
||||||
|
|
||||||
handle_preview(content_type, content_length, conn, media_proxy_url)
|
cond do
|
||||||
|
static and content_type == "image/gif" ->
|
||||||
|
handle_jpeg_preview(conn, media_proxy_url)
|
||||||
|
|
||||||
|
static ->
|
||||||
|
drop_static_param_and_redirect(conn)
|
||||||
|
|
||||||
|
content_type == "image/gif" ->
|
||||||
|
redirect(conn, external: media_proxy_url)
|
||||||
|
|
||||||
|
min_content_length_for_preview() > 0 and content_length > 0 and
|
||||||
|
content_length < min_content_length_for_preview() ->
|
||||||
|
redirect(conn, external: media_proxy_url)
|
||||||
|
|
||||||
|
true ->
|
||||||
|
handle_preview(content_type, conn, media_proxy_url)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
# If HEAD failed, redirecting to media proxy URI doesn't make much sense; returning an error
|
# If HEAD failed, redirecting to media proxy URI doesn't make much sense; returning an error
|
||||||
{_, %{status: status}} ->
|
{_, %{status: status}} ->
|
||||||
|
@ -74,58 +90,27 @@ defp handle_preview(conn, url) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_preview(
|
defp handle_preview("image/png" <> _ = _content_type, conn, media_proxy_url) do
|
||||||
"image/gif" = _content_type,
|
|
||||||
_content_length,
|
|
||||||
%{params: %{"static" => static}} = conn,
|
|
||||||
media_proxy_url
|
|
||||||
)
|
|
||||||
when static in ["true", true] do
|
|
||||||
handle_jpeg_preview(conn, media_proxy_url)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp handle_preview(
|
|
||||||
_content_type,
|
|
||||||
_content_length,
|
|
||||||
%{params: %{"static" => static}} = conn,
|
|
||||||
_media_proxy_url
|
|
||||||
)
|
|
||||||
when static in ["true", true] do
|
|
||||||
uri_without_static_param = UriHelper.modify_uri_params(current_url(conn), %{}, ["static"])
|
|
||||||
redirect(conn, external: uri_without_static_param)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp handle_preview("image/gif" = _content_type, _content_length, conn, media_proxy_url) do
|
|
||||||
redirect(conn, external: media_proxy_url)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp handle_preview("image/" <> _ = _content_type, content_length, conn, media_proxy_url)
|
|
||||||
when is_integer(content_length) and content_length > 0 and
|
|
||||||
content_length < @min_content_length_for_preview do
|
|
||||||
redirect(conn, external: media_proxy_url)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp handle_preview("image/png" <> _ = _content_type, _content_length, conn, media_proxy_url) do
|
|
||||||
handle_png_preview(conn, media_proxy_url)
|
handle_png_preview(conn, media_proxy_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_preview("image/" <> _ = _content_type, _content_length, conn, media_proxy_url) do
|
defp handle_preview("image/" <> _ = _content_type, conn, media_proxy_url) do
|
||||||
handle_jpeg_preview(conn, media_proxy_url)
|
handle_jpeg_preview(conn, media_proxy_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_preview("video/" <> _ = _content_type, _content_length, conn, media_proxy_url) do
|
defp handle_preview("video/" <> _ = _content_type, conn, media_proxy_url) do
|
||||||
handle_video_preview(conn, media_proxy_url)
|
handle_video_preview(conn, media_proxy_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_preview(_unsupported_content_type, _content_length, conn, media_proxy_url) do
|
defp handle_preview(_unsupported_content_type, conn, media_proxy_url) do
|
||||||
fallback_on_preview_error(conn, media_proxy_url)
|
fallback_on_preview_error(conn, media_proxy_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_png_preview(conn, media_proxy_url) do
|
defp handle_png_preview(conn, media_proxy_url) do
|
||||||
quality = Config.get!([:media_preview_proxy, :image_quality])
|
quality = Config.get!([:media_preview_proxy, :image_quality])
|
||||||
|
{thumbnail_max_width, thumbnail_max_height} = thumbnail_max_dimensions()
|
||||||
|
|
||||||
with {thumbnail_max_width, thumbnail_max_height} <- thumbnail_max_dimensions(),
|
with {:ok, thumbnail_binary} <-
|
||||||
{:ok, thumbnail_binary} <-
|
|
||||||
MediaHelper.image_resize(
|
MediaHelper.image_resize(
|
||||||
media_proxy_url,
|
media_proxy_url,
|
||||||
%{
|
%{
|
||||||
|
@ -146,9 +131,9 @@ defp handle_png_preview(conn, media_proxy_url) do
|
||||||
|
|
||||||
defp handle_jpeg_preview(conn, media_proxy_url) do
|
defp handle_jpeg_preview(conn, media_proxy_url) do
|
||||||
quality = Config.get!([:media_preview_proxy, :image_quality])
|
quality = Config.get!([:media_preview_proxy, :image_quality])
|
||||||
|
{thumbnail_max_width, thumbnail_max_height} = thumbnail_max_dimensions()
|
||||||
|
|
||||||
with {thumbnail_max_width, thumbnail_max_height} <- thumbnail_max_dimensions(),
|
with {:ok, thumbnail_binary} <-
|
||||||
{:ok, thumbnail_binary} <-
|
|
||||||
MediaHelper.image_resize(
|
MediaHelper.image_resize(
|
||||||
media_proxy_url,
|
media_proxy_url,
|
||||||
%{max_width: thumbnail_max_width, max_height: thumbnail_max_height, quality: quality}
|
%{max_width: thumbnail_max_width, max_height: thumbnail_max_height, quality: quality}
|
||||||
|
@ -174,6 +159,15 @@ defp handle_video_preview(conn, media_proxy_url) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp drop_static_param_and_redirect(conn) do
|
||||||
|
uri_without_static_param =
|
||||||
|
conn
|
||||||
|
|> current_url()
|
||||||
|
|> UriHelper.modify_uri_params(%{}, ["static"])
|
||||||
|
|
||||||
|
redirect(conn, external: uri_without_static_param)
|
||||||
|
end
|
||||||
|
|
||||||
defp fallback_on_preview_error(conn, media_proxy_url) do
|
defp fallback_on_preview_error(conn, media_proxy_url) do
|
||||||
redirect(conn, external: media_proxy_url)
|
redirect(conn, external: media_proxy_url)
|
||||||
end
|
end
|
||||||
|
@ -189,7 +183,7 @@ defp put_preview_response_headers(
|
||||||
end
|
end
|
||||||
|
|
||||||
defp thumbnail_max_dimensions do
|
defp thumbnail_max_dimensions do
|
||||||
config = Config.get([:media_preview_proxy], [])
|
config = media_preview_proxy_config()
|
||||||
|
|
||||||
thumbnail_max_width = Keyword.fetch!(config, :thumbnail_max_width)
|
thumbnail_max_width = Keyword.fetch!(config, :thumbnail_max_width)
|
||||||
thumbnail_max_height = Keyword.fetch!(config, :thumbnail_max_height)
|
thumbnail_max_height = Keyword.fetch!(config, :thumbnail_max_height)
|
||||||
|
@ -197,6 +191,14 @@ defp thumbnail_max_dimensions do
|
||||||
{thumbnail_max_width, thumbnail_max_height}
|
{thumbnail_max_width, thumbnail_max_height}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp min_content_length_for_preview do
|
||||||
|
Keyword.get(media_preview_proxy_config(), :min_content_length, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp media_preview_proxy_config do
|
||||||
|
Config.get!([:media_preview_proxy])
|
||||||
|
end
|
||||||
|
|
||||||
defp media_proxy_opts do
|
defp media_proxy_opts do
|
||||||
Config.get([:media_proxy, :proxy_opts], [])
|
Config.get([:media_proxy, :proxy_opts], [])
|
||||||
end
|
end
|
||||||
|
|
BIN
test/fixtures/image.gif
vendored
Executable file
BIN
test/fixtures/image.gif
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 978 KiB |
BIN
test/fixtures/image.png
vendored
Executable file
BIN
test/fixtures/image.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 102 KiB |
|
@ -14,7 +14,15 @@ defmodule Pleroma.Web.MediaProxy.MediaProxyControllerTest do
|
||||||
on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
|
on_exit(fn -> Cachex.clear(:banned_urls_cache) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns 404 when MediaProxy disabled", %{conn: conn} do
|
describe "Media Proxy" do
|
||||||
|
setup do
|
||||||
|
clear_config([:media_proxy, :enabled], true)
|
||||||
|
clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
|
||||||
|
|
||||||
|
[url: MediaProxy.encode_url("https://google.fn/test.png")]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns 404 when disabled", %{conn: conn} do
|
||||||
clear_config([:media_proxy, :enabled], false)
|
clear_config([:media_proxy, :enabled], false)
|
||||||
|
|
||||||
assert %Conn{
|
assert %Conn{
|
||||||
|
@ -28,13 +36,6 @@ test "it returns 404 when MediaProxy disabled", %{conn: conn} do
|
||||||
} = get(conn, "/proxy/hhgfh/eeee/fff")
|
} = get(conn, "/proxy/hhgfh/eeee/fff")
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "" do
|
|
||||||
setup do
|
|
||||||
clear_config([:media_proxy, :enabled], true)
|
|
||||||
clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
|
|
||||||
[url: MediaProxy.encode_url("https://google.fn/test.png")]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "it returns 403 for invalid signature", %{conn: conn, url: url} do
|
test "it returns 403 for invalid signature", %{conn: conn, url: url} do
|
||||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")
|
Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")
|
||||||
%{path: path} = URI.parse(url)
|
%{path: path} = URI.parse(url)
|
||||||
|
@ -55,7 +56,7 @@ test "it returns 403 for invalid signature", %{conn: conn, url: url} do
|
||||||
} = get(conn, "/proxy/hhgfh/eeee/fff")
|
} = get(conn, "/proxy/hhgfh/eeee/fff")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "redirects on valid url when filename is invalidated", %{conn: conn, url: url} do
|
test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do
|
||||||
invalid_url = String.replace(url, "test.png", "test-file.png")
|
invalid_url = String.replace(url, "test.png", "test-file.png")
|
||||||
response = get(conn, invalid_url)
|
response = get(conn, invalid_url)
|
||||||
assert response.status == 302
|
assert response.status == 302
|
||||||
|
@ -78,4 +79,249 @@ test "it returns 404 when url is in banned_urls cache", %{conn: conn, url: url}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "Media Preview Proxy" do
|
||||||
|
setup do
|
||||||
|
clear_config([:media_proxy, :enabled], true)
|
||||||
|
clear_config([:media_preview_proxy, :enabled], true)
|
||||||
|
clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000")
|
||||||
|
|
||||||
|
original_url = "https://google.fn/test.png"
|
||||||
|
|
||||||
|
[
|
||||||
|
url: MediaProxy.encode_preview_url(original_url),
|
||||||
|
media_proxy_url: MediaProxy.encode_url(original_url)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 404 when media proxy is disabled", %{conn: conn} do
|
||||||
|
clear_config([:media_proxy, :enabled], false)
|
||||||
|
|
||||||
|
assert %Conn{
|
||||||
|
status: 404,
|
||||||
|
resp_body: "Not Found"
|
||||||
|
} = get(conn, "/proxy/preview/hhgfh/eeeee")
|
||||||
|
|
||||||
|
assert %Conn{
|
||||||
|
status: 404,
|
||||||
|
resp_body: "Not Found"
|
||||||
|
} = get(conn, "/proxy/preview/hhgfh/fff")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 404 when disabled", %{conn: conn} do
|
||||||
|
clear_config([:media_preview_proxy, :enabled], false)
|
||||||
|
|
||||||
|
assert %Conn{
|
||||||
|
status: 404,
|
||||||
|
resp_body: "Not Found"
|
||||||
|
} = get(conn, "/proxy/preview/hhgfh/eeeee")
|
||||||
|
|
||||||
|
assert %Conn{
|
||||||
|
status: 404,
|
||||||
|
resp_body: "Not Found"
|
||||||
|
} = get(conn, "/proxy/preview/hhgfh/fff")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns 403 for invalid signature", %{conn: conn, url: url} do
|
||||||
|
Pleroma.Config.put([Pleroma.Web.Endpoint, :secret_key_base], "000")
|
||||||
|
%{path: path} = URI.parse(url)
|
||||||
|
|
||||||
|
assert %Conn{
|
||||||
|
status: 403,
|
||||||
|
resp_body: "Forbidden"
|
||||||
|
} = get(conn, path)
|
||||||
|
|
||||||
|
assert %Conn{
|
||||||
|
status: 403,
|
||||||
|
resp_body: "Forbidden"
|
||||||
|
} = get(conn, "/proxy/preview/hhgfh/eeee")
|
||||||
|
|
||||||
|
assert %Conn{
|
||||||
|
status: 403,
|
||||||
|
resp_body: "Forbidden"
|
||||||
|
} = get(conn, "/proxy/preview/hhgfh/eeee/fff")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "redirects to valid url when filename is invalidated", %{conn: conn, url: url} do
|
||||||
|
invalid_url = String.replace(url, "test.png", "test-file.png")
|
||||||
|
response = get(conn, invalid_url)
|
||||||
|
assert response.status == 302
|
||||||
|
assert redirected_to(response) == url
|
||||||
|
end
|
||||||
|
|
||||||
|
test "responds with 424 Failed Dependency if HEAD request to media proxy fails", %{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 500, body: ""}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url)
|
||||||
|
assert response.status == 424
|
||||||
|
assert response.resp_body == "Can't fetch HTTP headers (HTTP 500)."
|
||||||
|
end
|
||||||
|
|
||||||
|
test "redirects to media proxy URI on unsupported content type", %{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: "", headers: [{"content-type", "application/pdf"}]}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url)
|
||||||
|
assert response.status == 302
|
||||||
|
assert redirected_to(response) == media_proxy_url
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with `static=true` and GIF image preview requested, responds with JPEG image", %{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
# Setting a high :min_content_length to ensure this scenario is not affected by its logic
|
||||||
|
clear_config([:media_preview_proxy, :min_content_length], 1_000_000_000)
|
||||||
|
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: "",
|
||||||
|
headers: [{"content-type", "image/gif"}, {"content-length", "1001718"}]
|
||||||
|
}
|
||||||
|
|
||||||
|
%{method: :get, url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/image.gif")}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url <> "?static=true")
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"]
|
||||||
|
assert response.resp_body != ""
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with GIF image preview requested and no `static` param, redirects to media proxy URI",
|
||||||
|
%{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/gif"}]}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url)
|
||||||
|
|
||||||
|
assert response.status == 302
|
||||||
|
assert redirected_to(response) == media_proxy_url
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with `static` param and non-GIF image preview requested, " <>
|
||||||
|
"redirects to media preview proxy URI without `static` param",
|
||||||
|
%{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url <> "?static=true")
|
||||||
|
|
||||||
|
assert response.status == 302
|
||||||
|
assert redirected_to(response) == url
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with :min_content_length setting not matched by Content-Length header, " <>
|
||||||
|
"redirects to media proxy URI",
|
||||||
|
%{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
clear_config([:media_preview_proxy, :min_content_length], 100_000)
|
||||||
|
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: "",
|
||||||
|
headers: [{"content-type", "image/gif"}, {"content-length", "5000"}]
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url)
|
||||||
|
|
||||||
|
assert response.status == 302
|
||||||
|
assert redirected_to(response) == media_proxy_url
|
||||||
|
end
|
||||||
|
|
||||||
|
test "thumbnails PNG images into PNG", %{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/png"}]}
|
||||||
|
|
||||||
|
%{method: :get, url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/image.png")}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url)
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
assert Conn.get_resp_header(response, "content-type") == ["image/png"]
|
||||||
|
assert response.resp_body != ""
|
||||||
|
end
|
||||||
|
|
||||||
|
test "thumbnails JPEG images into JPEG", %{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]}
|
||||||
|
|
||||||
|
%{method: :get, url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url)
|
||||||
|
|
||||||
|
assert response.status == 200
|
||||||
|
assert Conn.get_resp_header(response, "content-type") == ["image/jpeg"]
|
||||||
|
assert response.resp_body != ""
|
||||||
|
end
|
||||||
|
|
||||||
|
test "redirects to media proxy URI in case of thumbnailing error", %{
|
||||||
|
conn: conn,
|
||||||
|
url: url,
|
||||||
|
media_proxy_url: media_proxy_url
|
||||||
|
} do
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{method: "head", url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: "", headers: [{"content-type", "image/jpeg"}]}
|
||||||
|
|
||||||
|
%{method: :get, url: ^media_proxy_url} ->
|
||||||
|
%Tesla.Env{status: 200, body: "<html><body>error</body></html>"}
|
||||||
|
end)
|
||||||
|
|
||||||
|
response = get(conn, url)
|
||||||
|
|
||||||
|
assert response.status == 302
|
||||||
|
assert redirected_to(response) == media_proxy_url
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue