Skip to content

Commit 2c8602c

Browse files
committed
Handle 401/403
1 parent cf5c9da commit 2c8602c

File tree

4 files changed

+34
-31
lines changed

4 files changed

+34
-31
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dependencies = [
3737
"rignore >= 0.5.1",
3838
"httpx >= 0.27.0",
3939
"pydantic >= 2.8.2",
40-
"rich-toolkit >= 0.6.3",
40+
"rich-toolkit >= 0.7.0",
4141
"pydantic >= 1.6.1",
4242
]
4343

src/fastapi_cli/commands/whoami.py

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import logging
22
from typing import Any
33

4-
import httpx
5-
import typer
64
from rich import print
5+
from rich_toolkit.progress import Progress
76

87
from fastapi_cli.utils.api import APIClient
98
from fastapi_cli.utils.auth import is_logged_in
9+
from fastapi_cli.utils.cli import handle_http_errors
1010

1111
logger = logging.getLogger(__name__)
1212

@@ -17,29 +17,10 @@ def whoami() -> Any:
1717
return
1818

1919
with APIClient() as client:
20-
try:
21-
response = client.get("/users/me")
22-
except httpx.ReadTimeout:
23-
print(
24-
"[red]Error[/]: The request to the FastAPI Cloud server timed out. Please try again later."
25-
)
26-
raise typer.Exit(code=1) from None
27-
28-
if response.status_code in (401, 403):
29-
print(
30-
"[red]Error[/]: The specified token is not valid. Use [blue]`fastapi login`[/] to generate a new token."
31-
)
32-
raise typer.Exit(code=1) from None
33-
34-
try:
35-
response.raise_for_status()
36-
except httpx.HTTPError as e:
37-
logger.debug("Error: %s", e)
38-
39-
print(
40-
"[red]Error[/]: Something went wrong while contacting the FastAPI Cloud server. Please try again later."
41-
)
42-
raise typer.Exit(code=1) from None
20+
with Progress(title="⚡Fetching profile", transient=True) as progress:
21+
with handle_http_errors(progress, message=""):
22+
response = client.get("/users/me")
23+
response.raise_for_status()
4324

4425
data = response.json()
4526

src/fastapi_cli/utils/cli.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Generator, Optional
44

55
import typer
6-
from httpx import HTTPError, ReadTimeout
6+
from httpx import HTTPError, HTTPStatusError, ReadTimeout
77
from rich_toolkit import RichToolkit, RichToolkitTheme
88
from rich_toolkit.progress import Progress
99
from rich_toolkit.styles import TaggedStyle
@@ -47,10 +47,14 @@ def handle_http_errors(
4747
except HTTPError as e:
4848
logger.debug(e)
4949

50-
message = (
51-
message
52-
or f"Something went wrong while contacting the FastAPI Cloud server. Please try again later. \n\n{e}"
53-
)
50+
if isinstance(e, HTTPStatusError) and e.response.status_code in (401, 403):
51+
message = "The specified token is not valid. Use `fastapi login` to generate a new token."
52+
53+
else:
54+
message = (
55+
message
56+
or f"Something went wrong while contacting the FastAPI Cloud server. Please try again later. \n\n{e}"
57+
)
5458

5559
progress.set_error(message)
5660

tests/test_cli_deploy.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,24 @@ def test_shows_error_when_trying_to_get_teams(
7272
assert "Error fetching teams. Please try again later" in result.output
7373

7474

75+
@pytest.mark.respx(base_url=settings.base_api_url)
76+
def test_handles_invalid_auth(
77+
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
78+
) -> None:
79+
steps = [ENTER]
80+
81+
respx_mock.get("/teams/").mock(return_value=Response(401))
82+
83+
with changing_dir(tmp_path), patch("click.getchar") as mock_getchar:
84+
mock_getchar.side_effect = steps
85+
86+
result = runner.invoke(app, ["deploy"])
87+
88+
assert result.exit_code == 1
89+
90+
assert "The specified token is not valid" in result.output
91+
92+
7593
@pytest.mark.respx(base_url=settings.base_api_url)
7694
def test_shows_teams(
7795
logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter

0 commit comments

Comments
 (0)