Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 41 additions & 8 deletions lib/open_api_spex/plug/swagger_ui.ex
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ defmodule OpenApiSpex.Plug.SwaggerUI do
}
return request;
}
<%= for {k, v} <- Map.drop(config, [:path, :oauth, :csp_nonce_assign_key]) do %>
<%= for {k, v} <- Map.drop(config, [:path, :paths, :oauth, :csp_nonce_assign_key]) do %>
, <%= camelize(k) %>: <%= encode_config(camelize(k), v) %>
<% end %>
};
Expand Down Expand Up @@ -259,15 +259,48 @@ defmodule OpenApiSpex.Plug.SwaggerUI do
end

if Code.ensure_loaded?(Phoenix.Controller) do
defp supplement_config(%{oauth2_redirect_url: {:endpoint_url, path}} = config, conn) do
endpoint_module = Phoenix.Controller.endpoint_module(conn)
url = Path.join(endpoint_module.url(), path)
Map.put(config, :oauth2_redirect_url, url)
defp supplement_config(config, conn) do
case conn.private[:phoenix_endpoint] do
nil ->
config

endpoint_module ->
config
|> expand_oauth2_redirect_url(endpoint_module)
|> expand_spec_path(endpoint_module)
end
end

defp expand_oauth2_redirect_url(
%{oauth2_redirect_url: {:endpoint_url, path}} = config,
endpoint_module
) do
url = Path.join([endpoint_module.url(), endpoint_module.path("/"), path])
%{config | oauth2_redirect_url: url}
end

defp expand_oauth2_redirect_url(config, _endpoint_module), do: config

defp expand_spec_path(%{paths: paths} = config, endpoint_module) when is_list(paths) do
expanded_paths =
Enum.map(paths, fn {name, path} -> {name, maybe_expand_path(endpoint_module, path)} end)

%{config | paths: expanded_paths}
end

defp expand_spec_path(%{path: path} = config, endpoint_module) when is_binary(path) do
%{config | path: maybe_expand_path(endpoint_module, path)}
end

defp expand_spec_path(config, _endpoint_module), do: config

defp maybe_expand_path(endpoint_module, "/" <> _ = path) do
endpoint_module.path(path)
end
end

defp supplement_config(config, _conn) do
config
defp maybe_expand_path(_endpoint_module, path), do: path
else
defp supplement_config(config, _conn), do: config
end

def get_nonce(conn, config, type) do
Expand Down
62 changes: 61 additions & 1 deletion test/plug/swagger_ui_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
defmodule OpenApiSpec.Plug.SwaggerUITest do
defmodule OpenApiSpex.Plug.SwaggerUITest do
use ExUnit.Case

defmodule Endpoint do
use Phoenix.Endpoint, otp_app: :open_api_spex_test
end

alias OpenApiSpex.Plug.SwaggerUI

@opts SwaggerUI.init(path: "/ui")
Expand Down Expand Up @@ -46,4 +50,60 @@ defmodule OpenApiSpec.Plug.SwaggerUITest do
assert String.match?(conn.resp_body, ~r/<script.*nonce="my_script_nonce"/)
end
end

describe "phoenix endpoint path expansion" do
setup do
# Just to avoid warnings
Application.put_env(:open_api_spex_test, Endpoint, [])

start_supervised!(
{Endpoint, url: [scheme: "https", host: "example.com", port: 1234, path: "/my_app"]}
)

:ok
end

test "expands path with endpoint path prefix" do
conn = conn_with_endpoint() |> SwaggerUI.call(@opts)
assert conn.resp_body =~ ~r[pathname.+?/my_app/ui]
end

test "expands paths with endpoint path prefix" do
opts = SwaggerUI.init(paths: [latest: "/api/openapi", legacy: "/legacy/openapi"])
conn = conn_with_endpoint() |> SwaggerUI.call(opts)
assert conn.resp_body =~ "/my_app/api/openapi"
assert conn.resp_body =~ "/my_app/legacy/openapi"
end

test "does not expand absolute URLs in paths" do
opts =
SwaggerUI.init(paths: [local: "/api/openapi", remote: "http://other.host/api/openapi"])

conn = conn_with_endpoint() |> SwaggerUI.call(opts)
assert conn.resp_body =~ "/my_app/api/openapi"
assert conn.resp_body =~ "http://other.host/api/openapi"
end

test "expands oauth2_redirect_url with endpoint_url tuple" do
opts =
SwaggerUI.init(
path: "/ui",
oauth2_redirect_url: {:endpoint_url, "/oauth2-redirect.html"}
)

conn = conn_with_endpoint() |> SwaggerUI.call(opts)
assert conn.resp_body =~ "https://example.com:1234/my_app/oauth2-redirect.html"
end

test "does not expand path without phoenix endpoint" do
conn = Plug.Test.conn(:get, "/ui") |> SwaggerUI.call(@opts)
assert conn.resp_body =~ ~r[pathname.+?/ui]
refute conn.resp_body =~ "/my_app"
end
end

defp conn_with_endpoint(path \\ "/ui") do
Plug.Test.conn(:get, path)
|> Plug.Conn.put_private(:phoenix_endpoint, Endpoint)
end
end