Skip to content

Commit 5539f29

Browse files
committed
feat: all cli options available as FASTAPI_<opt> *BREAKING* recently added PORT envvar
Signed-off-by: Damien Degois <[email protected]>
1 parent 7d048df commit 5539f29

File tree

2 files changed

+78
-40
lines changed

2 files changed

+78
-40
lines changed

src/fastapi_cli/cli.py

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -195,39 +195,44 @@ def dev(
195195
path: Annotated[
196196
Union[Path, None],
197197
typer.Argument(
198-
help="A path to a Python file or package directory (with [blue]__init__.py[/blue] files) containing a [bold]FastAPI[/bold] app. If not provided, a default set of paths will be tried."
198+
help="A path to a Python file or package directory (with [blue]__init__.py[/blue] files) containing a [bold]FastAPI[/bold] app. If not provided, a default set of paths will be tried.",
199+
envvar="FASTAPI_PATH",
199200
),
200201
] = None,
201202
*,
202203
host: Annotated[
203204
str,
204205
typer.Option(
205-
help="The host to serve on. For local development in localhost use [blue]127.0.0.1[/blue]. To enable public access, e.g. in a container, use all the IP addresses available with [blue]0.0.0.0[/blue]."
206+
help="The host to serve on. For local development in localhost use [blue]127.0.0.1[/blue]. To enable public access, e.g. in a container, use all the IP addresses available with [blue]0.0.0.0[/blue].",
207+
envvar="FASTAPI_HOST",
206208
),
207209
] = "127.0.0.1",
208210
port: Annotated[
209211
int,
210212
typer.Option(
211213
help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app.",
212-
envvar="PORT",
214+
envvar="FASTAPI_PORT",
213215
),
214216
] = 8000,
215217
reload: Annotated[
216218
bool,
217219
typer.Option(
218-
help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development."
220+
help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development.",
221+
envvar="FASTAPI_RELOAD",
219222
),
220223
] = True,
221224
root_path: Annotated[
222225
str,
223226
typer.Option(
224-
help="The root path is used to tell your app that it is being served to the outside world with some [bold]path prefix[/bold] set up in some termination proxy or similar."
227+
help="The root path is used to tell your app that it is being served to the outside world with some [bold]path prefix[/bold] set up in some termination proxy or similar.",
228+
envvar="FASTAPI_ROOTPATH",
225229
),
226230
] = "",
227231
app: Annotated[
228232
Union[str, None],
229233
typer.Option(
230-
help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically."
234+
help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically.",
235+
envvar="FASTAPI_APP",
231236
),
232237
] = None,
233238
entrypoint: Annotated[
@@ -236,18 +241,21 @@ def dev(
236241
"--entrypoint",
237242
"-e",
238243
help="The FastAPI app import string in the format 'some.importable_module:app_name'.",
244+
envvar="FASTAPI_ENTRYPOINT",
239245
),
240246
] = None,
241247
proxy_headers: Annotated[
242248
bool,
243249
typer.Option(
244-
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info."
250+
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info.",
251+
envvar="FASTAPI_PROXY_HEADERS",
245252
),
246253
] = True,
247254
forwarded_allow_ips: Annotated[
248255
Union[str, None],
249256
typer.Option(
250-
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
257+
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything.",
258+
envvar="FASTAPI_FORWARDED_ALLOW_IPS",
251259
),
252260
] = None,
253261
) -> Any:
@@ -295,45 +303,51 @@ def run(
295303
path: Annotated[
296304
Union[Path, None],
297305
typer.Argument(
298-
help="A path to a Python file or package directory (with [blue]__init__.py[/blue] files) containing a [bold]FastAPI[/bold] app. If not provided, a default set of paths will be tried."
306+
help="A path to a Python file or package directory (with [blue]__init__.py[/blue] files) containing a [bold]FastAPI[/bold] app. If not provided, a default set of paths will be tried.",
307+
envvar="FASTAPI_PATH",
299308
),
300309
] = None,
301310
*,
302311
host: Annotated[
303312
str,
304313
typer.Option(
305-
help="The host to serve on. For local development in localhost use [blue]127.0.0.1[/blue]. To enable public access, e.g. in a container, use all the IP addresses available with [blue]0.0.0.0[/blue]."
314+
help="The host to serve on. For local development in localhost use [blue]127.0.0.1[/blue]. To enable public access, e.g. in a container, use all the IP addresses available with [blue]0.0.0.0[/blue].",
315+
envvar="FASTAPI_HOST",
306316
),
307317
] = "0.0.0.0",
308318
port: Annotated[
309319
int,
310320
typer.Option(
311321
help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app.",
312-
envvar="PORT",
322+
envvar="FASTAPI_PORT",
313323
),
314324
] = 8000,
315325
reload: Annotated[
316326
bool,
317327
typer.Option(
318-
help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development."
328+
help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development.",
329+
envvar="FASTAPI_RELOAD",
319330
),
320331
] = False,
321332
workers: Annotated[
322333
Union[int, None],
323334
typer.Option(
324-
help="Use multiple worker processes. Mutually exclusive with the --reload flag."
335+
help="Use multiple worker processes. Mutually exclusive with the --reload flag.",
336+
envvar="FASTAPI_WORKERS",
325337
),
326338
] = None,
327339
root_path: Annotated[
328340
str,
329341
typer.Option(
330-
help="The root path is used to tell your app that it is being served to the outside world with some [bold]path prefix[/bold] set up in some termination proxy or similar."
342+
help="The root path is used to tell your app that it is being served to the outside world with some [bold]path prefix[/bold] set up in some termination proxy or similar.",
343+
envvar="FASTAPI_ROOTPATH",
331344
),
332345
] = "",
333346
app: Annotated[
334347
Union[str, None],
335348
typer.Option(
336-
help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically."
349+
help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically.",
350+
envvar="FASTAPI_APP",
337351
),
338352
] = None,
339353
entrypoint: Annotated[
@@ -342,18 +356,21 @@ def run(
342356
"--entrypoint",
343357
"-e",
344358
help="The FastAPI app import string in the format 'some.importable_module:app_name'.",
359+
envvar="FASTAPI_ENTRYPOINT",
345360
),
346361
] = None,
347362
proxy_headers: Annotated[
348363
bool,
349364
typer.Option(
350-
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info."
365+
help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info.",
366+
envvar="FASTAPI_PROXY_HEADERS",
351367
),
352368
] = True,
353369
forwarded_allow_ips: Annotated[
354370
Union[str, None],
355371
typer.Option(
356-
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything."
372+
help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything.",
373+
envvar="FASTAPI_FORWARDED_ALLOW_IPS",
357374
),
358375
] = None,
359376
) -> Any:

