mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-25 12:56:13 +08:00
Attempt to load a flat remote URL as a relative path fallback (#1428)
This commit is contained in:
parent
1799f0a303
commit
b20ac022a8
2 changed files with 61 additions and 6 deletions
|
|
@ -6,7 +6,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
import Livebook.Utils, only: [format_bytes: 1]
|
||||
|
||||
alias Livebook.{Sessions, Session, Delta, Notebook, Runtime, LiveMarkdown}
|
||||
alias Livebook.Notebook.Cell
|
||||
alias Livebook.Notebook.{Cell, ContentLoader}
|
||||
alias Livebook.JSInterop
|
||||
|
||||
@impl true
|
||||
|
|
@ -1242,7 +1242,8 @@ defmodule LivebookWeb.SessionLive do
|
|||
|> redirect_to_self()
|
||||
|
||||
resolution_location ->
|
||||
origin = Notebook.ContentLoader.resolve_location(resolution_location, relative_path)
|
||||
origin = ContentLoader.resolve_location(resolution_location, relative_path)
|
||||
fallback_locations = fallback_relative_locations(resolution_location, relative_path)
|
||||
|
||||
case session_id_by_location(origin) do
|
||||
{:ok, session_id} ->
|
||||
|
|
@ -1252,7 +1253,7 @@ defmodule LivebookWeb.SessionLive do
|
|||
push_redirect(socket, to: redirect_path)
|
||||
|
||||
{:error, :none} ->
|
||||
open_notebook(socket, origin, requested_url)
|
||||
open_notebook(socket, origin, fallback_locations, requested_url)
|
||||
|
||||
{:error, :many} ->
|
||||
origin_str =
|
||||
|
|
@ -1282,12 +1283,12 @@ defmodule LivebookWeb.SessionLive do
|
|||
end
|
||||
end
|
||||
|
||||
defp open_notebook(socket, origin, requested_url) do
|
||||
case Notebook.ContentLoader.fetch_content_from_location(origin) do
|
||||
defp open_notebook(socket, origin, fallback_locations, requested_url) do
|
||||
case fetch_content_with_fallbacks(origin, fallback_locations) do
|
||||
{:ok, content} ->
|
||||
{notebook, messages} = Livebook.LiveMarkdown.notebook_from_livemd(content)
|
||||
|
||||
# If the current session has no path, fork the notebook
|
||||
# If the current session has no file, fork the notebook
|
||||
fork? = socket.private.data.file == nil
|
||||
{file, notebook} = file_and_notebook(fork?, origin, notebook)
|
||||
url_hash = get_url_hash(requested_url)
|
||||
|
|
@ -1308,6 +1309,32 @@ defmodule LivebookWeb.SessionLive do
|
|||
end
|
||||
end
|
||||
|
||||
def fallback_relative_locations({:file, _}, _relative_path), do: []
|
||||
|
||||
def fallback_relative_locations(resolution_location, relative_path) do
|
||||
# Other locations to check in case the relative location doesn't
|
||||
# exist. For example, in ExDoc all pages (including notebooks) are
|
||||
# flat, regardless of how they are structured in the file system
|
||||
|
||||
name = relative_path |> String.split("/") |> Enum.at(-1)
|
||||
flat_location = ContentLoader.resolve_location(resolution_location, name)
|
||||
[flat_location]
|
||||
end
|
||||
|
||||
defp fetch_content_with_fallbacks(location, fallbacks) do
|
||||
case ContentLoader.fetch_content_from_location(location) do
|
||||
{:ok, content} ->
|
||||
{:ok, content}
|
||||
|
||||
error ->
|
||||
fallbacks
|
||||
|> Enum.reject(&(&1 == location))
|
||||
|> Enum.find_value(error, fn fallback ->
|
||||
with {:error, _} <- ContentLoader.fetch_content_from_location(fallback), do: nil
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
defp file_and_notebook(fork?, origin, notebook)
|
||||
defp file_and_notebook(false, {:file, file}, notebook), do: {file, notebook}
|
||||
defp file_and_notebook(true, {:file, _file}, notebook), do: {nil, Notebook.forked(notebook)}
|
||||
|
|
|
|||
|
|
@ -834,6 +834,34 @@ defmodule LivebookWeb.SessionLiveTest do
|
|||
close_session_by_id(session_id)
|
||||
end
|
||||
|
||||
test "when a remote URL cannot be loaded, attempts to resolve a flat URL", %{conn: conn} do
|
||||
bypass = Bypass.open()
|
||||
|
||||
# Multi-level path is not available
|
||||
Bypass.expect_once(bypass, "GET", "/nested/path/to/notebook.livemd", fn conn ->
|
||||
Plug.Conn.resp(conn, 500, "Error")
|
||||
end)
|
||||
|
||||
# A flat path is available
|
||||
Bypass.expect_once(bypass, "GET", "/notebook.livemd", fn conn ->
|
||||
conn
|
||||
|> Plug.Conn.put_resp_content_type("text/plain")
|
||||
|> Plug.Conn.resp(200, "# My notebook")
|
||||
end)
|
||||
|
||||
index_url = url(bypass.port) <> "/index.livemd"
|
||||
{:ok, session} = Sessions.create_session(origin: {:url, index_url})
|
||||
|
||||
assert {:error, {:live_redirect, %{to: "/sessions/" <> session_id}}} =
|
||||
result = live(conn, "/sessions/#{session.id}/nested/path/to/notebook.livemd")
|
||||
|
||||
{:ok, view, _} = follow_redirect(result, conn)
|
||||
assert render(view) =~ "My notebook"
|
||||
|
||||
Session.close(session.pid)
|
||||
close_session_by_id(session_id)
|
||||
end
|
||||
|
||||
test "renders an error message if relative remote notebook cannot be loaded", %{conn: conn} do
|
||||
bypass = Bypass.open()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue