Improve Teams response handling

This commit is contained in:
Alexandre de Souza 2025-07-07 18:46:18 -03:00
parent a5f2361f56
commit c327111dfd
No known key found for this signature in database
GPG key ID: E39228FFBA346545
2 changed files with 50 additions and 62 deletions

View file

@ -197,7 +197,7 @@ defmodule Livebook.Teams do
end end
@doc """ @doc """
Creates a new app deployment. Deploys the given app deployment.
""" """
@spec deploy_app(Team.t(), Teams.AppDeployment.t()) :: @spec deploy_app(Team.t(), Teams.AppDeployment.t()) ::
:ok :ok
@ -205,17 +205,9 @@ defmodule Livebook.Teams do
| {:transport_error, String.t()} | {:transport_error, String.t()}
def deploy_app(%Team{} = team, %Teams.AppDeployment{} = app_deployment) do def deploy_app(%Team{} = team, %Teams.AppDeployment{} = app_deployment) do
case Requests.deploy_app(team, app_deployment) do case Requests.deploy_app(team, app_deployment) do
{:ok, %{"id" => _id}} -> {:ok, %{"id" => _id}} -> :ok
:ok {:error, %{"errors" => errors}} -> {:error, add_external_errors(app_deployment, errors)}
any -> any
{:error, %{"errors" => %{"detail" => error}}} ->
{:error, add_external_errors(app_deployment, %{"file" => [error]})}
{:error, %{"errors" => errors}} ->
{:error, add_external_errors(app_deployment, errors)}
any ->
any
end end
end end

View file

@ -6,10 +6,14 @@ defmodule Livebook.Teams.Requests do
alias Livebook.Teams alias Livebook.Teams
@error_message "Something went wrong, try again later or please file a bug if it persists" @error_message "Something went wrong, try again later or please file a bug if it persists"
@unauthorized_error_message "You are not authorized to perform this action, make sure you have the access and you are not in a Livebook App Server/Offline instance"
@typep api_result :: {:ok, map()} | error_result() @typep api_result :: {:ok, map()} | error_result()
@typep error_result :: {:error, map() | String.t()} | {:transport_error, String.t()} @typep error_result :: {:error, map() | String.t()} | {:transport_error, String.t()}
@doc false
def error_message(), do: @error_message
@doc """ @doc """
Send a request to Livebook Team API to create a new org. Send a request to Livebook Team API to create a new org.
""" """
@ -237,61 +241,48 @@ defmodule Livebook.Teams.Requests do
do: {field, errors} do: {field, errors}
end end
@doc false
def error_message(), do: @error_message
defp post(path, json, team \\ nil) do defp post(path, json, team \\ nil) do
build_req() build_req(team)
|> add_team_auth(team) |> Req.post(url: path, json: json)
|> request(method: :post, url: path, json: json) |> handle_response()
|> dispatch_messages(team) |> dispatch_messages(team)
end end
defp put(path, json, team) do defp put(path, json, team) do
build_req() build_req(team)
|> add_team_auth(team) |> Req.put(url: path, json: json)
|> request(method: :put, url: path, json: json) |> handle_response()
|> dispatch_messages(team) |> dispatch_messages(team)
end end
defp delete(path, json, team) do defp delete(path, json, team) do
build_req() build_req(team)
|> add_team_auth(team) |> Req.delete(url: path, json: json)
|> request(method: :delete, url: path, json: json) |> handle_response()
|> dispatch_messages(team) |> dispatch_messages(team)
end end
defp get(path, params \\ %{}, team \\ nil) do defp get(path, params \\ %{}, team \\ nil) do
build_req() build_req(team)
|> add_team_auth(team) |> Req.get(url: path, params: params)
|> request(method: :get, url: path, params: params) |> handle_response()
end end
defp upload(path, content, params, team) do defp upload(path, content, params, team) do
build_req() build_req(team)
|> add_team_auth(team)
|> Req.Request.put_header("content-length", "#{byte_size(content)}") |> Req.Request.put_header("content-length", "#{byte_size(content)}")
|> request(method: :post, url: path, params: params, body: content) |> Req.Request.put_private(:deploy, true)
|> Req.post(url: path, params: params, body: content)
|> handle_response()
|> dispatch_messages(team) |> dispatch_messages(team)
end end
defp build_req() do defp build_req(team) do
base_url = URI.new!(Livebook.Config.teams_url()) Req.new(base_url: Livebook.Config.teams_url())
|> Req.Request.put_new_header("x-lb-version", Livebook.Config.app_version())
options = |> Req.Request.append_response_steps(transform_teams_response: &transform_response/1)
if userinfo = base_url.userinfo do
[
base_url: %{base_url | userinfo: nil},
auth: {:basic, userinfo}
]
else
[
base_url: base_url
]
end
Req.new([headers: [{"x-lb-version", Livebook.Config.app_version()}]] ++ options)
|> Livebook.Utils.req_attach_defaults() |> Livebook.Utils.req_attach_defaults()
|> add_team_auth(team)
end end
defp add_team_auth(req, nil), do: req defp add_team_auth(req, nil), do: req
@ -312,25 +303,24 @@ defmodule Livebook.Teams.Requests do
Req.Request.merge_options(req, auth: {:bearer, token}) Req.Request.merge_options(req, auth: {:bearer, token})
end end
defp request(req, opts) do defp transform_response({request, response}) do
case Req.request(req, opts) do case {request, response} do
{:ok, %{status: 204, body: body}} ->
{:ok, body}
{:ok, %{status: status} = response} when status in 200..299 -> {request, %{status: 400, body: %{"errors" => %{"detail" => error}}}}
{:ok, response.body} when request.private.deploy ->
{request, %{response | status: 422, body: %{"errors" => %{"file" => [error]}}}}
{:ok, %{status: status} = response} when status in [410, 422] ->
if json?(response),
do: {:error, response.body},
else: {:transport_error, response.body}
{:ok, %{status: 401}} ->
{:transport_error,
"You are not authorized to perform this action, make sure you have the access and you are not in a Livebook App Server/Offline instance"}
_otherwise -> _otherwise ->
{:transport_error, @error_message} {request, response}
end
end
defp handle_response(response) do
case response do
{:ok, %{status: status} = response} when status in 200..299 -> {:ok, response.body}
{:ok, %{status: status} = response} when status in [410, 422] -> return_error(response)
{:ok, %{status: 401}} -> {:transport_error, @unauthorized_error_message}
_otherwise -> {:transport_error, @error_message}
end end
end end
@ -351,6 +341,12 @@ defmodule Livebook.Teams.Requests do
defp dispatch_messages(result, _), do: result defp dispatch_messages(result, _), do: result
defp return_error(response) do
if json?(response),
do: {:error, response.body},
else: {:transport_error, response.body}
end
defp json?(response) do defp json?(response) do
"application/json; charset=utf-8" in Req.Response.get_header(response, "content-type") "application/json; charset=utf-8" in Req.Response.get_header(response, "content-type")
end end