tests/test_cli.py

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -126,26 +126,36 @@ def test_dev_env_vars() -> None:
126126
with changing_dir(assets_path):
127127
with patch.object(uvicorn, "run") as mock_run:
128128
result = runner.invoke(
129-
app, ["dev", "single_file_app.py"], env={"PORT": "8111"}
129+
app,
130+
["dev", "single_file_app.py"],
131+
env={
132+
"FASTAPI_HOST": "127.0.0.2",
133+
"FASTAPI_PORT": "8111",
134+
"FASTAPI_RELOAD": "false",
135+
"FASTAPI_ROOTPATH": "/api",
136+
"FASTAPI_APP": "api",
137+
"FASTAPI_PROXY_HEADERS": "false",
138+
"FASTAPI_FORWARDED_ALLOW_IPS": "*",
139+
},
130140
)
131141
assert result.exit_code == 0, result.output
132142
assert mock_run.called
133143
assert mock_run.call_args
134144
assert mock_run.call_args.kwargs == {
135-
"app": "single_file_app:app",
136-
"host": "127.0.0.1",
145+
"app": "single_file_app:api",
146+
"host": "127.0.0.2",
137147
"port": 8111,
138-
"reload": True,
148+
"reload": False,
139149
"workers": None,
140-
"root_path": "",
141-
"proxy_headers": True,
142-
"forwarded_allow_ips": None,
150+
"root_path": "/api",
151+
"proxy_headers": False,
152+
"forwarded_allow_ips": "*",
143153
"log_config": get_uvicorn_log_config(),
144154
}
145-
assert "Using import string: single_file_app:app" in result.output
155+
assert "Using import string: single_file_app:api" in result.output
146156
assert "Starting development server 🚀" in result.output
147-
assert "Server started at http://127.0.0.1:8111" in result.output
148-
assert "Documentation at http://127.0.0.1:8111/docs" in result.output
157+
assert "Server started at http://127.0.0.2:8111" in result.output
158+
assert "Documentation at http://127.0.0.2:8111/docs" in result.output
149159
assert (
150160
"Running in development mode, for production use: fastapi run"
151161
in result.output
@@ -163,7 +173,7 @@ def test_dev_env_vars_and_args() -> None:
163173
"--port",
164174
"8080",
165175
],
166-
env={"PORT": "8111"},
176+
env={"FASTAPI_PORT": "8111"},
167177
)
168178
assert result.exit_code == 0, result.output
169179
assert mock_run.called
@@ -294,26 +304,37 @@ def test_run_env_vars() -> None:
294304
with changing_dir(assets_path):
295305
with patch.object(uvicorn, "run") as mock_run:
296306
result = runner.invoke(
297-
app, ["run", "single_file_app.py"], env={"PORT": "8111"}
307+
app,
308+
["run", "single_file_app.py"],
309+
env={
310+
"FASTAPI_HOST": "192.168.1.1",
311+
"FASTAPI_PORT": "8111",
312+
"FASTAPI_RELOAD": "true",
313+
"FASTAPI_WORKERS": "4",
314+
"FASTAPI_ROOTPATH": "/api",
315+
"FASTAPI_APP": "api",
316+
"FASTAPI_PROXY_HEADERS": "false",
317+
"FASTAPI_FORWARDED_ALLOW_IPS": "*",
318+
},
298319
)
299320
assert result.exit_code == 0, result.output
300321
assert mock_run.called
301322
assert mock_run.call_args
302323
assert mock_run.call_args.kwargs == {
303-
"app": "single_file_app:app",
304-
"host": "0.0.0.0",
324+
"app": "single_file_app:api",
325+
"host": "192.168.1.1",
305326
"port": 8111,
306-
"reload": False,
307-
"workers": None,
308-
"root_path": "",
309-
"proxy_headers": True,
310-
"forwarded_allow_ips": None,
327+
"reload": True,
328+
"workers": 4,
329+
"root_path": "/api",
330+
"proxy_headers": False,
331+
"forwarded_allow_ips": "*",
311332
"log_config": get_uvicorn_log_config(),
312333
}
313-
assert "Using import string: single_file_app:app" in result.output
334+
assert "Using import string: single_file_app:api" in result.output
314335
assert "Starting production server 🚀" in result.output
315-
assert "Server started at http://0.0.0.0:8111" in result.output
316-
assert "Documentation at http://0.0.0.0:8111/docs" in result.output
336+
assert "Server started at http://192.168.1.1:8111" in result.output
337+
assert "Documentation at http://192.168.1.1:8111/docs" in result.output
317338

318339

319340
def test_run_env_vars_and_args() -> None:
@@ -327,7 +348,7 @@ def test_run_env_vars_and_args() -> None:
327348
"--port",
328349
"8080",
329350
],
330-
env={"PORT": "8111"},
351+
env={"FASTAPI_PORT": "8111"},
331352
)
332353
assert result.exit_code == 0, result.output
333354
assert mock_run.called

0 commit comments

Comments
 (0)