Skip to content

Commit b0fd334

Browse files
Riuzaky77Maxtiangolo
authored
Add CLI option --forwarded-allow-ips (#113)
Co-authored-by: Max <maximilianotorres@theluxergroup.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
1 parent d7aa2a0 commit b0fd334

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/fastapi_cli/cli.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def _run(
9696
command: str,
9797
app: Union[str, None] = None,
9898
proxy_headers: bool = False,
99+
forwarded_allow_ips: Union[str, None] = None,
99100
) -> None:
100101
with get_rich_toolkit() as toolkit:
101102
server_type = "development" if command == "dev" else "production"
@@ -177,6 +178,7 @@ def _run(
177178
workers=workers,
178179
root_path=root_path,
179180
proxy_headers=proxy_headers,
181+
forwarded_allow_ips=forwarded_allow_ips,
180182
log_config=get_uvicorn_log_config(),
181183
)
182184

@@ -226,6 +228,12 @@ def dev(
226228
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info."
227229
),
228230
] = True,
231+
forwarded_allow_ips: Annotated[
232+
Union[str, None],
233+
typer.Option(
234+
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
235+
),
236+
] = None,
229237
) -> Any:
230238
"""
231239
Run a [bold]FastAPI[/bold] app in [yellow]development[/yellow] mode. 🧪
@@ -261,6 +269,7 @@ def dev(
261269
app=app,
262270
command="dev",
263271
proxy_headers=proxy_headers,
272+
forwarded_allow_ips=forwarded_allow_ips,
264273
)
265274

266275

@@ -315,6 +324,12 @@ def run(
315324
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info."
316325
),
317326
] = True,
327+
forwarded_allow_ips: Annotated[
328+
Union[str, None],
329+
typer.Option(
330+
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
331+
),
332+
] = None,
318333
) -> Any:
319334
"""
320335
Run a [bold]FastAPI[/bold] app in [green]production[/green] mode. 🚀
@@ -351,6 +366,7 @@ def run(
351366
app=app,
352367
command="run",
353368
proxy_headers=proxy_headers,
369+
forwarded_allow_ips=forwarded_allow_ips,
354370
)
355371

356372

tests/test_cli.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def test_dev() -> None:
3030
"workers": None,
3131
"root_path": "",
3232
"proxy_headers": True,
33+
"forwarded_allow_ips": None,
3334
"log_config": get_uvicorn_log_config(),
3435
}
3536
assert "Using import string: single_file_app:app" in result.output
@@ -59,6 +60,7 @@ def test_dev_package() -> None:
5960
"workers": None,
6061
"root_path": "",
6162
"proxy_headers": True,
63+
"forwarded_allow_ips": None,
6264
"log_config": get_uvicorn_log_config(),
6365
}
6466
assert "Using import string: nested_package.package:app" in result.output
@@ -107,6 +109,7 @@ def test_dev_args() -> None:
107109
"workers": None,
108110
"root_path": "/api",
109111
"proxy_headers": False,
112+
"forwarded_allow_ips": None,
110113
"log_config": get_uvicorn_log_config(),
111114
}
112115
assert "Using import string: single_file_app:api" in result.output
@@ -134,6 +137,33 @@ def test_run() -> None:
134137
"workers": None,
135138
"root_path": "",
136139
"proxy_headers": True,
140+
"forwarded_allow_ips": None,
141+
"log_config": get_uvicorn_log_config(),
142+
}
143+
assert "Using import string: single_file_app:app" in result.output
144+
assert "Starting production server 🚀" in result.output
145+
assert "Server started at http://0.0.0.0:8000" in result.output
146+
assert "Documentation at http://0.0.0.0:8000/docs" in result.output
147+
148+
149+
def test_run_trust_proxy() -> None:
150+
with changing_dir(assets_path):
151+
with patch.object(uvicorn, "run") as mock_run:
152+
result = runner.invoke(
153+
app, ["run", "single_file_app.py", "--forwarded-allow-ips", "*"]
154+
)
155+
assert result.exit_code == 0, result.output
156+
assert mock_run.called
157+
assert mock_run.call_args
158+
assert mock_run.call_args.kwargs == {
159+
"app": "single_file_app:app",
160+
"host": "0.0.0.0",
161+
"port": 8000,
162+
"reload": False,
163+
"workers": None,
164+
"root_path": "",
165+
"proxy_headers": True,
166+
"forwarded_allow_ips": "*",
137167
"log_config": get_uvicorn_log_config(),
138168
}
139169
assert "Using import string: single_file_app:app" in result.output
@@ -179,6 +209,7 @@ def test_run_args() -> None:
179209
"workers": 2,
180210
"root_path": "/api",
181211
"proxy_headers": False,
212+
"forwarded_allow_ips": None,
182213
"log_config": get_uvicorn_log_config(),
183214
}
184215

0 commit comments

Comments
 (0)