mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-09-20 10:05:57 +08:00
Group proxy endpoints under a shared prefix (#2666)
This commit is contained in:
parent
e299cc9aba
commit
29c2877272
|
@ -17,7 +17,7 @@ defmodule LivebookWeb.AppAuthLive do
|
|||
{:ok, push_navigate(socket, to: authenticated_path(params))}
|
||||
end
|
||||
|
||||
defp authenticated_path(%{"slug" => slug, "id" => id}), do: ~p"/apps/#{slug}/#{id}"
|
||||
defp authenticated_path(%{"slug" => slug, "id" => id}), do: ~p"/apps/#{slug}/sessions/#{id}"
|
||||
defp authenticated_path(%{"slug" => slug}), do: ~p"/apps/#{slug}"
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -16,7 +16,7 @@ defmodule LivebookWeb.AppLive do
|
|||
else
|
||||
{:ok, pid} = Livebook.Apps.fetch_pid(slug)
|
||||
session_id = Livebook.App.get_session_id(pid, user: socket.assigns.current_user)
|
||||
{:ok, push_navigate(socket, to: ~p"/apps/#{slug}/#{session_id}")}
|
||||
{:ok, push_navigate(socket, to: ~p"/apps/#{slug}/sessions/#{session_id}")}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -70,7 +70,7 @@ defmodule LivebookWeb.AppLive do
|
|||
<div :if={@app_settings.show_existing_sessions} class="w-full flex flex-col space-y-4">
|
||||
<.link
|
||||
:for={app_session <- active_sessions(@app.sessions)}
|
||||
navigate={~p"/apps/#{@app.slug}/#{app_session.id}"}
|
||||
navigate={~p"/apps/#{@app.slug}/sessions/#{app_session.id}"}
|
||||
class="px-4 py-3 border border-gray-200 rounded-xl text-gray-800 pointer hover:bg-gray-50 flex justify-between"
|
||||
>
|
||||
<span>
|
||||
|
@ -98,7 +98,8 @@ defmodule LivebookWeb.AppLive do
|
|||
session_id =
|
||||
Livebook.App.get_session_id(socket.assigns.app.pid, user: socket.assigns.current_user)
|
||||
|
||||
{:noreply, push_navigate(socket, to: ~p"/apps/#{socket.assigns.app.slug}/#{session_id}")}
|
||||
{:noreply,
|
||||
push_navigate(socket, to: ~p"/apps/#{socket.assigns.app.slug}/sessions/#{session_id}")}
|
||||
end
|
||||
|
||||
def handle_params(_params, _url, socket), do: {:noreply, socket}
|
||||
|
|
|
@ -126,7 +126,10 @@ defmodule LivebookWeb.AppSessionLive do
|
|||
</.link>
|
||||
</.menu_item>
|
||||
<.menu_item :if={@data_view.show_source}>
|
||||
<.link patch={~p"/apps/#{@data_view.slug}/#{@session.id}/source"} role="menuitem">
|
||||
<.link
|
||||
patch={~p"/apps/#{@data_view.slug}/sessions/#{@session.id}/source"}
|
||||
role="menuitem"
|
||||
>
|
||||
<.remix_icon icon="code-line" />
|
||||
<span>View source</span>
|
||||
</.link>
|
||||
|
@ -211,7 +214,7 @@ defmodule LivebookWeb.AppSessionLive do
|
|||
id="source-modal"
|
||||
show
|
||||
width={:big}
|
||||
patch={~p"/apps/#{@data_view.slug}/#{@session.id}"}
|
||||
patch={~p"/apps/#{@data_view.slug}/sessions/#{@session.id}"}
|
||||
>
|
||||
<.live_component
|
||||
module={LivebookWeb.AppSessionLive.SourceComponent}
|
||||
|
|
|
@ -157,7 +157,7 @@ defmodule LivebookWeb.AppsDashboardLive do
|
|||
<.icon_button
|
||||
disabled={app_session.app_status.lifecycle != :active}
|
||||
aria-label="open app"
|
||||
href={~p"/apps/#{app.slug}/#{app_session.id}"}
|
||||
href={~p"/apps/#{app.slug}/sessions/#{app_session.id}"}
|
||||
>
|
||||
<.remix_icon icon="link" />
|
||||
</.icon_button>
|
||||
|
|
|
@ -171,7 +171,7 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
<.icon_button
|
||||
disabled={app_session.app_status.lifecycle != :active}
|
||||
aria-label="open app"
|
||||
href={~p"/apps/#{@app.slug}/#{app_session.id}"}
|
||||
href={~p"/apps/#{@app.slug}/sessions/#{app_session.id}"}
|
||||
>
|
||||
<.remix_icon icon="link" />
|
||||
</.icon_button>
|
||||
|
|
|
@ -8,16 +8,20 @@ defmodule LivebookWeb.ProxyPlug do
|
|||
@impl true
|
||||
def init(opts), do: opts
|
||||
|
||||
# We group all routes under the /proxy namespace, so that it's easy
|
||||
# to expose them when Livebook runs behind an authentication proxy.
|
||||
# The users may want to expose them, for example, to use as webhooks
|
||||
|
||||
@impl true
|
||||
def call(%{path_info: ["sessions", id, "proxy" | path_info]} = conn, _opts) do
|
||||
def call(%{path_info: ["proxy", "sessions", id | path_info]} = conn, _opts) do
|
||||
session = fetch_session!(id)
|
||||
Livebook.Session.reset_auto_shutdown(session.pid)
|
||||
proxy_handler_spec = fetch_proxy_handler_spec!(session)
|
||||
conn = prepare_conn(conn, path_info, ["sessions", id, "proxy"])
|
||||
conn = prepare_conn(conn, path_info, ["proxy", "sessions", id])
|
||||
call_proxy_handler(proxy_handler_spec, conn)
|
||||
end
|
||||
|
||||
def call(%{path_info: ["apps", slug, id, "proxy" | path_info]} = conn, _opts) do
|
||||
def call(%{path_info: ["proxy", "apps", slug, "sessions", id | path_info]} = conn, _opts) do
|
||||
app = fetch_app!(slug)
|
||||
|
||||
unless Enum.any?(app.sessions, &(&1.id == id)) do
|
||||
|
@ -28,11 +32,11 @@ defmodule LivebookWeb.ProxyPlug do
|
|||
Livebook.Session.reset_auto_shutdown(session.pid)
|
||||
await_app_session_ready(app, session.id)
|
||||
proxy_handler_spec = fetch_proxy_handler_spec!(session)
|
||||
conn = prepare_conn(conn, path_info, ["apps", slug, id, "proxy"])
|
||||
conn = prepare_conn(conn, path_info, ["proxy", "apps", slug, "sessions", id])
|
||||
call_proxy_handler(proxy_handler_spec, conn)
|
||||
end
|
||||
|
||||
def call(%{path_info: ["apps", slug, "proxy" | path_info]} = conn, _opts) do
|
||||
def call(%{path_info: ["proxy", "apps", slug | path_info]} = conn, _opts) do
|
||||
app = fetch_app!(slug)
|
||||
|
||||
if app.multi_session do
|
||||
|
@ -46,7 +50,7 @@ defmodule LivebookWeb.ProxyPlug do
|
|||
Livebook.Session.reset_auto_shutdown(session.pid)
|
||||
await_app_session_ready(app, session.id)
|
||||
proxy_handler_spec = fetch_proxy_handler_spec!(session)
|
||||
conn = prepare_conn(conn, path_info, ["apps", slug, "proxy"])
|
||||
conn = prepare_conn(conn, path_info, ["proxy", "apps", slug])
|
||||
call_proxy_handler(proxy_handler_spec, conn)
|
||||
end
|
||||
|
||||
|
|
|
@ -146,8 +146,8 @@ defmodule LivebookWeb.Router do
|
|||
live "/apps/:slug/new", AppLive, :new_session
|
||||
live "/apps/:slug/authenticate", AppAuthLive, :page
|
||||
|
||||
live "/apps/:slug/:id", AppSessionLive, :page
|
||||
live "/apps/:slug/:id/source", AppSessionLive, :source
|
||||
live "/apps/:slug/sessions/:id", AppSessionLive, :page
|
||||
live "/apps/:slug/sessions/:id/source", AppSessionLive, :source
|
||||
|
||||
live "/apps", AppsLive, :page
|
||||
end
|
||||
|
|
|
@ -108,7 +108,7 @@ defmodule LivebookWeb.AppAuthLiveTest do
|
|||
|
||||
{:ok, view, _} =
|
||||
conn
|
||||
|> live(~p"/apps/#{slug}/#{session_id}")
|
||||
|> live(~p"/apps/#{slug}/sessions/#{session_id}")
|
||||
|> follow_redirect(conn)
|
||||
|
||||
view
|
||||
|
@ -118,7 +118,7 @@ defmodule LivebookWeb.AppAuthLiveTest do
|
|||
assert_push_event(view, "persist_app_auth", %{"slug" => ^slug, "token" => _token})
|
||||
|
||||
assert {:error, {:live_redirect, %{to: to}}} = render_hook(view, "app_auth_persisted")
|
||||
assert to == ~p"/apps/#{slug}/#{session_id}"
|
||||
assert to == ~p"/apps/#{slug}/sessions/#{session_id}"
|
||||
end
|
||||
|
||||
test "redirects to the app page when authenticating in Livebook", %{conn: conn, slug: slug} do
|
||||
|
|
|
@ -19,7 +19,7 @@ defmodule LivebookWeb.AppLiveTest do
|
|||
assert_receive {:app_updated, %{pid: ^app_pid, sessions: [%{id: session_id}]}}
|
||||
|
||||
{:error, {:live_redirect, %{to: to}}} = live(conn, ~p"/apps/#{slug}")
|
||||
assert to == ~p"/apps/#{slug}/#{session_id}"
|
||||
assert to == ~p"/apps/#{slug}/sessions/#{session_id}"
|
||||
|
||||
App.close(app_pid)
|
||||
end
|
||||
|
@ -59,8 +59,8 @@ defmodule LivebookWeb.AppLiveTest do
|
|||
|
||||
{:ok, view, _} = live(conn, ~p"/apps/#{slug}")
|
||||
|
||||
assert render(view) =~ ~p"/apps/#{slug}/#{session_id1}"
|
||||
refute render(view) =~ ~p"/apps/#{slug}/#{session_id2}"
|
||||
assert render(view) =~ ~p"/apps/#{slug}/sessions/#{session_id1}"
|
||||
refute render(view) =~ ~p"/apps/#{slug}/sessions/#{session_id2}"
|
||||
|
||||
# Create a new app session
|
||||
session_id3 = App.get_session_id(app_pid)
|
||||
|
@ -68,7 +68,7 @@ defmodule LivebookWeb.AppLiveTest do
|
|||
assert_receive {:app_updated,
|
||||
%{pid: ^app_pid, sessions: [%{id: ^session_id3, pid: session_pid3}, _, _]}}
|
||||
|
||||
assert render(view) =~ ~p"/apps/#{slug}/#{session_id3}"
|
||||
assert render(view) =~ ~p"/apps/#{slug}/sessions/#{session_id3}"
|
||||
|
||||
# Deactivate the app session
|
||||
Livebook.Session.app_deactivate(session_pid3)
|
||||
|
@ -79,8 +79,8 @@ defmodule LivebookWeb.AppLiveTest do
|
|||
sessions: [%{app_status: %{lifecycle: :deactivated}}, _, _]
|
||||
}}
|
||||
|
||||
assert render(view) =~ ~p"/apps/#{slug}/#{session_id1}"
|
||||
refute render(view) =~ ~p"/apps/#{slug}/#{session_id3}"
|
||||
assert render(view) =~ ~p"/apps/#{slug}/sessions/#{session_id1}"
|
||||
refute render(view) =~ ~p"/apps/#{slug}/sessions/#{session_id3}"
|
||||
|
||||
App.close(app_pid)
|
||||
end
|
||||
|
@ -104,7 +104,7 @@ defmodule LivebookWeb.AppLiveTest do
|
|||
|
||||
assert_receive {:app_updated, %{pid: ^app_pid, sessions: [%{id: session_id}]}}
|
||||
|
||||
assert to == ~p"/apps/#{slug}/#{session_id}"
|
||||
assert to == ~p"/apps/#{slug}/sessions/#{session_id}"
|
||||
|
||||
App.close(app_pid)
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ defmodule LivebookWeb.AppSessionLiveTest do
|
|||
|
||||
app_pid = deploy_notebook_sync(notebook)
|
||||
|
||||
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/nonexistent")
|
||||
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/sessions/nonexistent")
|
||||
assert render(view) =~ "This app session does not exist"
|
||||
assert render(view) =~ ~p"/apps/#{slug}"
|
||||
|
||||
|
@ -39,7 +39,7 @@ defmodule LivebookWeb.AppSessionLiveTest do
|
|||
assert_receive {:app_updated,
|
||||
%{pid: ^app_pid, sessions: [%{app_status: %{lifecycle: :deactivated}}]}}
|
||||
|
||||
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/#{session_id}")
|
||||
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/sessions/#{session_id}")
|
||||
assert render(view) =~ "This app session does not exist"
|
||||
assert render(view) =~ ~p"/apps/#{slug}"
|
||||
|
||||
|
@ -59,7 +59,7 @@ defmodule LivebookWeb.AppSessionLiveTest do
|
|||
assert_receive {:app_updated,
|
||||
%{pid: ^app_pid, sessions: [%{id: session_id, pid: session_pid}]}}
|
||||
|
||||
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/#{session_id}")
|
||||
{:ok, view, _} = live(conn, ~p"/apps/#{slug}/sessions/#{session_id}")
|
||||
|
||||
Livebook.Session.app_deactivate(session_pid)
|
||||
|
||||
|
|
|
@ -2246,7 +2246,7 @@ defmodule LivebookWeb.SessionLiveTest do
|
|||
assert_receive {:app_updated,
|
||||
%{slug: ^slug, sessions: [%{app_status: %{lifecycle: :deactivated}}]}}
|
||||
|
||||
assert render(view) =~ "/apps/#{slug}/#{app_session.id}"
|
||||
assert render(view) =~ "/apps/#{slug}/sessions/#{app_session.id}"
|
||||
|
||||
view
|
||||
|> element(~s/[data-el-app-info] button[aria-label="terminate app session"]/)
|
||||
|
@ -2254,7 +2254,7 @@ defmodule LivebookWeb.SessionLiveTest do
|
|||
|
||||
assert_receive {:app_updated, %{slug: ^slug, sessions: []}}
|
||||
|
||||
refute render(view) =~ "/apps/#{slug}/#{app_session.id}"
|
||||
refute render(view) =~ "/apps/#{slug}/sessions/#{app_session.id}"
|
||||
|
||||
Livebook.App.close(app.pid)
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
session_id = Livebook.Utils.random_long_id()
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, "/sessions/#{session_id}/proxy/foo/bar")
|
||||
get(conn, "/proxy/sessions/#{session_id}/foo/bar")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -21,7 +21,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
{:ok, session} = Sessions.create_session()
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, "/sessions/#{session.id}/proxy/foo/bar")
|
||||
get(conn, "/proxy/sessions/#{session.id}/foo/bar")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -38,7 +38,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
{:add_cell_evaluation_response, _, ^cell_id, _, %{errored: false}}},
|
||||
4_000
|
||||
|
||||
url = "/sessions/#{session.id}/proxy/"
|
||||
url = "/proxy/sessions/#{session.id}/"
|
||||
|
||||
assert text_response(get(conn, url), 200) == "used GET method"
|
||||
assert text_response(post(conn, url), 200) == "used POST method"
|
||||
|
@ -56,7 +56,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
session_id = Livebook.Utils.random_long_id()
|
||||
|
||||
assert_error_sent 404, fn ->
|
||||
get(conn, "/apps/#{slug}/#{session_id}/proxy/foo/bar")
|
||||
get(conn, "/proxy/apps/#{slug}/sessions/#{session_id}/foo/bar")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -73,7 +73,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
assert_receive {:app_updated,
|
||||
%{slug: ^slug, sessions: [%{id: id, app_status: %{execution: :executed}}]}}
|
||||
|
||||
url = "/apps/#{slug}/#{id}/proxy/"
|
||||
url = "/proxy/apps/#{slug}/sessions/#{id}/"
|
||||
|
||||
assert text_response(get(conn, url), 200) == "used GET method"
|
||||
assert text_response(post(conn, url), 200) == "used POST method"
|
||||
|
@ -82,7 +82,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
assert text_response(delete(conn, url), 200) == "used DELETE method"
|
||||
|
||||
# Generic path also works for single-session apps
|
||||
url = "/apps/#{slug}/proxy/"
|
||||
url = "/proxy/apps/#{slug}/"
|
||||
|
||||
assert text_response(get(conn, url), 200) == "used GET method"
|
||||
end
|
||||
|
@ -107,7 +107,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
# The app is configured with auto shutdown, so the session will
|
||||
# start only once requested. We should wait until it executes
|
||||
# and then proxy the request as usual
|
||||
url = "/apps/#{slug}/proxy/"
|
||||
url = "/proxy/apps/#{slug}/"
|
||||
|
||||
assert text_response(get(conn, url), 200) == "used GET method"
|
||||
end
|
||||
|
@ -130,7 +130,7 @@ defmodule LivebookWeb.ProxyPlugTest do
|
|||
assert_receive {:app_created, %{pid: ^pid, slug: ^slug, sessions: []}}
|
||||
|
||||
assert_error_sent 400, fn ->
|
||||
get(conn, "/apps/#{slug}/proxy/foo/bar")
|
||||
get(conn, "/proxy/apps/#{slug}/foo/bar")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue