]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:sparkles: Re-export utils from Starlette (#1064)
authorSebastián Ramírez <tiangolo@gmail.com>
Sun, 1 Mar 2020 20:49:20 +0000 (21:49 +0100)
committerGitHub <noreply@github.com>
Sun, 1 Mar 2020 20:49:20 +0000 (21:49 +0100)
* :sparkles: Re-export main features used from Starlette to simplify developer's code

* :recycle: Refactor Starlette exports

* :recycle: Refactor tutorial examples to use re-exported utils from Starlette

* :memo: Add examples for all middlewares

* :memo: Add new docs for middlewares

* :memo: Add examples for custom responses

* :memo: Extend docs for custom responses

* :memo: Update docs and add notes explaining re-exports from Starlette everywhere

* :bento: Update screenshot for HTTP status

* :wrench: Update MkDocs config with new content

* :recycle: Refactor tests to use re-exported utils from Starlette

* :sparkles: Re-export WebSocketDisconnect from Starlette for tests

* :white_check_mark: Add extra tests for extra re-exported middleware

* :white_check_mark: Add tests for re-exported responses from Starlette

* :sparkles: Add docs about mounting WSGI apps

* :heavy_plus_sign: Add Flask as a dependency to test WSGIMiddleware

* :white_check_mark: Test WSGIMiddleware example

267 files changed:
docs/advanced/additional-status-codes.md
docs/advanced/advanced-dependencies.md
docs/advanced/custom-request-and-route.md
docs/advanced/custom-response.md
docs/advanced/extending-openapi.md
docs/advanced/middleware.md [new file with mode: 0644]
docs/advanced/response-change-status-code.md
docs/advanced/response-cookies.md
docs/advanced/response-directly.md
docs/advanced/response-headers.md
docs/advanced/security/http-basic-auth.md
docs/advanced/security/oauth2-scopes.md
docs/advanced/templates.md
docs/advanced/using-request-directly.md
docs/advanced/websockets.md
docs/advanced/wsgi.md [new file with mode: 0644]
docs/img/tutorial/response-status-code/image02.png
docs/src/additional_responses/tutorial001.py
docs/src/additional_responses/tutorial002.py
docs/src/additional_responses/tutorial003.py
docs/src/additional_responses/tutorial004.py
docs/src/additional_status_codes/tutorial001.py
docs/src/advanced_middleware/tutorial001.py [new file with mode: 0644]
docs/src/advanced_middleware/tutorial002.py [new file with mode: 0644]
docs/src/advanced_middleware/tutorial003.py [new file with mode: 0644]
docs/src/app_testing/test_main.py
docs/src/app_testing/test_main_b.py
docs/src/app_testing/tutorial001.py
docs/src/app_testing/tutorial002.py
docs/src/app_testing/tutorial003.py
docs/src/cors/tutorial001.py
docs/src/custom_request_and_route/tutorial001.py
docs/src/custom_request_and_route/tutorial002.py
docs/src/custom_request_and_route/tutorial003.py
docs/src/custom_response/tutorial001.py
docs/src/custom_response/tutorial002.py
docs/src/custom_response/tutorial003.py
docs/src/custom_response/tutorial004.py
docs/src/custom_response/tutorial005.py [new file with mode: 0644]
docs/src/custom_response/tutorial006.py [new file with mode: 0644]
docs/src/custom_response/tutorial007.py [new file with mode: 0644]
docs/src/custom_response/tutorial008.py [new file with mode: 0644]
docs/src/custom_response/tutorial009.py [new file with mode: 0644]
docs/src/dependency_testing/tutorial001.py
docs/src/extending_openapi/tutorial002.py
docs/src/handling_errors/tutorial003.py
docs/src/handling_errors/tutorial004.py
docs/src/handling_errors/tutorial005.py
docs/src/middleware/tutorial001.py
docs/src/openapi_callbacks/tutorial001.py
docs/src/path_operation_configuration/tutorial001.py
docs/src/request_files/tutorial002.py
docs/src/response_change_status_code/tutorial001.py
docs/src/response_cookies/tutorial001.py
docs/src/response_cookies/tutorial002.py
docs/src/response_directly/tutorial001.py
docs/src/response_directly/tutorial002.py
docs/src/response_headers/tutorial001.py
docs/src/response_headers/tutorial002.py
docs/src/response_status_code/tutorial002.py
docs/src/security/tutorial003.py
docs/src/security/tutorial004.py
docs/src/security/tutorial005.py
docs/src/security/tutorial007.py
docs/src/sql_databases/sql_app/alt_main.py
docs/src/static_files/tutorial001.py
docs/src/templates/tutorial001.py
docs/src/using_request_directly/tutorial001.py
docs/src/websockets/tutorial001.py
docs/src/websockets/tutorial002.py
docs/src/wsgi/tutorial001.py [new file with mode: 0644]
docs/tutorial/cors.md
docs/tutorial/handling-errors.md
docs/tutorial/middleware.md
docs/tutorial/path-operation-configuration.md
docs/tutorial/request-files.md
docs/tutorial/response-status-code.md
docs/tutorial/security/oauth2-jwt.md
docs/tutorial/security/simple-oauth2.md
docs/tutorial/sql-databases.md
docs/tutorial/static-files.md
docs/tutorial/testing.md
fastapi/__init__.py
fastapi/background.py [new file with mode: 0644]
fastapi/concurrency.py
fastapi/middleware/__init__.py [new file with mode: 0644]
fastapi/middleware/cors.py [new file with mode: 0644]
fastapi/middleware/gzip.py [new file with mode: 0644]
fastapi/middleware/httpsredirect.py [new file with mode: 0644]
fastapi/middleware/trustedhost.py [new file with mode: 0644]
fastapi/middleware/wsgi.py [new file with mode: 0644]
fastapi/requests.py [new file with mode: 0644]
fastapi/responses.py [new file with mode: 0644]
fastapi/routing.py
fastapi/staticfiles.py [new file with mode: 0644]
fastapi/templating.py [new file with mode: 0644]
fastapi/testclient.py [new file with mode: 0644]
fastapi/websockets.py [new file with mode: 0644]
mkdocs.yml
pyproject.toml
tests/test_additional_properties.py
tests/test_additional_response_extra.py
tests/test_additional_responses_bad.py
tests/test_additional_responses_custom_validationerror.py
tests/test_additional_responses_default_validationerror.py
tests/test_additional_responses_response_class.py
tests/test_additional_responses_router.py
tests/test_application.py
tests/test_callable_endpoint.py
tests/test_custom_route_class.py
tests/test_custom_swagger_ui_redirect.py
tests/test_datetime_custom_encoder.py
tests/test_default_response_class.py
tests/test_default_response_class_router.py
tests/test_dependency_cache.py
tests/test_dependency_class.py
tests/test_dependency_contextmanager.py
tests/test_dependency_overrides.py
tests/test_empty_router.py
tests/test_extra_routes.py
tests/test_filter_pydantic_sub_model.py
tests/test_forms_from_non_typing_sequences.py
tests/test_include_route.py
tests/test_infer_param_optionality.py
tests/test_inherited_custom_class.py
tests/test_modules_same_name_body/test_main.py
tests/test_multi_body_errors.py
tests/test_multi_query_errors.py
tests/test_no_swagger_ui_redirect.py
tests/test_param_class.py
tests/test_param_in_path_and_dependency.py
tests/test_path.py
tests/test_put_no_body.py
tests/test_query.py
tests/test_repeated_dependency_schema.py
tests/test_request_body_parameters_media_type.py
tests/test_response_change_status_code.py
tests/test_response_class_no_mediatype.py
tests/test_response_code_no_body.py
tests/test_response_model_sub_types.py
tests/test_router_events.py
tests/test_router_prefix_with_template.py
tests/test_security_api_key_cookie.py
tests/test_security_api_key_cookie_optional.py
tests/test_security_api_key_header.py
tests/test_security_api_key_header_optional.py
tests/test_security_api_key_query.py
tests/test_security_api_key_query_optional.py
tests/test_security_http_base.py
tests/test_security_http_base_optional.py
tests/test_security_http_basic_optional.py
tests/test_security_http_basic_realm.py
tests/test_security_http_bearer.py
tests/test_security_http_bearer_optional.py
tests/test_security_http_digest.py
tests/test_security_http_digest_optional.py
tests/test_security_oauth2.py
tests/test_security_oauth2_authorization_code_bearer.py
tests/test_security_oauth2_optional.py
tests/test_security_oauth2_password_bearer_optional.py
tests/test_security_openid_connect.py
tests/test_security_openid_connect_optional.py
tests/test_serialize_response.py
tests/test_serialize_response_dataclass.py
tests/test_skip_defaults.py
tests/test_starlette_exception.py
tests/test_starlette_urlconvertors.py
tests/test_sub_callbacks.py
tests/test_swagger_ui_init_oauth.py
tests/test_tutorial/test_additional_responses/test_tutorial001.py
tests/test_tutorial/test_additional_responses/test_tutorial002.py
tests/test_tutorial/test_additional_responses/test_tutorial003.py
tests/test_tutorial/test_additional_responses/test_tutorial004.py
tests/test_tutorial/test_additional_status_codes/test_tutorial001.py
tests/test_tutorial/test_advanced_middleware/__init__.py [new file with mode: 0644]
tests/test_tutorial/test_advanced_middleware/test_tutorial001.py [new file with mode: 0644]
tests/test_tutorial/test_advanced_middleware/test_tutorial002.py [new file with mode: 0644]
tests/test_tutorial/test_advanced_middleware/test_tutorial003.py [new file with mode: 0644]
tests/test_tutorial/test_application_configuration/test_tutorial001.py
tests/test_tutorial/test_async_sql_databases/test_tutorial001.py
tests/test_tutorial/test_background_tasks/test_tutorial001.py
tests/test_tutorial/test_background_tasks/test_tutorial002.py
tests/test_tutorial/test_bigger_applications/test_main.py
tests/test_tutorial/test_body/test_tutorial001.py
tests/test_tutorial/test_body_fields/test_tutorial001.py
tests/test_tutorial/test_body_multiple_params/test_tutorial001.py
tests/test_tutorial/test_body_multiple_params/test_tutorial003.py
tests/test_tutorial/test_body_nested_models/test_tutorial009.py
tests/test_tutorial/test_body_updates/test_tutorial001.py
tests/test_tutorial/test_cookie_params/test_tutorial001.py
tests/test_tutorial/test_cors/__init__.py [new file with mode: 0644]
tests/test_tutorial/test_cors/test_tutorial001.py [new file with mode: 0644]
tests/test_tutorial/test_custom_request_and_route/test_tutorial001.py
tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py
tests/test_tutorial/test_custom_request_and_route/test_tutorial003.py
tests/test_tutorial/test_custom_response/test_tutorial001.py
tests/test_tutorial/test_custom_response/test_tutorial004.py
tests/test_tutorial/test_custom_response/test_tutorial005.py [new file with mode: 0644]
tests/test_tutorial/test_custom_response/test_tutorial006.py [new file with mode: 0644]
tests/test_tutorial/test_custom_response/test_tutorial007.py [new file with mode: 0644]
tests/test_tutorial/test_custom_response/test_tutorial008.py [new file with mode: 0644]
tests/test_tutorial/test_dependencies/test_tutorial001.py
tests/test_tutorial/test_dependencies/test_tutorial004.py
tests/test_tutorial/test_dependencies/test_tutorial006.py
tests/test_tutorial/test_events/test_tutorial001.py
tests/test_tutorial/test_events/test_tutorial002.py
tests/test_tutorial/test_extending_openapi/test_tutorial001.py
tests/test_tutorial/test_extending_openapi/test_tutorial002.py
tests/test_tutorial/test_extra_data_types/test_tutorial001.py
tests/test_tutorial/test_extra_models/test_tutorial003.py
tests/test_tutorial/test_extra_models/test_tutorial004.py
tests/test_tutorial/test_extra_models/test_tutorial005.py
tests/test_tutorial/test_first_steps/test_tutorial001.py
tests/test_tutorial/test_handling_errors/test_tutorial001.py
tests/test_tutorial/test_handling_errors/test_tutorial002.py
tests/test_tutorial/test_handling_errors/test_tutorial003.py
tests/test_tutorial/test_handling_errors/test_tutorial004.py
tests/test_tutorial/test_handling_errors/test_tutorial005.py
tests/test_tutorial/test_handling_errors/test_tutorial006.py
tests/test_tutorial/test_header_params/test_tutorial001.py
tests/test_tutorial/test_openapi_callbacks/test_tutorial001.py
tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial001.py
tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial002.py
tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial003.py
tests/test_tutorial/test_path_operation_advanced_configurations/test_tutorial004.py
tests/test_tutorial/test_path_operation_configurations/test_tutorial005.py
tests/test_tutorial/test_path_operation_configurations/test_tutorial006.py
tests/test_tutorial/test_path_params/test_tutorial004.py
tests/test_tutorial/test_path_params/test_tutorial005.py
tests/test_tutorial/test_query_params/test_tutorial005.py
tests/test_tutorial/test_query_params/test_tutorial006.py
tests/test_tutorial/test_query_params/test_tutorial007.py
tests/test_tutorial/test_query_params_str_validations/test_tutorial001.py
tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py
tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py
tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py
tests/test_tutorial/test_request_files/test_tutorial001.py
tests/test_tutorial/test_request_files/test_tutorial002.py
tests/test_tutorial/test_request_forms/test_tutorial001.py
tests/test_tutorial/test_request_forms_and_files/test_tutorial001.py
tests/test_tutorial/test_response_change_status_code/test_tutorial001.py
tests/test_tutorial/test_response_cookies/test_tutorial001.py
tests/test_tutorial/test_response_cookies/test_tutorial002.py
tests/test_tutorial/test_response_headers/test_tutorial001.py
tests/test_tutorial/test_response_headers/test_tutorial002.py
tests/test_tutorial/test_response_model/test_tutorial003.py
tests/test_tutorial/test_response_model/test_tutorial004.py
tests/test_tutorial/test_response_model/test_tutorial005.py
tests/test_tutorial/test_response_model/test_tutorial006.py
tests/test_tutorial/test_security/test_tutorial001.py
tests/test_tutorial/test_security/test_tutorial003.py
tests/test_tutorial/test_security/test_tutorial005.py
tests/test_tutorial/test_security/test_tutorial006.py
tests/test_tutorial/test_sql_databases/test_sql_databases.py
tests/test_tutorial/test_sql_databases/test_sql_databases_middleware.py
tests/test_tutorial/test_sql_databases_peewee/test_sql_databases_peewee.py
tests/test_tutorial/test_sub_applications/test_tutorial001.py
tests/test_tutorial/test_templates/test_tutorial001.py
tests/test_tutorial/test_websockets/test_tutorial001.py
tests/test_tutorial/test_websockets/test_tutorial002.py
tests/test_tutorial/test_wsgi/__init__.py [new file with mode: 0644]
tests/test_tutorial/test_wsgi/test_tutorial001.py [new file with mode: 0644]
tests/test_union_body.py
tests/test_union_inherited_body.py
tests/test_validate_response.py
tests/test_validate_response_dataclass.py
tests/test_ws_router.py

index f93dbfca3bfd932f0d8209e6ee4c2c24a65c1d07..14a867c989c88544f72f7b9522a1fef9d1c7d348 100644 (file)
@@ -1,4 +1,4 @@
-By default, **FastAPI** will return the responses using Starlette's `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`.
+By default, **FastAPI** will return the responses using a `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`.
 
 It will use the default status code or the one you set in your *path operation*.
 
@@ -12,7 +12,7 @@ But you also want it to accept new items. And when the items didn't exist before
 
 To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
 
-```Python hl_lines="2 20"
+```Python hl_lines="2  19"
 {!./src/additional_status_codes/tutorial001.py!}
 ```
 
@@ -23,8 +23,13 @@ To achieve that, import `JSONResponse`, and return your content there directly,
     
     Make sure it has the data you want it to have, and that the values are valid JSON (if you are using `JSONResponse`).
 
+!!! note "Technical Details"
+    You could also use `from starlette.responses import JSONResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `status`.
+
 ## OpenAPI and API docs
 
-If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know before hand what you are going to return.
+If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know beforehand what you are going to return.
 
 But you can document that in your code, using: [Additional Responses](additional-responses.md){.internal-link target=_blank}.
index a7b9cb4f7791e5833598a03098ca41c17b26a4cc..ec796362a847d46f273ac56396b97be770cdf328 100644 (file)
@@ -1,8 +1,3 @@
-!!! warning
-    This is, more or less, an "advanced" chapter.
-    
-    If you are just starting with **FastAPI** you might want to skip this chapter and come back to it later.
-
 ## Parameterized dependencies
 
 All the dependencies we have seen are a fixed function or class.
index 9f2b604fb658a2784e85682a15559cc1c8ac6596..2e823143a74d9d9b6f356650dff2b26ed9801f09 100644 (file)
@@ -25,13 +25,16 @@ And an `APIRoute` subclass to use that custom request class.
 
 ### Create a custom `GzipRequest` class
 
+!!! tip
+    This is a toy example to demonstrate how it works, if you need Gzip support, you can use the provided [`GzipMiddleware`](./middleware.md#gzipmiddleware){.internal-link target=_blank}.
+
 First, we create a `GzipRequest` class, which will overwrite the `Request.body()` method to decompress the body in the presence of an appropriate header.
 
 If there's no `gzip` in the header, it will not try to decompress the body.
 
 That way, the same route class can handle gzip compressed or uncompressed requests.
 
-```Python hl_lines="10 11 12 13 14 15 16 17"
+```Python hl_lines="8 9 10 11 12 13 14 15"
 {!./src/custom_request_and_route/tutorial001.py!}
 ```
 
@@ -45,7 +48,7 @@ This method returns a function. And that function is what will receive a request
 
 Here we use it to create a `GzipRequest` from the original request.
 
-```Python hl_lines="20 21 22 23 24 25 26 27 28"
+```Python hl_lines="18 19 20 21 22 23 24 25 26"
 {!./src/custom_request_and_route/tutorial001.py!}
 ```
 
@@ -79,13 +82,13 @@ We can also use this same approach to access the request body in an exception ha
 
 All we need to do is handle the request inside a `try`/`except` block:
 
-```Python hl_lines="15 17"
+```Python hl_lines="13 15"
 {!./src/custom_request_and_route/tutorial002.py!}
 ```
 
 If an exception occurs, the`Request` instance will still be in scope, so we can read and make use of the request body when handling the error:
 
-```Python hl_lines="18 19 20"
+```Python hl_lines="16 17 18"
 {!./src/custom_request_and_route/tutorial002.py!}
 ```
 
@@ -93,12 +96,12 @@ If an exception occurs, the`Request` instance will still be in scope, so we can
 
 You can also set the `route_class` parameter of an `APIRouter`:
 
-```Python hl_lines="28"
+```Python hl_lines="26"
 {!./src/custom_request_and_route/tutorial003.py!}
 ```
 
 In this example, the *path operations* under the `router` will use the custom `TimedRoute` class, and will have an extra `X-Response-Time` header in the response with the time it took to generate the response:
 
-```Python hl_lines="15 16 17 18 19 20 21 22"
+```Python hl_lines="13 14 15 16 17 18 19 20"
 {!./src/custom_request_and_route/tutorial003.py!}
 ```
index a6413374475aa6242fe916e2ad44570ee9e45bef..5e4504023440aaf882afb75529b0e7b13e2fb790 100644 (file)
@@ -1,13 +1,8 @@
-!!! warning
-    This is a rather advanced topic.
-
-    If you are starting with **FastAPI**, you might not need this.
-
-By default, **FastAPI** will return the responses using Starlette's `JSONResponse`.
+By default, **FastAPI** will return the responses using `JSONResponse`.
 
 You can override it by returning a `Response` directly as seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}.
 
-But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type`).
+But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type` as part of the generated OpenAPI).
 
 But you can also declare the `Response` that you want to be used, in the *path operation decorator*.
 
@@ -20,7 +15,7 @@ And if that `Response` has a JSON media type (`application/json`), like is the c
 
 ## Use `UJSONResponse`
 
-For example, if you are squeezing performance, you can install and use `ujson` and set the response to be Starlette's `UJSONResponse`.
+For example, if you are squeezing performance, you can install and use `ujson` and set the response to be `UJSONResponse`.
 
 Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
 
@@ -28,9 +23,6 @@ Import the `Response` class (sub-class) you want to use and declare it in the *p
 {!./src/custom_response/tutorial001.py!}
 ```
 
-!!! note
-    Notice that you import it directly from `starlette.responses`, not from `fastapi`.
-
 !!! info
     The parameter `response_class` will also be used to define the "media type" of the response.
 
@@ -49,9 +41,6 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
 {!./src/custom_response/tutorial002.py!}
 ```
 
-!!! note
-    Notice that you import it directly from `starlette.responses`, not from `fastapi`.
-
 !!! info
     The parameter `response_class` will also be used to define the "media type" of the response.
 
@@ -59,7 +48,7 @@ To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
 
     And it will be documented as such in OpenAPI.
 
-### Return a Starlette `Response`
+### Return a `Response`
 
 As seen in [Return a Response directly](response-directly.md){.internal-link target=_blank}, you can also override the response directly in your *path operation*, by returning it.
 
@@ -89,14 +78,115 @@ For example, it could be something like:
 {!./src/custom_response/tutorial004.py!}
 ```
 
-In this example, the function `generate_html_response()` already generates a Starlette `Response` instead of the HTML in a `str`.
+In this example, the function `generate_html_response()` already generates and returns a `Response` instead of returning the HTML in a `str`.
 
 By returning the result of calling `generate_html_response()`, you are already returning a `Response` that will override the default **FastAPI** behavior.
 
-But as you passed the `HTMLResponse` in the `response_class`, **FastAPI** will know how to document it in OpenAPI and the interactive docs as HTML with `text/html`:
+But as you passed the `HTMLResponse` in the `response_class` too, **FastAPI** will know how to document it in OpenAPI and the interactive docs as HTML with `text/html`:
 
 <img src="/img/tutorial/custom-response/image01.png">
 
+## Available responses
+
+Here are some of the available responses.
+
+Have in mind that you can use `Response` to return anything else, or even create a custom sub-class.
+
+!!! note "Technical Details"
+    You could also use `from starlette.responses import HTMLResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+
+### `Response`
+
+The main `Response` class, all the other responses inherit from it.
+
+You can return it directly.
+
+It accepts the following parameters:
+
+* `content` - A `str` or `bytes`.
+* `status_code` - An `int` HTTP status code.
+* `headers` - A `dict` of strings.
+* `media_type` - A `str` giving the media type. E.g. `"text/html"`.
+
+FastAPI (actually Starlette) will automatically include a Content-Length header. It will also include a Content-Type header, based on the media_type and appending a charset for text types.
+
+```Python hl_lines="1  18"
+{!./src/response_directly/tutorial002.py!}
+```
+
+### `HTMLResponse`
+
+Takes some text or bytes and returns an HTML response, as you read above.
+
+### `PlainTextResponse`
+
+Takes some text or bytes and returns an plain text response.
+
+```Python hl_lines="2  7  9"
+{!./src/custom_response/tutorial005.py!}
+```
+
+### `JSONResponse`
+
+Takes some data and returns an `application/json` encoded response.
+
+This is the default response used in **FastAPI**, as you read above.
+
+### `UJSONResponse`
+
+An alternative JSON response using `ujson` for faster serialization as you read above.
+
+!!! warning
+    `ujson` is less careful than Python's built-in implementation in how it handles some edge-cases.
+
+### `RedirectResponse`
+
+Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default.
+
+```Python hl_lines="2  9"
+{!./src/custom_response/tutorial006.py!}
+```
+
+### `StreamingResponse`
+
+Takes an async generator or a normal generator/iterator and streams the response body.
+
+```Python hl_lines="2  14"
+{!./src/custom_response/tutorial007.py!}
+```
+
+#### Using `StreamingResponse` with file-like objects
+
+If you have a file-like object (e.g. the object returned by `open()`), you can return it in a `StreamingResponse`.
+
+This includes many libraries to interact with cloud storage, video processing, and others.
+
+```Python hl_lines="2  10 11"
+{!./src/custom_response/tutorial008.py!}
+```
+
+!!! tip
+    Notice that here as we are using standard `open()` that doesn't support `async` and `await`, we declare the path operation with normal `def`.
+
+### `FileResponse`
+
+Asynchronously streams a file as the response.
+
+Takes a different set of arguments to instantiate than the other response types:
+
+* `path` - The filepath to the file to stream.
+* `headers` - Any custom headers to include, as a dictionary.
+* `media_type` - A string giving the media type. If unset, the filename or path will be used to infer a media type.
+* `filename` - If set, this will be included in the response `Content-Disposition`.
+
+File responses will include appropriate `Content-Length`, `Last-Modified` and `ETag` headers.
+
+```Python hl_lines="2  10"
+{!./src/custom_response/tutorial009.py!}
+```
+
 ## Additional documentation
 
 You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
index fa1998ce4d6a7c16b45bb5ab9afcd3de24aab9d5..91fb29db874663a93ff1de47cc4de6319f950c29 100644 (file)
@@ -161,7 +161,7 @@ pip install aiofiles
 
 ### Serve the static files
 
-* Import `StaticFiles` from Starlette.
+* Import `StaticFiles`.
 * "Mount" a `StaticFiles()` instance in a specific path.
 
 ```Python hl_lines="7 11"
diff --git a/docs/advanced/middleware.md b/docs/advanced/middleware.md
new file mode 100644 (file)
index 0000000..eff6c30
--- /dev/null
@@ -0,0 +1,97 @@
+In the main tutorial you read how to add [Custom Middleware](../tutorial/middleware.md){.internal-link target=_blank} to your application.
+
+And then you also read how to handle [CORS with the `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}.
+
+In this section we'll see how to use other middlewares.
+
+## Adding ASGI middlewares
+
+As **FastAPI** is based on Starlette and implements the <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr> specification, you can use any ASGI middleware.
+
+A middleware doesn't have to be made for FastAPI or Starlette to work, as long as it follows the ASGI spec.
+
+In general, ASGI middlewares are classes that expect to receive an ASGI app as the first argument.
+
+So, in the documentation for third-party ASGI middlewares they will probably tell you to do something like:
+
+```Python
+from unicorn import UnicornMiddleware
+
+app = SomeASGIApp()
+
+new_app = UnicornMiddleware(app, some_config="rainbow")
+```
+
+But FastAPI (actually Starlette) provides a simpler way to do it that makes sure that the internal middlewares to handle server errors and custom exception handlers work properly.
+
+For that, you use `app.add_middleware()` (as in the example for CORS).
+
+```Python
+from fastapi import FastAPI
+from unicorn import UnicornMiddleware
+
+app = FastAPI()
+
+app.add_middleware(UnicornMiddleware, some_config="rainbow")
+```
+
+`app.add_middleware()` receives a middleware class as the first argument and any additional arguments to be passed to the middleware.
+
+## Integrated middlewares
+
+**FastAPI** includes several middlewares for common use cases, we'll see next how to use them.
+
+!!! note "Technical Details"
+    For the next examples, you could also use `from starlette.middleware.something import SomethingMiddleware`.
+
+    **FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette.
+
+## `HTTPSRedirectMiddleware`
+
+Enforces that all incoming requests must either be `https` or `wss`.
+
+Any incoming requests to `http` or `ws` will be redirected to the secure scheme instead.
+
+```Python hl_lines="2  6"
+{!./src/advanced_middleware/tutorial001.py!}
+```
+
+## `TrustedHostMiddleware`
+
+Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks.
+
+```Python hl_lines="2  6 7 8"
+{!./src/advanced_middleware/tutorial002.py!}
+```
+
+The following arguments are supported:
+
+* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains to allow any hostname either use `allowed_hosts=["*"]` or omit the middleware.
+
+If an incoming request does not validate correctly then a `400` response will be sent.
+
+## `GZipMiddleware`
+
+Handles GZip responses for any request that includes `"gzip"` in the `Accept-Encoding` header.
+
+The middleware will handle both standard and streaming responses.
+
+```Python hl_lines="2  6 7 8"
+{!./src/advanced_middleware/tutorial002.py!}
+```
+
+The following arguments are supported:
+
+* `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`.
+
+## Other middlewares
+
+There are many other ASGI middlewares.
+
+For example:
+
+* <a href="https://docs.sentry.io/platforms/python/asgi/" class="external-link" target="_blank">Sentry</a>
+* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn's `ProxyHeadersMiddleware`</a>
+* <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>
+
+To see other available middlewares check <a href="https://www.starlette.io/middleware/" class="external-link" target="_blank">Starlette's Middleware docs</a> and the <a href="https://github.com/florimondmanca/awesome-asgi" class="external-link" target="_blank">ASGI Awesome List</a>.
index ac3692a991451cab26fe3b1f5135698cbb640b7b..1f10e12da9133aa3c46cbca41646b4a2a337376f 100644 (file)
@@ -18,7 +18,7 @@ You can declare a parameter of type `Response` in your *path operation function*
 
 And then you can set the `status_code` in that *temporal* response object.
 
-```Python hl_lines="2 11 14"
+```Python hl_lines="1  9  12"
 {!./src/response_change_status_code/tutorial001.py!}
 ```
 
index a73d54622cc65b991b8ffe590e355a5c7a022e17..8ce07bbf35c921938df057bbb1579cbcc168f971 100644 (file)
@@ -2,9 +2,9 @@
 
 You can declare a parameter of type `Response` in your *path operation function*.
 
-And then you can set headers in that *temporal* response object.
+And then you can set cookies in that *temporal* response object.
 
-```Python hl_lines="2 8 9"
+```Python hl_lines=" 8 9"
 {!./src/response_cookies/tutorial002.py!}
 ```
 
@@ -37,4 +37,11 @@ Then set Cookies in it, and then return it:
 
 ### More info
 
+!!! note "Technical Details"
+    You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+
+    And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
+
 To see all the available parameters and options, check the <a href="https://www.starlette.io/responses/#set-cookie" class="external-link" target="_blank">documentation in Starlette</a>.
index b4027105065f7c94e727a4eba2e29ee351be6054..1b123280878ef93e9a41eae7608160d1ae2bdc74 100644 (file)
@@ -2,20 +2,20 @@ When you create a **FastAPI** *path operation* you can normally return any data
 
 By default, **FastAPI** would automatically convert that return value to JSON using the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}.
 
-Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a Starlette `JSONResponse` that would be used to send the response to the client.
+Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a `JSONResponse` that would be used to send the response to the client.
 
 But you can return a `JSONResponse` directly from your *path operations*.
 
 It might be useful, for example, to return custom headers or cookies.
 
-## Starlette `Response`
+## Return a `Response`
 
-In fact, you can return any <a href="https://www.starlette.io/responses/" class="external-link" target="_blank">Starlette `Response`</a> or any sub-class of it.
+In fact, you can return any `Response` or any sub-class of it.
 
 !!! tip
     `JSONResponse` itself is a sub-class of `Response`.
 
-And when you return a Starlette `Response`, **FastAPI** will pass it directly.
+And when you return a `Response`, **FastAPI** will pass it directly.
 
 It won't do any data conversion with Pydantic models, it won't convert the contents to any type, etc.
 
@@ -33,8 +33,10 @@ For those cases, you can use the `jsonable_encoder` to convert your data before
 {!./src/response_directly/tutorial001.py!}
 ```
 
-!!! note
-    Notice that you import it directly from `starlette.responses`, not from `fastapi`.
+!!! note "Technical Details"
+    You could also use `from starlette.responses import JSONResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
 
 ## Returning a custom `Response`
 
@@ -42,13 +44,11 @@ The example above shows all the parts you need, but it's not very useful yet, as
 
 Now, let's see how you could use that to return a custom response.
 
-Let's say you want to return a response that is not available in the default <a href="https://www.starlette.io/responses/" class="external-link" target="_blank">Starlette `Response`s</a>.
-
-Let's say that you want to return <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>.
+Let's say that you want to return an <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a> response.
 
-You could put your XML content in a string, put it in a Starlette Response, and return it:
+You could put your XML content in a string, put it in a `Response`, and return it:
 
-```Python hl_lines="2 20"
+```Python hl_lines="1  18"
 {!./src/response_directly/tutorial002.py!}
 ```
 
index 55affc5cda2b6ebf0e76d816be996b81ae1a004d..c0f0e6b463fc4c2b7f238d56ef9a9ee7db482591 100644 (file)
@@ -4,7 +4,7 @@ You can declare a parameter of type `Response` in your *path operation function*
 
 And then you can set headers in that *temporal* response object.
 
-```Python hl_lines="2 8 9"
+```Python hl_lines="1  7 8"
 {!./src/response_headers/tutorial002.py!}
 ```
 
@@ -26,6 +26,13 @@ Create a response as described in [Return a Response Directly](response-directly
 {!./src/response_headers/tutorial001.py!}
 ```
 
+!!! note "Technical Details"
+    You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+
+    And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`.
+
 ## Custom Headers
 
 Have in mind that custom proprietary headers can be added <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">using the 'X-' prefix</a>.
index cbdad8279cafa1713bb4d17494cbf1ed710de0fa..8dc277dae5fe14aa11de8bf451e9e78a86fb88d9 100644 (file)
@@ -34,7 +34,7 @@ Use a dependency to check if the username and password are correct.
 
 For this, use the Python standard module <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> to check the username and password:
 
-```Python hl_lines="1  13 14 15"
+```Python hl_lines="1  11 12 13"
 {!./src/security/tutorial007.py!}
 ```
 
@@ -100,6 +100,6 @@ That way, using `secrets.compare_digest()` in your application code, it will be
 
 After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
 
-```Python hl_lines="16 17 18 19 20"
+```Python hl_lines="15 16 17 18 19"
 {!./src/security/tutorial007.py!}
 ```
index 671e38d7fb953b78370933cd18eaf9ac021e66f7..84c806bf888e42ef9552993f11a1e9569e184cb2 100644 (file)
@@ -54,7 +54,7 @@ They are normally used to declare specific security permissions, for example:
 
 First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
 
-```Python hl_lines="2 5 9 13 48 66 107 109 110 111 112 113 114 115 116 117 123 124 125 126 130 131 132 133 134 135 136 141 155"
+```Python hl_lines="2  5  9  13  47  65  106  108 109 110 111 112 113 114 115 116  122 123 124 125  129 130 131 132 133 134 135  140  154"
 {!./src/security/tutorial005.py!}
 ```
 
@@ -66,7 +66,7 @@ The first change is that now we are declaring the OAuth2 security scheme with tw
 
 The `scopes` parameter receives a `dict` with each scope as a key and the description as the value:
 
-```Python hl_lines="64 65 66 67"
+```Python hl_lines="63 64 65 66"
 {!./src/security/tutorial005.py!}
 ```
 
@@ -91,7 +91,7 @@ And we return the scopes as part of the JWT token.
 
     But in your application, for security, you should make sure you only add the scopes that the user is actually able to have, or the ones you have predefined.
 
-```Python hl_lines="156"
+```Python hl_lines="155"
 {!./src/security/tutorial005.py!}
 ```
 
@@ -116,7 +116,7 @@ In this case, it requires the scope `me` (it could require more than one scope).
     
     We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels.
 
-```Python hl_lines="5 141 168"
+```Python hl_lines="5  140  167"
 {!./src/security/tutorial005.py!}
 ```
 
@@ -141,7 +141,7 @@ We also declare a special parameter of type `SecurityScopes`, imported from `fas
 
 This `SecurityScopes` class is similar to `Request` (`Request` was used to get the request object directly).
 
-```Python hl_lines="9 107"
+```Python hl_lines="9  106"
 {!./src/security/tutorial005.py!}
 ```
 
@@ -157,7 +157,7 @@ We create an `HTTPException` that we can re-use (`raise`) later at several point
 
 In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in in the `WWW-Authenticate` header (this is part of the spec).
 
-```Python hl_lines="107 109 110 111 112 113 114 115 116 117"
+```Python hl_lines="106  108 109 110 111 112 113 114 115 116"
 {!./src/security/tutorial005.py!}
 ```
 
@@ -175,7 +175,7 @@ Instead of, for example, a `dict`, or something else, as it could break the appl
 
 We also verify that we have a user with that username, and if not, we raise that same exception we created before.
 
-```Python hl_lines="48 118 119 120 121 122 123 124 125 126 127 128 129"
+```Python hl_lines="47  117 118 119 120 121 122 123 124 125 126 127 128"
 {!./src/security/tutorial005.py!}
 ```
 
@@ -185,7 +185,7 @@ We now verify that all the scopes required, by this dependency and all the depen
 
 For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`.
 
-```Python hl_lines="130 131 132 133 134 135 136"
+```Python hl_lines="129 130 131 132 133 134 135"
 {!./src/security/tutorial005.py!}
 ```
 
index 2a43903b8784b0c946e1ce64d7c8cabbe474950b..9b8f750b5923c95d1399bcaebc3766535c100965 100644 (file)
@@ -2,7 +2,7 @@ You can use any template engine you want with **FastAPI**.
 
 A common election is Jinja2, the same one used by Flask and other tools.
 
-Starlette has utilities to configure it easily that you can use directly in your **FastAPI** application.
+There are utilities to configure it easily that you can use directly in your **FastAPI** application (provided by Starlette).
 
 ## Install dependencies
 
@@ -20,18 +20,23 @@ pip install aiofiles
 
 ## Using `Jinja2Templates`
 
-* Import `Jinja2Templates` form Starlette.
+* Import `Jinja2Templates`.
 * Create a `templates` object that you can re-use later.
 * Declare a `Request` parameter in the *path operation* that will return a template.
 * Use the `templates` you created to render and return a `TemplateResponse`, passing the `request` as one of the key-value pairs in the Jinja2 "context".
 
-```Python hl_lines="4 11 15 16"
+```Python hl_lines="3  10  14 15"
 {!./src/templates/tutorial001.py!}
 ```
 
 !!! note
     Notice that you have to pass the `request` as part of the key-value pairs in the context for Jinja2. So, you also have to declare it in your *path operation*.
 
+!!! note "Technical Details"
+    You could also use `from starlette.templating import Jinja2Templates`.
+
+    **FastAPI** provides the same `starlette.templating` as `fastapi.templating` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `Request` and `StaticFiles`.
+
 ## Writing templates
 
 Then you can write a template at `templates/item.html` with:
index 9a7b9d66dcacb58bc5c5d3c61fd316e09e01c35c..4d9e84d2c2a422c88e1ab9951713eeb52d392994 100644 (file)
@@ -15,7 +15,7 @@ But there are situations where you might need to access the `Request` object dir
 
 As **FastAPI** is actually **Starlette** underneath, with a layer of several tools on top, you can use Starlette's <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request`</a> object directly when you need to.
 
-It would also mean that if you get data from the `Request` object directly (for example, read the body) it won't be validated, converted or annotated (with OpenAPI, for the automatic documentation) by FastAPI.
+It would also mean that if you get data from the `Request` object directly (for example, read the body) it won't be validated, converted or documented (with OpenAPI, for the automatic API user interface) by FastAPI.
 
 Although any other parameter declared normally (for example, the body with a Pydantic model) would still be validated, converted, annotated, etc.
 
@@ -27,24 +27,14 @@ Let's imagine you want to get the client's IP address/host inside of your *path
 
 For that you need to access the request directly.
 
-### Import the `Request`
-
-First, import the `Request` class from Starlette:
-
-```Python hl_lines="2"
+```Python hl_lines="1  7 8"
 {!./src/using_request_directly/tutorial001.py!}
 ```
 
-### Declare the `Request` parameter
-
-Then declare a *path operation function* parameter with the type being the `Request` class:
-
-```Python hl_lines="8"
-{!./src/using_request_directly/tutorial001.py!}
-```
+By declaring a *path operation function* parameter with the type being the `Request` **FastAPI** will know to pass the `Request` in that parameter.
 
 !!! tip
-    Note that in this case, we are declaring a path parameter besides the request parameter.
+    Note that in this case, we are declaring a path parameter beside the request parameter.
 
     So, the path parameter will be extracted, validated, converted to the specified type and annotated with OpenAPI.
 
@@ -53,3 +43,8 @@ Then declare a *path operation function* parameter with the type being the `Requ
 ## `Request` documentation
 
 You can read more details about the <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request` object in the official Starlette documentation site</a>.
+
+!!! note "Technical Details"
+    You could also use `from starlette.requests import Request`.
+
+    **FastAPI** provides it directly just as a convenience for you, the developer. But it comes directly from Starlette.
index aae5f2be2764ea6f22cf1407d0e46507c4c23a96..ac6d93864ff3ca7b2da5986abe9edef3adf96e3c 100644 (file)
@@ -23,7 +23,7 @@ In production you would have one of the options above.
 
 But it's the simplest way to focus on the server-side of WebSockets and have a working example:
 
-```Python hl_lines="2 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 42 43 44"
+```Python hl_lines="2  6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38  41 42 43"
 {!./src/websockets/tutorial001.py!}
 ```
 
@@ -31,18 +31,20 @@ But it's the simplest way to focus on the server-side of WebSockets and have a w
 
 In your **FastAPI** application, create a `websocket`:
 
-```Python hl_lines="3 47 48"
+```Python hl_lines="1 46 47"
 {!./src/websockets/tutorial001.py!}
 ```
 
-!!! tip
-    In this example we are importing `WebSocket` from `starlette.websockets` to use it in the type declaration in the WebSocket route function.
+!!! note "Technical Details"
+    You could also use `from starlette.websockets import WebSocket`.
+
+    **FastAPI** provides the same `WebSocket` directly just as a convenience for you, the developer. But it comes directly from Starlette.
 
 ## Await for messages and send messages
 
 In your WebSocket route you can `await` for messages and send messages.
 
-```Python hl_lines="49 50 51 52 53"
+```Python hl_lines="48 49 50 51 52"
 {!./src/websockets/tutorial001.py!}
 ```
 
@@ -61,7 +63,7 @@ In WebSocket endpoints you can import from `fastapi` and use:
 
 They work the same way as for other FastAPI endpoints/*path operations*:
 
-```Python hl_lines="55 56 57 58 59 60 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78"
+```Python hl_lines="53 54 55 56 57 58  61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76"
 {!./src/websockets/tutorial002.py!}
 ```
 
@@ -76,7 +78,6 @@ They work the same way as for other FastAPI endpoints/*path operations*:
 
 To learn more about the options, check Starlette's documentation for:
 
-* <a href="https://www.starlette.io/applications/" class="external-link" target="_blank">Applications (`websocket_route`)</a>.
 * <a href="https://www.starlette.io/websockets/" class="external-link" target="_blank">The `WebSocket` class</a>.
 * <a href="https://www.starlette.io/endpoints/#websocketendpoint" class="external-link" target="_blank">Class-based WebSocket handling</a>.
 
diff --git a/docs/advanced/wsgi.md b/docs/advanced/wsgi.md
new file mode 100644 (file)
index 0000000..7d2edfc
--- /dev/null
@@ -0,0 +1,35 @@
+You can mount WSGI applications as you saw with [Sub Applications - Behind a Proxy, Mounts](./sub-applications-proxy.md){.internal-link target=_blank}.
+
+For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc.
+
+## Using `WSGIMiddleware`
+
+You need to import `WSGIMiddleware`.
+
+Then wrap the WSGI (e.g. Flask) app with the middleware.
+
+And then mount that under a path.
+
+```Python hl_lines="1  3  22"
+{!./src/wsgi/tutorial001.py!}
+```
+
+## Check it
+
+Now, every request under the path `/v1/` will be handled by the Flask application.
+
+And the rest will be handled by **FastAPI**.
+
+If you run it with Uvicorn and go to <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a> you will see the response from Flask:
+
+```txt
+Hello, World from Flask!
+```
+
+And if you go to <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a> you will see the response from FastAPI:
+
+```JSON
+{
+    "message": "Hello World"
+}
+```
index 9f6327b3e77359d2d8df8c5c08c29281ac8dca62..44a29813eec57539565fcfaeee96ad8c84aed569 100644 (file)
Binary files a/docs/img/tutorial/response-status-code/image02.png and b/docs/img/tutorial/response-status-code/image02.png differ
index dfb0fc91e47ef9a53dec7b5a984bf400ce80ec36..79dcc2efee601812112ec6e3b6ce37f514f1226b 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI
+from fastapi.responses import JSONResponse
 from pydantic import BaseModel
-from starlette.responses import JSONResponse
 
 
 class Item(BaseModel):
index bb19c8938917d193b90db10e25d21a59f8b98953..28bdb9b2a4ac2696e7d0358fc5fe7f61ea080535 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI
+from fastapi.responses import FileResponse
 from pydantic import BaseModel
-from starlette.responses import FileResponse
 
 
 class Item(BaseModel):
index bca3ba93eefbf58513fcec2520dd13034fcf011c..f3e41e8d26fc100a1b4163b5aa5526cf69dcecf4 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI
+from fastapi.responses import JSONResponse
 from pydantic import BaseModel
-from starlette.responses import JSONResponse
 
 
 class Item(BaseModel):
index f7314ba8e10dd03e076c71b94e712ad4b4b62c44..f1b15fee1399a988f30ebcca05cc8ea06e7d4b64 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI
+from fastapi.responses import FileResponse
 from pydantic import BaseModel
-from starlette.responses import FileResponse
 
 
 class Item(BaseModel):
index d32978685af4971fbe078c8918db9d79e5264146..c1b88828dd0e736421a7316831d3026090089127 100644 (file)
@@ -1,6 +1,5 @@
-from fastapi import Body, FastAPI
-from starlette.responses import JSONResponse
-from starlette.status import HTTP_201_CREATED
+from fastapi import Body, FastAPI, status
+from fastapi.responses import JSONResponse
 
 app = FastAPI()
 
@@ -17,4 +16,4 @@ async def upsert_item(item_id: str, name: str = Body(None), size: int = Body(Non
     else:
         item = {"name": name, "size": size}
         items[item_id] = item
-        return JSONResponse(status_code=HTTP_201_CREATED, content=item)
+        return JSONResponse(status_code=status.HTTP_201_CREATED, content=item)
diff --git a/docs/src/advanced_middleware/tutorial001.py b/docs/src/advanced_middleware/tutorial001.py
new file mode 100644 (file)
index 0000000..35dbd30
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi import FastAPI
+from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
+
+app = FastAPI()
+
+app.add_middleware(HTTPSRedirectMiddleware)
+
+
+@app.get("/")
+async def main():
+    return {"message": "Hello World"}
diff --git a/docs/src/advanced_middleware/tutorial002.py b/docs/src/advanced_middleware/tutorial002.py
new file mode 100644 (file)
index 0000000..405235a
--- /dev/null
@@ -0,0 +1,13 @@
+from fastapi import FastAPI
+from fastapi.middleware.trustedhost import TrustedHostMiddleware
+
+app = FastAPI()
+
+app.add_middleware(
+    TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"]
+)
+
+
+@app.get("/")
+async def main():
+    return {"message": "Hello World"}
diff --git a/docs/src/advanced_middleware/tutorial003.py b/docs/src/advanced_middleware/tutorial003.py
new file mode 100644 (file)
index 0000000..b99e3ed
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi import FastAPI
+from fastapi.middleware.gzip import GZipMiddleware
+
+app = FastAPI()
+
+app.add_middleware(GZipMiddleware, minimum_size=1000)
+
+
+@app.get("/")
+async def main():
+    return "somebigcontent"
index b02d7f010876212b3129b53119faf21a8550682a..ddc013f40c502b8d1f7f03bb24083ebd7dc50ee4 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from .main import app
 
index ad2a2a80682b6c2150102e6fb44a87668683c354..3e31a41806dbaedb5f03d14b712296684dd672d8 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from .main_b import app
 
index 9b00acb47a7924a9273f1b20abd1b48f9edd873a..79a853b487908f379444fcd03c26a89a1a3d0e67 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 0c3b9b9f0d2a7b0ebd14e7006f0963ce076e2228..b4a9c0586d78d2e750475eb01cbbad16d78e4552 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
-from starlette.websockets import WebSocket
+from fastapi.testclient import TestClient
+from fastapi.websockets import WebSocket
 
 app = FastAPI()
 
index 8843de174d74d1ef5979e0fca13d45e99debb22d..ca6b45ce03f5623a63f2f7fec4184d8080d05fb7 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index b0a581d2e953dc6e71a0389601412b9a9511e4d8..d59ab27acc2d72500c46b030ae803e56761c2331 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.middleware.cors import CORSMiddleware
+from fastapi.middleware.cors import CORSMiddleware
 
 app = FastAPI()
 
@@ -17,3 +17,8 @@ app.add_middleware(
     allow_methods=["*"],
     allow_headers=["*"],
 )
+
+
+@app.get("/")
+async def main():
+    return {"message": "Hello World"}
index cd21582e360baccdeb5ca3c5f8b1a6655d64b721..2e64ad45d8b5648474c5d0ff6f98bab47dc32370 100644 (file)
@@ -1,10 +1,8 @@
 import gzip
 from typing import Callable, List
 
-from fastapi import Body, FastAPI
+from fastapi import Body, FastAPI, Request, Response
 from fastapi.routing import APIRoute
-from starlette.requests import Request
-from starlette.responses import Response
 
 
 class GzipRequest(Request):
index 95cad99b15b33f0c189f7dc60fe0fd23ff7664e9..f4c093ac9c6e5b9cc112edb67e3634f0ede10095 100644 (file)
@@ -1,10 +1,8 @@
 from typing import Callable, List
 
-from fastapi import Body, FastAPI, HTTPException
+from fastapi import Body, FastAPI, HTTPException, Request, Response
 from fastapi.exceptions import RequestValidationError
 from fastapi.routing import APIRoute
-from starlette.requests import Request
-from starlette.responses import Response
 
 
 class ValidationErrorLoggingRoute(APIRoute):
index 4497736a59c375ce6a999e637cc8f819cec42775..aabe7606851b6d03e4aa25a532528f40ee60780e 100644 (file)
@@ -1,10 +1,8 @@
 import time
 from typing import Callable
 
-from fastapi import APIRouter, FastAPI
+from fastapi import APIRouter, FastAPI, Request, Response
 from fastapi.routing import APIRoute
-from starlette.requests import Request
-from starlette.responses import Response
 
 
 class TimedRoute(APIRoute):
index 53e784fcc7607baee8b32ca52d4700071bcfba83..0f09bdf77fdb865b6dea4b9f87e3a868ade995bf 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.responses import UJSONResponse
+from fastapi.responses import UJSONResponse
 
 app = FastAPI()
 
index d4375c338ff1f9d613a5d06213bb15b1ff7322f3..23c495867b6bb3cee5b6eac158a08797ddda7268 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.responses import HTMLResponse
+from fastapi.responses import HTMLResponse
 
 app = FastAPI()
 
index ba0819cecd5388ed4c84bec0184fbbab93d7d04f..51ad3c146b4962d1732093e684e5380e5450574d 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.responses import HTMLResponse
+from fastapi.responses import HTMLResponse
 
 app = FastAPI()
 
index e2248773e519737e64b772ea6391e26be1b594ab..0e90f20126431224d087a4a8d06fdf7c4fe325f5 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.responses import HTMLResponse
+from fastapi.responses import HTMLResponse
 
 app = FastAPI()
 
diff --git a/docs/src/custom_response/tutorial005.py b/docs/src/custom_response/tutorial005.py
new file mode 100644 (file)
index 0000000..3d58f57
--- /dev/null
@@ -0,0 +1,9 @@
+from fastapi import FastAPI
+from fastapi.responses import PlainTextResponse
+
+app = FastAPI()
+
+
+@app.get("/", response_class=PlainTextResponse)
+async def main():
+    return "Hello World"
diff --git a/docs/src/custom_response/tutorial006.py b/docs/src/custom_response/tutorial006.py
new file mode 100644 (file)
index 0000000..1c55568
--- /dev/null
@@ -0,0 +1,9 @@
+from fastapi import FastAPI
+from fastapi.responses import RedirectResponse
+
+app = FastAPI()
+
+
+@app.get("/typer")
+async def read_typer():
+    return RedirectResponse("https://typer.tiangolo.com")
diff --git a/docs/src/custom_response/tutorial007.py b/docs/src/custom_response/tutorial007.py
new file mode 100644 (file)
index 0000000..e2a53a2
--- /dev/null
@@ -0,0 +1,14 @@
+from fastapi import FastAPI
+from fastapi.responses import StreamingResponse
+
+app = FastAPI()
+
+
+async def fake_video_streamer():
+    for i in range(10):
+        yield b"some fake video bytes"
+
+
+@app.get("/")
+async def main():
+    return StreamingResponse(fake_video_streamer())
diff --git a/docs/src/custom_response/tutorial008.py b/docs/src/custom_response/tutorial008.py
new file mode 100644 (file)
index 0000000..d332736
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi import FastAPI
+from fastapi.responses import StreamingResponse
+
+some_file_path = "large-video-file.mp4"
+app = FastAPI()
+
+
+@app.get("/")
+def main():
+    file_like = open(some_file_path, mode="rb")
+    return StreamingResponse(file_like, media_type="video/mp4")
diff --git a/docs/src/custom_response/tutorial009.py b/docs/src/custom_response/tutorial009.py
new file mode 100644 (file)
index 0000000..71cf50c
--- /dev/null
@@ -0,0 +1,10 @@
+from fastapi import FastAPI
+from fastapi.responses import FileResponse
+
+some_file_path = "large-video-file.mp4"
+app = FastAPI()
+
+
+@app.get("/")
+async def main():
+    return FileResponse(some_file_path)
index 2f234d396ed66cfbf56c99c5754fb7ab2927b11e..67c3874a369eea6e4596c735b1272b7e2023829b 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import Depends, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index df8cbca886bdcbf50c52ca75d0005acc5a299867..23ea368f8bd4369772ca1c1a4173ac6f33ca827d 100644 (file)
@@ -4,7 +4,7 @@ from fastapi.openapi.docs import (
     get_swagger_ui_html,
     get_swagger_ui_oauth2_redirect_html,
 )
-from starlette.staticfiles import StaticFiles
+from fastapi.staticfiles import StaticFiles
 
 app = FastAPI(docs_url=None, redoc_url=None)
 
index eac9b5cbb76440e72552b971d783be4b2942938e..791cd6838c5ba128a0d4726dd3ed688add045ac5 100644 (file)
@@ -1,6 +1,5 @@
-from fastapi import FastAPI
-from starlette.requests import Request
-from starlette.responses import JSONResponse
+from fastapi import FastAPI, Request
+from fastapi.responses import JSONResponse
 
 
 class UnicornException(Exception):
index ce25979c3a4d4f294626f46b6105b94e4f8b07eb..300a3834ff47cc05997f78565eb48cba8758e09a 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import FastAPI, HTTPException
 from fastapi.exceptions import RequestValidationError
+from fastapi.responses import PlainTextResponse
 from starlette.exceptions import HTTPException as StarletteHTTPException
-from starlette.responses import PlainTextResponse
 
 app = FastAPI()
 
index 38a2c0a08d42c28183a118f7fb230c2d36255878..6e0b81d313fdc6e07755cd88ddffd32e45e211ff 100644 (file)
@@ -1,10 +1,8 @@
-from fastapi import FastAPI
+from fastapi import FastAPI, Request, status
 from fastapi.encoders import jsonable_encoder
 from fastapi.exceptions import RequestValidationError
+from fastapi.responses import JSONResponse
 from pydantic import BaseModel
-from starlette import status
-from starlette.requests import Request
-from starlette.responses import JSONResponse
 
 app = FastAPI()
 
index d590cbcf48c94ca022ec07dea0cbb54b761d33b9..6bab3410a6548c3f8b25c9f7e7ed18f9e1e35739 100644 (file)
@@ -1,7 +1,6 @@
 import time
 
-from fastapi import FastAPI
-from starlette.requests import Request
+from fastapi import FastAPI, Request
 
 app = FastAPI()
 
index 717e981f82622b4e7a00c59cd7018d41fcad5331..c9ca4eb96a9ad686c83af83041cca63b585b1d2b 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import APIRouter, FastAPI
+from fastapi.responses import JSONResponse
 from pydantic import BaseModel, HttpUrl
-from starlette.responses import JSONResponse
 
 app = FastAPI()
 
index b486018672ada8c2c170f662c452bc7c23e64e0b..a60b47fef0f201753cd049d69e28ae85aab26354 100644 (file)
@@ -1,8 +1,7 @@
 from typing import Set
 
-from fastapi import FastAPI
+from fastapi import FastAPI, status
 from pydantic import BaseModel
-from starlette.status import HTTP_201_CREATED
 
 app = FastAPI()
 
@@ -15,6 +14,6 @@ class Item(BaseModel):
     tags: Set[str] = []
 
 
-@app.post("/items/", response_model=Item, status_code=HTTP_201_CREATED)
+@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
 async def create_item(*, item: Item):
     return item
index bc665b25912123f6770285707f9ec887e2199c5b..6fdf16a751213a6ffa861b0eaaf758fb8c01684b 100644 (file)
@@ -1,7 +1,7 @@
 from typing import List
 
 from fastapi import FastAPI, File, UploadFile
-from starlette.responses import HTMLResponse
+from fastapi.responses import HTMLResponse
 
 app = FastAPI()
 
index 9bdfef778d490d7a94fdaf26fc260c3d6805cd07..197decbfbf1ec49fb44d71aebbd0bf6b3b1475d9 100644 (file)
@@ -1,6 +1,4 @@
-from fastapi import FastAPI
-from starlette.responses import Response
-from starlette.status import HTTP_201_CREATED
+from fastapi import FastAPI, Response, status
 
 app = FastAPI()
 
@@ -11,5 +9,5 @@ tasks = {"foo": "Listen to the Bar Fighters"}
 def get_or_create_task(task_id: str, response: Response):
     if task_id not in tasks:
         tasks[task_id] = "This didn't exist before"
-        response.status_code = HTTP_201_CREATED
+        response.status_code = status.HTTP_201_CREATED
     return tasks[task_id]
index badc2fcc9b3d2622f81446a1eaaa142a4b4f5808..33f8e8f6e996b4796363244d2671ff30a1f978b1 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.responses import JSONResponse
+from fastapi.responses import JSONResponse
 
 app = FastAPI()
 
index fed1fadcd9ca2dcb2ff853c335bc13065b1c56fa..76c06fdb9fe6932a8be495ca50d08f149b2b6d61 100644 (file)
@@ -1,5 +1,4 @@
-from fastapi import FastAPI
-from starlette.responses import Response
+from fastapi import FastAPI, Response
 
 app = FastAPI()
 
index 92ae0ca37a71418769289994891444fc6c537c37..89c5968b143beda2f4c2bed5a5d5e349f9bb49f0 100644 (file)
@@ -2,8 +2,8 @@ from datetime import datetime
 
 from fastapi import FastAPI
 from fastapi.encoders import jsonable_encoder
+from fastapi.responses import JSONResponse
 from pydantic import BaseModel
-from starlette.responses import JSONResponse
 
 
 class Item(BaseModel):
index 10db00a679c855fe36ad30a2aaf101cb3ae5f110..6643da6e6d61ac322a9ecacc1d9defd8ddfdba9a 100644 (file)
@@ -1,5 +1,4 @@
-from fastapi import FastAPI
-from starlette.responses import Response
+from fastapi import FastAPI, Response
 
 app = FastAPI()
 
index 8aad084b68daa34dc7b499ea65aabbc49dc2e228..2da02a470b4b70431ee4df10407f8f1ae7a426b5 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.responses import JSONResponse
+from fastapi.responses import JSONResponse
 
 app = FastAPI()
 
index 3fcde0289136519fe00dd71566edfde58b21a85b..d2c4983051434595a9ca4c9af97685a1838a145b 100644 (file)
@@ -1,5 +1,4 @@
-from fastapi import FastAPI
-from starlette.responses import Response
+from fastapi import FastAPI, Response
 
 app = FastAPI()
 
index e31a6c17c378fa60462e0dd927d7d75556cfe5a4..4fcc9829db2a0eddc1dcf52080d21ecd5c84aad0 100644 (file)
@@ -1,9 +1,8 @@
-from fastapi import FastAPI
-from starlette.status import HTTP_201_CREATED
+from fastapi import FastAPI, status
 
 app = FastAPI()
 
 
-@app.post("/items/", status_code=HTTP_201_CREATED)
+@app.post("/items/", status_code=status.HTTP_201_CREATED)
 async def create_item(name: str):
     return {"name": name}
index 55724e59d13a9781c01b3bfa150759fbba418ce1..5dabb393f193d9409815d79c170fae5f60dfc7cf 100644 (file)
@@ -1,7 +1,6 @@
-from fastapi import Depends, FastAPI, HTTPException
+from fastapi import Depends, FastAPI, HTTPException, status
 from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
 from pydantic import BaseModel
-from starlette.status import HTTP_401_UNAUTHORIZED
 
 fake_users_db = {
     "johndoe": {
@@ -58,7 +57,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
     user = fake_decode_token(token)
     if not user:
         raise HTTPException(
-            status_code=HTTP_401_UNAUTHORIZED,
+            status_code=status.HTTP_401_UNAUTHORIZED,
             detail="Invalid authentication credentials",
             headers={"WWW-Authenticate": "Bearer"},
         )
index df57acf24141b66d40c1fa627cb66ef1e5894e6c..3c8b6693d2f5ce344ff460d7c9d2a9461ed1621d 100644 (file)
@@ -1,12 +1,11 @@
 from datetime import datetime, timedelta
 
 import jwt
-from fastapi import Depends, FastAPI, HTTPException
+from fastapi import Depends, FastAPI, HTTPException, status
 from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
 from jwt import PyJWTError
 from passlib.context import CryptContext
 from pydantic import BaseModel
-from starlette.status import HTTP_401_UNAUTHORIZED
 
 # to get a string like this run:
 # openssl rand -hex 32
@@ -89,7 +88,7 @@ def create_access_token(*, data: dict, expires_delta: timedelta = None):
 
 async def get_current_user(token: str = Depends(oauth2_scheme)):
     credentials_exception = HTTPException(
-        status_code=HTTP_401_UNAUTHORIZED,
+        status_code=status.HTTP_401_UNAUTHORIZED,
         detail="Could not validate credentials",
         headers={"WWW-Authenticate": "Bearer"},
     )
@@ -118,7 +117,7 @@ async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends(
     user = authenticate_user(fake_users_db, form_data.username, form_data.password)
     if not user:
         raise HTTPException(
-            status_code=HTTP_401_UNAUTHORIZED,
+            status_code=status.HTTP_401_UNAUTHORIZED,
             detail="Incorrect username or password",
             headers={"WWW-Authenticate": "Bearer"},
         )
index 5f34387b5ad20103a4a6be0ef35415b80b71b9e5..f43659454c167b36f37f44f08b8e3459fb4759f6 100644 (file)
@@ -2,7 +2,7 @@ from datetime import datetime, timedelta
 from typing import List
 
 import jwt
-from fastapi import Depends, FastAPI, HTTPException, Security
+from fastapi import Depends, FastAPI, HTTPException, Security, status
 from fastapi.security import (
     OAuth2PasswordBearer,
     OAuth2PasswordRequestForm,
@@ -11,7 +11,6 @@ from fastapi.security import (
 from jwt import PyJWTError
 from passlib.context import CryptContext
 from pydantic import BaseModel, ValidationError
-from starlette.status import HTTP_401_UNAUTHORIZED
 
 # to get a string like this run:
 # openssl rand -hex 32
@@ -111,7 +110,7 @@ async def get_current_user(
     else:
         authenticate_value = f"Bearer"
     credentials_exception = HTTPException(
-        status_code=HTTP_401_UNAUTHORIZED,
+        status_code=status.HTTP_401_UNAUTHORIZED,
         detail="Could not validate credentials",
         headers={"WWW-Authenticate": authenticate_value},
     )
@@ -130,7 +129,7 @@ async def get_current_user(
     for scope in security_scopes.scopes:
         if scope not in token_data.scopes:
             raise HTTPException(
-                status_code=HTTP_401_UNAUTHORIZED,
+                status_code=status.HTTP_401_UNAUTHORIZED,
                 detail="Not enough permissions",
                 headers={"WWW-Authenticate": authenticate_value},
             )
index 2c323fd48dbdbcc7d59e1f8e359abc544efb7a37..90b9ac0546ff5b544b56cf2202670067af3aeb4f 100644 (file)
@@ -1,8 +1,7 @@
 import secrets
 
-from fastapi import Depends, FastAPI, HTTPException
+from fastapi import Depends, FastAPI, HTTPException, status
 from fastapi.security import HTTPBasic, HTTPBasicCredentials
-from starlette.status import HTTP_401_UNAUTHORIZED
 
 app = FastAPI()
 
@@ -14,7 +13,7 @@ def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
     correct_password = secrets.compare_digest(credentials.password, "swordfish")
     if not (correct_username and correct_password):
         raise HTTPException(
-            status_code=HTTP_401_UNAUTHORIZED,
+            status_code=status.HTTP_401_UNAUTHORIZED,
             detail="Incorrect email or password",
             headers={"WWW-Authenticate": "Basic"},
         )
index 01b71333b408b1b63b5bdb6190f4d82ed624f773..f7206bcb4173f335d34eb68cdae8a22c3c3c3a67 100644 (file)
@@ -1,9 +1,7 @@
 from typing import List
 
-from fastapi import Depends, FastAPI, HTTPException
+from fastapi import Depends, FastAPI, HTTPException, Request, Response
 from sqlalchemy.orm import Session
-from starlette.requests import Request
-from starlette.responses import Response
 
 from . import crud, models, schemas
 from .database import SessionLocal, engine
index 5bcd594c7f61e2fb8d07996b2567efbbc5856f5b..460352c7e1596648682ee75e16e6770ecead1d4d 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.staticfiles import StaticFiles
+from fastapi.staticfiles import StaticFiles
 
 app = FastAPI()
 
index 0f00c3fca6d465b5ce4d8473d13509a0fbfd6d14..b818861db77e9e4a4e5094335814d25ed41def57 100644 (file)
@@ -1,7 +1,6 @@
-from fastapi import FastAPI
-from starlette.requests import Request
-from starlette.staticfiles import StaticFiles
-from starlette.templating import Jinja2Templates
+from fastapi import FastAPI, Request
+from fastapi.staticfiles import StaticFiles
+from fastapi.templating import Jinja2Templates
 
 app = FastAPI()
 
index ca71f32f723030e92c417482bd86aae458225347..2d7288b54d061ec18957627bb290ba911b0777f1 100644 (file)
@@ -1,5 +1,4 @@
-from fastapi import FastAPI
-from starlette.requests import Request
+from fastapi import FastAPI, Request
 
 app = FastAPI()
 
index 3adfd49c10ba051fca1f194f943bd3421cc21001..a43a2be17c6f904634ebecdaf0689e03de69bc97 100644 (file)
@@ -1,6 +1,5 @@
-from fastapi import FastAPI
-from starlette.responses import HTMLResponse
-from starlette.websockets import WebSocket
+from fastapi import FastAPI, WebSocket
+from fastapi.responses import HTMLResponse
 
 app = FastAPI()
 
index f57b927f8e6948abb128f7a615d75e391fc731b2..43005e54c7da60af83f3611f86ad50bf5c8733f8 100644 (file)
@@ -1,7 +1,5 @@
-from fastapi import Cookie, Depends, FastAPI, Header
-from starlette.responses import HTMLResponse
-from starlette.status import WS_1008_POLICY_VIOLATION
-from starlette.websockets import WebSocket
+from fastapi import Cookie, Depends, FastAPI, Header, WebSocket, status
+from fastapi.responses import HTMLResponse
 
 app = FastAPI()
 
@@ -56,7 +54,7 @@ async def get_cookie_or_client(
     websocket: WebSocket, session: str = Cookie(None), x_client: str = Header(None)
 ):
     if session is None and x_client is None:
-        await websocket.close(code=WS_1008_POLICY_VIOLATION)
+        await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
     return session or x_client
 
 
diff --git a/docs/src/wsgi/tutorial001.py b/docs/src/wsgi/tutorial001.py
new file mode 100644 (file)
index 0000000..7a4011e
--- /dev/null
@@ -0,0 +1,22 @@
+from flask import Flask, escape, request
+from fastapi import FastAPI
+from fastapi.middleware.wsgi import WSGIMiddleware
+
+flask_app = Flask(__name__)
+
+
+@flask_app.route("/")
+def flask_main():
+    name = request.args.get("name", "World")
+    return f"Hello, {escape(name)} from Flask!"
+
+
+app = FastAPI()
+
+
+@app.get("/v2")
+def read_main():
+    return {"message": "Hello World"}
+
+
+app.mount("/v1", WSGIMiddleware(flask_app))
index 6e93354a2130b104dc47d584221be97a0a73a4b5..868fc056aacc7ae334a7640483b20a0d84cdf4fd 100644 (file)
@@ -32,9 +32,9 @@ So, for everything to work correctly, it's better to specify explicitly the allo
 
 ## Use `CORSMiddleware`
 
-You can configure it in your **FastAPI** application using Starlette's <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">`CORSMiddleware`</a>.
+You can configure it in your **FastAPI** application using the `CORSMiddleware`.
 
-* Import it from Starlette.
+* Import `CORSMiddleware`.
 * Create a list of allowed origins (as strings).
 * Add it as a "middleware" to your **FastAPI** application.
 
@@ -44,12 +44,39 @@ You can also specify if your backend allows:
 * Specific HTTP methods (`POST`, `PUT`) or all of them with the wildcard `"*"`.
 * Specific HTTP headers or all of them with the wildcard `"*"`.
 
-```Python hl_lines="2 6 7 8 9 10 11 13 14 15 16 17 18 19"
+```Python hl_lines="2  6 7 8 9 10 11  13 14 15 16 17 18 19"
 {!./src/cors/tutorial001.py!}
 ```
 
-## More info
+The default parameters used by the `CORSMiddleware` implementation are restrictive by default, so you'll need to explicitly enable particular origins, methods, or headers, in order for browsers to be permitted to use them in a Cross-Domain context.
+
+The following arguments are supported:
+
+* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. E.g. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
+* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. eg. `'https://.*\.example\.org'`.
+* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
+* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for CORS requests.
+* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`.
+* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
+* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `60`.
+
+The middleware responds to two particular types of HTTP request...
+
+### CORS preflight requests
+
+These are any `OPTIONS` request with `Origin` and `Access-Control-Request-Method` headers.
 
-For more details of what you can specify in `CORSMiddleware`, check <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's `CORSMiddleware` docs</a>.
+In this case the middleware will intercept the incoming request and respond with appropriate CORS headers, and either a `200` or `400` response for informational purposes.
+
+### Simple requests
+
+Any request with an `Origin` header. In this case the middleware will pass the request through as normal, but will include appropriate CORS headers on the response.
+
+## More info
 
 For more info about <abbr title="Cross-Origin Resource Sharing">CORS</abbr>, check the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS documentation</a>.
+
+!!! note "Technical Details"
+    You could also use `from starlette.middleware.cors import CORSMiddleware`.
+
+    **FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette.
index 2962c733eec47673e2b26b701128e8ee231d3652..8ae9ff47ea97b5ea52972d6cf939d4b4f18def34 100644 (file)
@@ -90,7 +90,7 @@ And you want to handle this exception globally with FastAPI.
 
 You could add a custom exception handler with `@app.exception_handler()`:
 
-```Python hl_lines="6 7 8 14 15 16 17 18 24"
+```Python hl_lines="5 6 7  13 14 15 16 17 18  24"
 {!./src/handling_errors/tutorial003.py!}
 ```
 
@@ -104,6 +104,11 @@ So, you will receive a clean error, with an HTTP status code of `418` and a JSON
 {"message": "Oops! yolo did something. There goes a rainbow..."}
 ```
 
+!!! note "Technical Details"
+    You could also use `from starlette.requests import Request` and `from starlette.responses import JSONResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `Request`.
+
 ## Override the default exception handlers
 
 **FastAPI** has some default exception handlers.
@@ -172,17 +177,22 @@ The same way, you can override the `HTTPException` handler.
 
 For example, you could want to return a plain text response instead of JSON for these errors:
 
-```Python hl_lines="1 3 9 10 11 22"
+```Python hl_lines="3 4  9 10 11 22"
 {!./src/handling_errors/tutorial004.py!}
 ```
 
+!!! note "Technical Details"
+    You could also use `from starlette.responses import PlainTextResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+
 ### Use the `RequestValidationError` body
 
 The `RequestValidationError` contains the `body` it received with invalid data.
 
 You could use it while developing your app to log the body and debug it, return it to the user, etc.
 
-```Python hl_lines="16"
+```Python hl_lines="14"
 {!./src/handling_errors/tutorial005.py!}
 ```
 
@@ -231,7 +241,7 @@ So, you can keep raising **FastAPI**'s `HTTPException` as normally in your code.
 
 But when you register an exception handler, you should register it for Starlette's `HTTPException`.
 
-This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises an `HTTPException`, your handler will be able to catch and handle it.
+This way, if any part of Starlette's internal code, or a Starlette extension or plug-in, raises a Starlette `HTTPException`, your handler will be able to catch and handle it.
 
 In this example, to be able to have both `HTTPException`s in the same code, Starlette's exceptions is renamed to `StarletteHTTPException`:
 
index 9e348aa7b8cabed037dc9d63ea323a9ed33ddfd8..5dd779189abc56ee255a091c7e7100f25352df4a 100644 (file)
@@ -9,6 +9,11 @@ A "middleware" is a function that works with every **request** before it is proc
 * It can do something to that **response** or run any needed code.
 * Then it returns the **response**.
 
+!!! note "Technical Details"
+    If you have dependencies with `yield`, the exit code will run *after* the middleware.
+
+    If there were any background tasks (documented later), they will run *after* all the middleware.
+
 ## Create a middleware
 
 To create a middleware you use the decorator `@app.middleware("http")` on top of a function.
@@ -21,7 +26,7 @@ The middleware function receives:
     * Then it returns the `response` generated by the corresponding *path operation*.
 * You can then modify further the `response` before returning it.
 
-```Python hl_lines="9 10 12 15"
+```Python hl_lines="8 9  11  14"
 {!./src/middleware/tutorial001.py!}
 ```
 
@@ -30,6 +35,11 @@ The middleware function receives:
 
     But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) using the parameter `expose_headers` documented in <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
 
+!!! note "Technical Details"
+    You could also use `from starlette.requests import Request`.
+
+    **FastAPI** provides it as a convenience for you, the developer. But it comes directly from Starlette.
+
 ### Before and after the `response`
 
 You can add code to be run with the `request`,  before any *path operation* receives it.
@@ -38,19 +48,12 @@ And also after the `response` is generated, before returning it.
 
 For example, you could add a custom header `X-Process-Time` containing the time in seconds that it took to process the request and generate a response:
 
-```Python hl_lines="11 13 14"
+```Python hl_lines="10  12  13"
 {!./src/middleware/tutorial001.py!}
 ```
 
-## Starlette's Middleware
-
-You can also add any other <a href="https://www.starlette.io/middleware/" class="external-link" target="_blank">Starlette Middleware</a>.
-
-These are classes instead of plain functions.
+## Other middlewares
 
-Including:
+You can later read more about other middlewares in the [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}.
 
-* `CORSMiddleware` (described in the next section).
-* `GZipMiddleware`.
-* `SentryMiddleware`.
-* ...and others.
+You will read about how to handle <abbr title="Cross-Origin Resource Sharing">CORS</abbr> with a middleware in the next section.
index ff200aae154aed5a597e9382fca41dbfde8eb1df..cfc970b7a90056a336d61b19f2e3d066b1d1532a 100644 (file)
@@ -9,14 +9,19 @@ You can define the (HTTP) `status_code` to be used in the response of your *path
 
 You can pass directly the `int` code, like `404`.
 
-But if you don't remember what each number code is for, you can use the shortcut constants from `starlette`:
+But if you don't remember what each number code is for, you can use the shortcut constants in `status`:
 
-```Python hl_lines="5 18"
+```Python hl_lines="3  17"
 {!./src/path_operation_configuration/tutorial001.py!}
 ```
 
 That status code will be used in the response and will be added to the OpenAPI schema.
 
+!!! note "Technical Details"
+    You could also use `from starlette import status`.
+
+    **FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
+
 ## Tags
 
 You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
index 608e9e55d2143dbf73023c52a2564870e1b20d2a..b14f45c702f229d167dbe613d4b02e1bc6617fdc 100644 (file)
@@ -132,6 +132,11 @@ You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
     
     So, whenever Swagger UI supports multi-file uploads, or any other tools that supports OpenAPI, they will be compatible with **FastAPI**.
 
+!!! note "Technical Details"
+    You could also use `from starlette.responses import HTMLResponse`.
+
+    **FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
+
 ## Recap
 
 Use `File` to declare files to be uploaded as input parameters (as form data).
index 821de9a4ff20c24e91d7a7cb4b55f702533f9866..3f77272de3f58b9f26d23430a0db77839975970b 100644 (file)
@@ -64,9 +64,9 @@ Let's see the previous example again:
 
 But you don't have to memorize what each of these codes mean.
 
-You can use the convenience variables from `starlette.status`.
+You can use the convenience variables from `fastapi.status`.
 
-```Python hl_lines="2 7"
+```Python hl_lines="1 6"
 {!./src/response_status_code/tutorial002.py!}
 ```
 
@@ -74,6 +74,11 @@ They are just a convenience, they hold the same number, but that way you can use
 
 <img src="/img/tutorial/response-status-code/image02.png">
 
+!!! note "Technical Details"
+    You could also use `from starlette import status`.
+
+    **FastAPI** provides the same `starlette.status` as `fastapi.status` just as a convenience for you, the developer. But it comes directly from Starlette.
+
 ## Changing the default
 
 Later, in the **Advanced User Guide**, you will see how to return a different status code than the default you are declaring here.
index 163d8126fe88b50c678aa5551b2b8e47fccb8f78..70945f2368bb3e13e0ba8c1ca637edb703bc5ed7 100644 (file)
@@ -86,7 +86,7 @@ And another utility to verify if a received password matches the hash stored.
 
 And another one to authenticate and return a user.
 
-```Python hl_lines="7 39 56 57 60 61 70 71 72 73 74 75 76"
+```Python hl_lines="7  48  55 56  59 60  69 70 71 72 73 74 75"
 {!./src/security/tutorial004.py!}
 ```
 
@@ -115,7 +115,7 @@ Define a Pydantic Model that will be used in the token endpoint for the response
 
 Create a utility function to generate a new access token.
 
-```Python hl_lines="3 6 13 14 15 29 30 31 79 80 81 82 83 84 85 86 87"
+```Python hl_lines="3  6  12 13 14  28 29 30  78 79 80 81 82 83 84 85 86"
 {!./src/security/tutorial004.py!}
 ```
 
@@ -127,7 +127,7 @@ Decode the received token, verify it, and return the current user.
 
 If the token is invalid, return an HTTP error right away.
 
-```Python hl_lines="90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107"
+```Python hl_lines="89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106"
 {!./src/security/tutorial004.py!}
 ```
 
@@ -137,7 +137,7 @@ Create a `timedelta` with the expiration time of the token.
 
 Create a real JWT access token and return it.
 
-```Python hl_lines="116 117 118 119 120 121 122 123 124 125 126 127 128 129"
+```Python hl_lines="115 116 117 118 119 120 121 122 123 124 125 126 127 128"
 {!./src/security/tutorial004.py!}
 ```
 
index 041f8517cae5e00819ddf13972b6905776aec756..d7507a1ec8183e48bc508d8267690ee2e579308a 100644 (file)
@@ -47,7 +47,7 @@ Now let's use the utilities provided by **FastAPI** to handle this.
 
 First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` for the path `/token`:
 
-```Python hl_lines="2 75"
+```Python hl_lines="2  74"
 {!./src/security/tutorial003.py!}
 ```
 
@@ -88,7 +88,7 @@ If there is no such user, we return an error saying "incorrect username or passw
 
 For the error, we use the exception `HTTPException`:
 
-```Python hl_lines="1 76 77 78"
+```Python hl_lines="1  75 76 77"
 {!./src/security/tutorial003.py!}
 ```
 
@@ -116,7 +116,7 @@ If your database is stolen, the thief won't have your users' plaintext passwords
 
 So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
 
-```Python hl_lines="79 80 81 82"
+```Python hl_lines="78 79 80 81"
 {!./src/security/tutorial003.py!}
 ```
 
@@ -154,7 +154,7 @@ For this simple example, we are going to just be completely insecure and return
 
     But for now, let's focus on the specific details we need.
 
-```Python hl_lines="84"
+```Python hl_lines="83"
 {!./src/security/tutorial003.py!}
 ```
 
@@ -179,7 +179,7 @@ Both of these dependencies will just return an HTTP error if the user doesn't ex
 
 So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
 
-```Python hl_lines="57 58 59 60 61 62 63 64 65 68 69 70 71 88"
+```Python hl_lines="56 57 58 59 60 61 62 63 64 65  67 68 69 70  88"
 {!./src/security/tutorial003.py!}
 ```
 
index d4f456209dc4367e1bce69089eb393b342185f7f..77fd2c8f46ab5d244d741bd540ff73840d933cd9 100644 (file)
@@ -626,7 +626,7 @@ A "middleware" is basically a function that is always executed for each request,
 
 The middleware we'll add (just a function) will create a new SQLAlchemy `SessionLocal` for each request, add it to the request and then close it once the request is finished.
 
-```Python hl_lines="16 17 18 19 20 21 22 23 24"
+```Python hl_lines="14 15 16 17 18 19 20 21 22"
 {!./src/sql_databases/sql_app/alt_main.py!}
 ```
 
@@ -639,7 +639,7 @@ The middleware we'll add (just a function) will create a new SQLAlchemy `Session
 
 ### About `request.state`
 
-<a href="https://www.starlette.io/requests/#other-state" class="external-link" target="_blank">`request.state` is a property of each Starlette `Request` object</a>. It is there to store arbitrary objects attached to the request itself, like the database session in this case.
+`request.state` is a property of each `Request` object. It is there to store arbitrary objects attached to the request itself, like the database session in this case. You can read more about it in <a href="https://www.starlette.io/requests/#other-state" class="external-link" target="_blank">Starlette's docs about `Request` state</a>.
 
 For us in this case, it helps us ensure a single database session is used through all the request, and then closed afterwards (in the middleware).
 
index 77ffdee8237a7b235e8700ae0c00a7802dfb042a..1b0725291311d16b89cb72cc1ec7f948da66f6fc 100644 (file)
@@ -1,4 +1,4 @@
-You can serve static files automatically from a directory using <a href="https://www.starlette.io/staticfiles/" class="external-link" target="_blank">Starlette's Static Files</a>.
+You can serve static files automatically from a directory using `StaticFiles`.
 
 ## Install `aiofiles`
 
@@ -10,13 +10,18 @@ pip install aiofiles
 
 ## Use `StaticFiles`
 
-* Import `StaticFiles` from Starlette.
+* Import `StaticFiles`.
 * "Mount" a `StaticFiles()` instance in a specific path.
 
 ```Python hl_lines="2 6"
 {!./src/static_files/tutorial001.py!}
 ```
 
+!!! note "Technical Details"
+    You could also use `from starlette.staticfiles import StaticFiles`.
+
+    **FastAPI** provides the same `starlette.staticfiles` as `fastapi.staticfiles` just as a convenience for you, the developer. But it actually comes directly from Starlette.
+
 ### What is "Mounting"
 
 "Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
index 5eaf6e778d11741ff07cd45d0bb01055907da74a..1b1da2ab28a9f8d8f72cb477b6726ca091423292 100644 (file)
@@ -1,4 +1,4 @@
-Thanks to <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette's TestClient</a>, testing **FastAPI** applications is easy and enjoyable.
+Thanks to <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a>, testing **FastAPI** applications is easy and enjoyable.
 
 It is based on <a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests</a>, so it's very familiar and intuitive.
 
@@ -6,7 +6,7 @@ With it, you can use <a href="https://docs.pytest.org/" class="external-link" ta
 
 ## Using `TestClient`
 
-Import `TestClient` from `starlette.testclient`.
+Import `TestClient`.
 
 Create a `TestClient` passing to it your **FastAPI**.
 
@@ -16,7 +16,7 @@ Use the `TestClient` object the same way as you do with `requests`.
 
 Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
 
-```Python hl_lines="2 12 15 16 17 18"
+```Python hl_lines="2  12  15 16 17 18"
 {!./src/app_testing/tutorial001.py!}
 ```
 
@@ -27,6 +27,11 @@ Write simple `assert` statements with the standard Python expressions that you n
 
     This allows you to use `pytest` directly without complications.
 
+!!! note "Technical Details"
+    You could also use `from starlette.testclient import TestClient`.
+
+    **FastAPI** provides the same `starlette.testclient` as `fastapi.testclient` just as a convenience for you, the developer. But it comes directly from Starlette.
+
 ## Separating tests
 
 In a real application, you probably would have your tests in a different file.
index 313bc5e193fa71f0fc2d80041b50cd3c5b4cfc08..b558d111e0e6fa41f06a2f8f56bfd47f8256332a 100644 (file)
@@ -2,9 +2,10 @@
 
 __version__ = "0.50.0"
 
-from starlette.background import BackgroundTasks
+from starlette import status
 
 from .applications import FastAPI
+from .background import BackgroundTasks
 from .datastructures import UploadFile
 from .exceptions import HTTPException
 from .param_functions import (
@@ -18,4 +19,7 @@ from .param_functions import (
     Query,
     Security,
 )
+from .requests import Request
+from .responses import Response
 from .routing import APIRouter
+from .websockets import WebSocket
diff --git a/fastapi/background.py b/fastapi/background.py
new file mode 100644 (file)
index 0000000..2d0d3d3
--- /dev/null
@@ -0,0 +1 @@
+from starlette.background import BackgroundTasks  # noqa
index 03ed2d08d489ae0d51dc977032325281f1ddf1b0..451923c550c318f50dbd6586b4229f624f5412d8 100644 (file)
@@ -1,7 +1,8 @@
 from typing import Any, Callable
 
 from starlette.concurrency import iterate_in_threadpool  # noqa
-from starlette.concurrency import run_in_threadpool
+from starlette.concurrency import run_in_threadpool  # noqa
+from starlette.concurrency import run_until_first_complete  # noqa
 
 asynccontextmanager_error_message = """
 FastAPI's contextmanager_in_threadpool require Python 3.7 or above,
diff --git a/fastapi/middleware/__init__.py b/fastapi/middleware/__init__.py
new file mode 100644 (file)
index 0000000..6601b17
--- /dev/null
@@ -0,0 +1 @@
+from starlette.middleware import Middleware
diff --git a/fastapi/middleware/cors.py b/fastapi/middleware/cors.py
new file mode 100644 (file)
index 0000000..4c08a16
--- /dev/null
@@ -0,0 +1 @@
+from starlette.middleware.cors import CORSMiddleware  # noqa
diff --git a/fastapi/middleware/gzip.py b/fastapi/middleware/gzip.py
new file mode 100644 (file)
index 0000000..08460d0
--- /dev/null
@@ -0,0 +1 @@
+from starlette.middleware.gzip import GZipMiddleware  # noqa
diff --git a/fastapi/middleware/httpsredirect.py b/fastapi/middleware/httpsredirect.py
new file mode 100644 (file)
index 0000000..674263a
--- /dev/null
@@ -0,0 +1 @@
+from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware  # noqa
diff --git a/fastapi/middleware/trustedhost.py b/fastapi/middleware/trustedhost.py
new file mode 100644 (file)
index 0000000..b16aee8
--- /dev/null
@@ -0,0 +1 @@
+from starlette.middleware.trustedhost import TrustedHostMiddleware  # noqa
diff --git a/fastapi/middleware/wsgi.py b/fastapi/middleware/wsgi.py
new file mode 100644 (file)
index 0000000..bf8d3e6
--- /dev/null
@@ -0,0 +1 @@
+from starlette.middleware.wsgi import WSGIMiddleware  # noqa
diff --git a/fastapi/requests.py b/fastapi/requests.py
new file mode 100644 (file)
index 0000000..eb13f03
--- /dev/null
@@ -0,0 +1 @@
+from starlette.requests import Request  # noqa
diff --git a/fastapi/responses.py b/fastapi/responses.py
new file mode 100644 (file)
index 0000000..69bf5c9
--- /dev/null
@@ -0,0 +1,8 @@
+from starlette.responses import FileResponse  # noqa
+from starlette.responses import HTMLResponse  # noqa
+from starlette.responses import JSONResponse  # noqa
+from starlette.responses import PlainTextResponse  # noqa
+from starlette.responses import RedirectResponse  # noqa
+from starlette.responses import Response  # noqa
+from starlette.responses import StreamingResponse  # noqa
+from starlette.responses import UJSONResponse  # noqa
index 7f3dc49774cf593150b21969837d1d73e0fabe8b..b36104869648a53520304f9d6cfdc0b3aa5531da 100644 (file)
@@ -29,6 +29,7 @@ from starlette.concurrency import run_in_threadpool
 from starlette.exceptions import HTTPException
 from starlette.requests import Request
 from starlette.responses import JSONResponse, Response
+from starlette.routing import Mount  # noqa
 from starlette.routing import (
     compile_path,
     get_name,
diff --git a/fastapi/staticfiles.py b/fastapi/staticfiles.py
new file mode 100644 (file)
index 0000000..78359dd
--- /dev/null
@@ -0,0 +1 @@
+from starlette.staticfiles import StaticFiles  # noqa
diff --git a/fastapi/templating.py b/fastapi/templating.py
new file mode 100644 (file)
index 0000000..d4c035c
--- /dev/null
@@ -0,0 +1 @@
+from starlette.templating import Jinja2Templates  # noqa
diff --git a/fastapi/testclient.py b/fastapi/testclient.py
new file mode 100644 (file)
index 0000000..0288f69
--- /dev/null
@@ -0,0 +1 @@
+from starlette.testclient import TestClient  # noqa
diff --git a/fastapi/websockets.py b/fastapi/websockets.py
new file mode 100644 (file)
index 0000000..2edf973
--- /dev/null
@@ -0,0 +1,2 @@
+from starlette.websockets import WebSocket  # noqa
+from starlette.websockets import WebSocketDisconnect  # noqa
index 88cd1f6ca5877b84470785e5b65e711a71036266..b1f88184f10ee8c7ec84fbf5930b1a854d0eafac 100644 (file)
@@ -51,14 +51,14 @@ nav:
             - Sub-dependencies: 'tutorial/dependencies/sub-dependencies.md'
             - Dependencies in path operation decorators: 'tutorial/dependencies/dependencies-in-path-operation-decorators.md'
             - Dependencies with yield: 'tutorial/dependencies/dependencies-with-yield.md'
-        - Security: 
+        - Security:
             - Security Intro: 'tutorial/security/index.md'
             - First Steps: 'tutorial/security/first-steps.md'
             - Get Current User: 'tutorial/security/get-current-user.md'
             - Simple OAuth2 with Password and Bearer: 'tutorial/security/simple-oauth2.md'
             - OAuth2 with Password (and hashing), Bearer with JWT tokens: 'tutorial/security/oauth2-jwt.md'
-        - Middleware: 'tutorial/middleware.md'    
-        - CORS (Cross-Origin Resource Sharing): 'tutorial/cors.md'    
+        - Middleware: 'tutorial/middleware.md'
+        - CORS (Cross-Origin Resource Sharing): 'tutorial/cors.md'
         - SQL (Relational) Databases: 'tutorial/sql-databases.md'
         - Bigger Applications - Multiple Files: 'tutorial/bigger-applications.md'
         - Background Tasks: 'tutorial/background-tasks.md'
@@ -71,21 +71,22 @@ nav:
         - Path Operation Advanced Configuration: 'advanced/path-operation-advanced-configuration.md'
         - Additional Status Codes: 'advanced/additional-status-codes.md'
         - Return a Response Directly: 'advanced/response-directly.md'
-        - Custom Response Class: 'advanced/custom-response.md'
+        - Custom Response - HTML, Stream, File, others: 'advanced/custom-response.md'
         - Additional Responses in OpenAPI: 'advanced/additional-responses.md'
         - Response Cookies: 'advanced/response-cookies.md'
         - Response Headers: 'advanced/response-headers.md'
         - Response - Change Status Code: 'advanced/response-change-status-code.md'
         - Advanced Dependencies: 'advanced/advanced-dependencies.md'
         - Advanced Security:
-            - Advanced Security - Intro: advanced/security/index.md
+            - Advanced Security - Intro: 'advanced/security/index.md'
             - OAuth2 scopes: 'advanced/security/oauth2-scopes.md'
             - HTTP Basic Auth: 'advanced/security/http-basic-auth.md'
         - Using the Request Directly: 'advanced/using-request-directly.md'
+        - Advanced Middleware: 'advanced/middleware.md'
         - SQL (Relational) Databases with Peewee: 'advanced/sql-databases-peewee.md'
         - Async SQL (Relational) Databases: 'advanced/async-sql-databases.md'
         - NoSQL (Distributed / Big Data) Databases: 'advanced/nosql-databases.md'
-        - Sub Applications - Behind a Proxy: 'advanced/sub-applications-proxy.md'
+        - Sub Applications - Behind a Proxy, Mounts: 'advanced/sub-applications-proxy.md'
         - Templates: 'advanced/templates.md'
         - GraphQL: 'advanced/graphql.md'
         - WebSockets: 'advanced/websockets.md'
@@ -96,6 +97,7 @@ nav:
         - Testing Dependencies with Overrides: 'advanced/testing-dependencies.md'
         - Extending OpenAPI: 'advanced/extending-openapi.md'
         - OpenAPI Callbacks: 'advanced/openapi-callbacks.md'
+        - Including WSGI - Flask, Django, others: 'advanced/wsgi.md'
     - Concurrency and async / await: 'async.md'
     - Deployment: 'deployment.md'
     - Project Generation - Template: 'project-generation.md'
@@ -105,7 +107,7 @@ nav:
     - Benchmarks: 'benchmarks.md'
     - Help FastAPI - Get Help: 'help-fastapi.md'
     - Development - Contributing: 'contributing.md'
-    - Release Notes: release-notes.md
+    - Release Notes: 'release-notes.md'
 
 markdown_extensions:
     - toc:
index 3805104ea504d39a85ef940325d85b16d1675081..58e53c3eec2f5c7e40e9122f501d836ca37b3fe8 100644 (file)
@@ -58,7 +58,8 @@ test = [
     "async_generator",
     "python-multipart",
     "aiofiles",
-    "ujson"
+    "ujson",
+    "flask"
 ]
 doc = [
     "mkdocs",
index 71165e0465fd9a5cba6a5c4c1f0b8cadea8db5b4..de38ce050538ff31c8e166331d2b59dbcc995579 100644 (file)
@@ -1,8 +1,8 @@
 from typing import Dict
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 09b4446ee7e6019698d075fecb80e70384d4bb9a..a20036cc7fd172db5fd648757fadc1b34465b1ed 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import APIRouter, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 router = APIRouter()
 
index fb9208ba8069698c94964f21186795ac04649900..d2eb4d7a1942a2a5cfc1acaf9c38cf655c78d0bd 100644 (file)
@@ -1,6 +1,6 @@
 import pytest
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 65fa62875eaf87cbdf9227b19d7e583bf294eff5..ce21bca24e59746a60677e49882bdc96bc66e152 100644 (file)
@@ -1,9 +1,9 @@
 import typing
 
 from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.responses import JSONResponse
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 3453575845292c13e61739f20f4ca6a9219c1023..c7f56367b588eff52cb784d9d2d7d33b3fc58cfd 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index a26724afa8ca1917aefcd6ee1dbc5237753ce5aa..4d4e1db891197111b98c8952171be75ba031ecb1 100644 (file)
@@ -1,9 +1,9 @@
 import typing
 
 from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.responses import JSONResponse
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index c54d73a3ec754bfc4500b0a470b94b0a46bda6c9..bc5efeb035a362946e76f111a8de81e078847349 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import APIRouter, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 router = APIRouter()
index ba5f2e9408d776589a7999dc9f84b00cf1db4350..f4d294e1b7fb24d1ed54a474550d195193ee4383 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from .main import app
 
index bcc60a0231a2921371f10d469c8bb661bef06798..8aaf4488498e19a15b15fa9b18b5357d4bd0d2f5 100644 (file)
@@ -1,7 +1,7 @@
 from functools import partial
 
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 
 def main(some_arg, q: str = None):
index cca32e399f55f0520f136dbe2a97aa9925a3843a..afca4732fff93efe078b66ec9729f45c7c79a659 100644 (file)
@@ -1,7 +1,7 @@
 import pytest
 from fastapi import APIRouter, FastAPI
 from fastapi.routing import APIRoute
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 0b14e925071102f80e1928a1aefd334ce56f8211..ac724f8fb46ec429c5b6e249f596115974b83de0 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 swagger_ui_oauth2_redirect_url = "/docs/redirect"
 
index 75b40b3bf2c373e00aee761bc5b1ce04f933776f..5c1833eb4cea62fee637b1b0739a7cc742208999 100644 (file)
@@ -1,8 +1,8 @@
 from datetime import datetime, timezone
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 
 class ModelWithDatetimeField(BaseModel):
index 4905945b55315599de19b93afdd9c14c397bd0ca..042fb1dea93231e9cfd06378f1b66366008a37e6 100644 (file)
@@ -2,8 +2,8 @@ from typing import Any
 
 import orjson
 from fastapi import APIRouter, FastAPI
-from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse
-from starlette.testclient import TestClient
+from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
+from fastapi.testclient import TestClient
 
 
 class ORJSONResponse(JSONResponse):
index 95aada4097df56b1f75539866a7bc87bbbe0762c..87415e18828397e497283519edf275443b064435 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import APIRouter, FastAPI
-from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse
-from starlette.testclient import TestClient
+from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
+from fastapi.testclient import TestClient
 
 
 class OverrideResponse(JSONResponse):
index e9d027b1d07e062db5fdcbf31d85898727ba1c08..dc7a14cd4b56c4fba0c105a369d814f6b9241319 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import Depends, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index db1f5cc8fe70aa96eac9ef7270e3581c66fe7d9f..4b3bd724322b1abdbe45ce12cc11f374b89fb4c0 100644 (file)
@@ -1,6 +1,6 @@
 import pytest
 from fastapi import Depends, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 5771b0fd8671b1408a682a3d71ec4a3b1685ceb9..5090e5459d11731ed7e8972f4094036a0f113e08 100644 (file)
@@ -2,7 +2,7 @@ from typing import Dict
 
 import pytest
 from fastapi import BackgroundTasks, Depends, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 state = {
index 7faf12ea5f548daec6987a2a6b19dbc88e238824..3cee6f8ad815ac9576087931957766976f665ac3 100644 (file)
@@ -1,6 +1,6 @@
 import pytest
 from fastapi import APIRouter, Depends, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index c38fae8551e2774c7228a1f0551bcad2ba6f07f6..ccca5dbd34fcececfed39c0ff4f32521f2c5a78e 100644 (file)
@@ -1,6 +1,6 @@
 import pytest
 from fastapi import APIRouter, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index d9e1f321d9ec25e1726ff62fb1e2efdb4ac55152..150ae1e078735e8f9da39d36799fd4aa71e2d1fa 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.responses import JSONResponse
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 1f7d1deed24ea879ee4ebad6c90b2c7317e6021a..9d631cc0215f7e793eb6f691b460f56107636189 100644 (file)
@@ -1,7 +1,7 @@
 import pytest
 from fastapi import Depends, FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel, ValidationError, validator
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 0e47e906ae75b41eb9315ea5405a18c04c4563e2..a34ec44c29612105952678a828bcb864de1d4446 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI, Form
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index c194d2060fd8263d021d23bb4b87d51846e89cba..61bf34f40400fb7de6a021c19ad4402e2bf16af5 100644 (file)
@@ -1,7 +1,6 @@
-from fastapi import APIRouter, FastAPI
-from starlette.requests import Request
-from starlette.responses import JSONResponse
-from starlette.testclient import TestClient
+from fastapi import APIRouter, FastAPI, Request
+from fastapi.responses import JSONResponse
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 router = APIRouter()
index 3175f72d30b80d444f3dbfafe2a837996f61aeee..6d189989777f7a43e4efec074faa138522e7e0f1 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import APIRouter, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index a9f673898359162cc70903ea5497a5496c8f7548..1ed5bf1b9d9f0f56f85761f28ea8b1301d5e05b5 100644 (file)
@@ -2,8 +2,8 @@ import uuid
 
 import pytest
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index a2dcb6e572fbd46e5e5a82104c89968a16d5fb37..e73b5c408b5ea9f7e4f25c3fc8d39ff0af905c17 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from .app.main import app
 
index d506fe7f64aeaca2b818e35295ef3de599dc4c0e..23e6b64d556ec9e39d1c19323fc8300758d8fa5e 100644 (file)
@@ -2,8 +2,8 @@ from decimal import Decimal
 from typing import List
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel, condecimal
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index c2785479fa4cb4a9b2ef3edc746266d851a15cef..467ed9f4fb6c1f9497d230e555279b11edb159a6 100644 (file)
@@ -1,7 +1,7 @@
 from typing import List
 
 from fastapi import FastAPI, Query
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 542f78e7a143d336b0a27614230bfa0f804637c0..b403fa64c940012e933476d92617e1f28bc44fb1 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI(swagger_ui_oauth2_redirect_url=None)
 
index 8a3d62589e0e2a550cf967fb45d410f04bc23fcc..3066f22bfabba243741f8e40132c1ce79e7aab7e 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI
 from fastapi.params import Param
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 55b667ee9f744a5260b08f6660386d1c6a8e89fe..214d90174096f911ad212abe68df1fc0fc41e323 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import Depends, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index f1ef58038b0e426b99f7b69e3a87707bb07cc58b..26b65e695d220266a73f8eb925c1521478a60b43 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from .main import app
 
index 0a7cec2a2a5f37472342d4b7f215f0c6af2e1ebf..95dbf03d2c8ecbdcc371adc83e3cf5e01d8bba52 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 92cff2bb5a2487f648e61814ef5987ff8d6c8628..cdbdd1ccdcd15380e8c1c6d5317d76a5481fd655 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from .main import app
 
index 042e962e9910cdedd37c4faaf5a8b9cd43dd0cbb..fd616e12ad16738c243838fd3972fa44e74ca5c1 100644 (file)
@@ -1,6 +1,5 @@
-from fastapi import Depends, FastAPI, Header
-from starlette.status import HTTP_200_OK
-from starlette.testclient import TestClient
+from fastapi import Depends, FastAPI, Header, status
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
@@ -89,7 +88,7 @@ schema = {
 
 def test_schema():
     response = client.get("/openapi.json")
-    assert response.status_code == HTTP_200_OK
+    assert response.status_code == status.HTTP_200_OK
     actual_schema = response.json()
     assert actual_schema == schema
     assert (
@@ -99,5 +98,5 @@ def test_schema():
 
 def test_response():
     response = client.get("/", headers={"someheader": "hello"})
-    assert response.status_code == HTTP_200_OK
+    assert response.status_code == status.HTTP_200_OK
     assert response.json() == {"dep1": "hello", "dep2": "hello123"}
index 89b98b2203cca916e631c9c204133951645af01a..2eecd45eaa105199bd7ec8253dd05434c5771a15 100644 (file)
@@ -1,8 +1,8 @@
 import typing
 
 from fastapi import Body, FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 0e2ba883365d06a26170b653a85118d63c6de532..d401b81b05cf7241805547457b4296f09a25b98e 100644 (file)
@@ -1,6 +1,5 @@
-from fastapi import Depends, FastAPI
-from starlette.responses import Response
-from starlette.testclient import TestClient
+from fastapi import Depends, FastAPI, Response
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index b8969a35e0fb6ff65a37f1469a5ec94d5e4e04ae..ab869c3c5dbce72eb14ff44794ffaef7ddf2edd9 100644 (file)
@@ -1,9 +1,9 @@
 import typing
 
-from fastapi import FastAPI
+from fastapi import FastAPI, Response
+from fastapi.responses import JSONResponse
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.responses import JSONResponse, Response
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 0d5051b3c89f525c4dc1358f6773f007ce6adbc1..7d658d0cf7c4777acb9afd339a1ed36d9b91ac45 100644 (file)
@@ -1,9 +1,9 @@
 import typing
 
 from fastapi import FastAPI
+from fastapi.responses import JSONResponse
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.responses import JSONResponse
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index ac12098377e38e7d09804218e600ba175fa43e3b..3f146481280bfe8a14e9bc2d46b4d75f73882875 100644 (file)
@@ -1,8 +1,8 @@
 from typing import List
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 
 class Model(BaseModel):
index 3a499b149e840bd9ec00c9c418128990ee77f250..5aeb966f30478acb7df655d8982fa46eee2b5569 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import APIRouter, FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 
 class State(BaseModel):
index febd664c2b5564af0fa19bae140e5f0afe5c186a..b331c24bdf42f2f4c28aea17ea463b63642e1ac4 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import APIRouter, FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index ed59526b18c80a9b39b053081416548cd2c5f916..6b9642988103eb70172df8fd972735f06a961bcb 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import APIKeyCookie
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index a0edbcfae834e227e50ea094f120626680ed2027..0f3da9ad5edc01ddcfc6914ffcd014ceedf46757 100644 (file)
@@ -2,8 +2,8 @@ from typing import Optional
 
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import APIKeyCookie
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 057beb5ed0d5b77119b98fb9136e67f2d8a81904..a871a65fe419fb2de7d849c88c0522a6f7bec220 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import APIKeyHeader
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 9f264dc5f5fb47f6aedd79ab7c06dde043db950a..f71bac9cf6ccf566ff63cc6598f04ef5c0efd656 100644 (file)
@@ -2,8 +2,8 @@ from typing import Optional
 
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import APIKeyHeader
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 680f79a70dfa60fa834344c51dbfb0a8bb77c1cc..228f2a7a3baf9a058b61454fd3bc6b24d1326b87 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import APIKeyQuery
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 2142adf7dcfa7567dcebc32905092b7c63a2368b..ddbdd55671edd4b69fe8f65a8b86078a228a1cb3 100644 (file)
@@ -2,8 +2,8 @@ from typing import Optional
 
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import APIKeyQuery
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 5b937b8817aac1552f692314eef62fc676a1bbe5..7e2c191ef10379fc46fe8331f0126f652cbca559 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI, Security
 from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBase
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index d9e93e1b9cdcd91869acf575d89f83ad0d174bde..4cc757dfb43bdbc23ac78a6e06a08ad96aa3d20c 100644 (file)
@@ -2,7 +2,7 @@ from typing import Optional
 
 from fastapi import FastAPI, Security
 from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBase
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 4b2f433cf399df4c8877d01db589db0ae801abc8..b80fadff312e56a80843eba2e4914dfbe1c1a23d 100644 (file)
@@ -3,8 +3,8 @@ from typing import Optional
 
 from fastapi import FastAPI, Security
 from fastapi.security import HTTPBasic, HTTPBasicCredentials
+from fastapi.testclient import TestClient
 from requests.auth import HTTPBasicAuth
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 9a11ebda9deff6c7c88b4b5c6509adaed7b8f121..117c9ef0244d2f1773a7fd1c94be3db8a7c0d856 100644 (file)
@@ -2,8 +2,8 @@ from base64 import b64encode
 
 from fastapi import FastAPI, Security
 from fastapi.security import HTTPBasic, HTTPBasicCredentials
+from fastapi.testclient import TestClient
 from requests.auth import HTTPBasicAuth
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index e8a004cf0e949963ea00a0f6767a92ef0e597a71..a05fbf4472b0df62c3096be3e66b87692ddd1981 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI, Security
 from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index b666284696f970fcc742cabe4d5cf02e58afcf7d..f1f202abb61dd0147aef077523601b56756e2193 100644 (file)
@@ -2,7 +2,7 @@ from typing import Optional
 
 from fastapi import FastAPI, Security
 from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 5ffeac92bcc9d647c465d9cf57a4773a1019db02..e6b9919916bfc7abe5ca0ca8ea406e3bf47cfa65 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI, Security
 from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 21ec872f6e3d1909bf8cd62c9834be5c147f0a24..83c4539351fd010961b94416bbb3f84ab10c0ed0 100644 (file)
@@ -2,7 +2,7 @@ from typing import Optional
 
 from fastapi import FastAPI, Security
 from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 692c498637afd2997194fb617b6b7ae243ea7661..3f96846d48c679f19f4aee6add495ee5e1beb08e 100644 (file)
@@ -2,8 +2,8 @@ import pytest
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import OAuth2
 from fastapi.security.oauth2 import OAuth2PasswordRequestFormStrict
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 8cfc9ac1004ebaf7151cd9a2fc15e09fb6488ec1..ab088d67c7973d95150dc21acfba0dfb027b575e 100644 (file)
@@ -2,7 +2,7 @@ from typing import Optional
 
 from fastapi import FastAPI, Security
 from fastapi.security import OAuth2AuthorizationCodeBearer
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index 648adefb753757b15a89bb99ffb5f44f669abb7d..8732dd03701dcd3f1e91c2b7d5ae2e5ae9ab0831 100644 (file)
@@ -4,8 +4,8 @@ import pytest
 from fastapi import Depends, FastAPI, Security
 from fastapi.security import OAuth2
 from fastapi.security.oauth2 import OAuth2PasswordRequestFormStrict
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 4a702770be152afdf053befc4e911c538af39417..0c36796aef8af84083576dfd3198f50689fce918 100644 (file)
@@ -2,7 +2,7 @@ from typing import Optional
 
 from fastapi import FastAPI, Security
 from fastapi.security import OAuth2PasswordBearer
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index fc9f50d40f9eeabc7eb66854c3a85adb398351fc..07596ecfe02141c9f5992f8735bc8214830b8675 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import Depends, FastAPI, Security
 from fastapi.security.open_id_connect_url import OpenIdConnect
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 874aba672bb7ac779c032a8144a0a8d4e6d42f2e..8aff16f28225072aafbacee1c481dd270621ed20 100644 (file)
@@ -2,8 +2,8 @@ from typing import Optional
 
 from fastapi import Depends, FastAPI, Security
 from fastapi.security.open_id_connect_url import OpenIdConnect
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 5fff871f0f0ca0fd4e42b17462f2de0b315f30fe..1ec957177d60aded612285e527ec3d86cf3119b5 100644 (file)
@@ -1,8 +1,8 @@
 from typing import List
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index ee701f9696f7703e0c7bd44dabe7e5421e9dc144..4bbb0c2c15e7e25595ddc0f1afc451ad16fd1c77 100644 (file)
@@ -1,8 +1,8 @@
 from typing import List
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic.dataclasses import dataclass
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 36b2de53768db7691ff4fde0b469f65a93e0f670..c9a85a305a3c301fbbb992c35f8b05fa0dd1f06c 100644 (file)
@@ -1,8 +1,8 @@
 from typing import Optional
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 6fb458979d6b5c6814a4b94b683e45a84bf24965..6cd9b8208b034abc579f8fecbc8d313ccc632bc8 100644 (file)
@@ -1,6 +1,6 @@
 from fastapi import FastAPI, HTTPException
+from fastapi.testclient import TestClient
 from starlette.exceptions import HTTPException as StarletteHTTPException
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index c928d5596034b7c035ff19c0ddad22615b507a78..97fa41f2986c2992018b11d621dc4e2d19b6fef8 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI, Path
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 app = FastAPI()
 
index b05b532c691db18751b5c251079a6601911148ed..c5a22e8b7c5ce46b351d1b63d4d2351493c41280 100644 (file)
@@ -1,7 +1,7 @@
 from fastapi import APIRouter, FastAPI
+from fastapi.responses import JSONResponse
+from fastapi.testclient import TestClient
 from pydantic import BaseModel, HttpUrl
-from starlette.responses import JSONResponse
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 37af939306fa6c3f4597bf1a0285f05ee301b229..fc6b265dbcb3a888073bd6a6469787ad3bb9b855 100644 (file)
@@ -1,5 +1,5 @@
 from fastapi import FastAPI
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 swagger_ui_init_oauth = {"clientId": "the-foo-clients", "appName": "The Predendapp"}
 
index dc0cc5963b7e84f6bb7a492d7221da7a56814550..b6ba63f5ab6e882cd94cb39c391908fb67028a2b 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from additional_responses.tutorial001 import app
 
index c3e9fe1baae13e74caa1b1d8e7b6bbfa10852bab..09a06d957771e19a6733c18cf20734cbe0ca6975 100644 (file)
@@ -1,7 +1,7 @@
 import os
 import shutil
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from additional_responses.tutorial002 import app
 
index ba1ba39d3a635db921e1ec783931d9370775b1bc..52144f7ae29ec262edb7c6957f42f9d8ecf3bc26 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from additional_responses.tutorial003 import app
 
index 2d24de28ed5c1ccc557f053477302cfe40c19441..d1285c8ea2009eee2b2a5b82c149129521df0fcd 100644 (file)
@@ -1,7 +1,7 @@
 import os
 import shutil
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from additional_responses.tutorial004 import app
 
index 1d33796c5c4a9ea10619c773778b17844934d8ca..ccfe343dc46c1d1dcbb8619ac30650b8d4138204 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from additional_status_codes.tutorial001 import app
 
diff --git a/tests/test_tutorial/test_advanced_middleware/__init__.py b/tests/test_tutorial/test_advanced_middleware/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial001.py
new file mode 100644 (file)
index 0000000..f49f50f
--- /dev/null
@@ -0,0 +1,14 @@
+from fastapi.testclient import TestClient
+
+from advanced_middleware.tutorial001 import app
+
+
+def test_middleware():
+    client = TestClient(app, base_url="https://testserver")
+    response = client.get("/")
+    assert response.status_code == 200
+
+    client = TestClient(app)
+    response = client.get("/", allow_redirects=False)
+    assert response.status_code == 307
+    assert response.headers["location"] == "https://testserver/"
diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial002.py
new file mode 100644 (file)
index 0000000..da1d60b
--- /dev/null
@@ -0,0 +1,15 @@
+from fastapi.testclient import TestClient
+
+from advanced_middleware.tutorial002 import app
+
+
+def test_middleware():
+    client = TestClient(app, base_url="http://example.com")
+    response = client.get("/")
+    assert response.status_code == 200
+    client = TestClient(app, base_url="http://subdomain.example.com")
+    response = client.get("/")
+    assert response.status_code == 200
+    client = TestClient(app, base_url="http://invalidhost")
+    response = client.get("/")
+    assert response.status_code == 400
diff --git a/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py b/tests/test_tutorial/test_advanced_middleware/test_tutorial003.py
new file mode 100644 (file)
index 0000000..0d482b8
--- /dev/null
@@ -0,0 +1,22 @@
+from fastapi.responses import PlainTextResponse
+from fastapi.testclient import TestClient
+
+from advanced_middleware.tutorial003 import app
+
+
+@app.get("/large")
+async def large():
+    return PlainTextResponse("x" * 4000, status_code=200)
+
+
+client = TestClient(app)
+
+
+def test_middleware():
+    response = client.get("/large", headers={"accept-encoding": "gzip"})
+    assert response.status_code == 200
+    assert response.text == "x" * 4000
+    assert response.headers["Content-Encoding"] == "gzip"
+    assert int(response.headers["Content-Length"]) < 4000
+    response = client.get("/")
+    assert response.status_code == 200
index ab79a089521cda76bfdbe368aa22ce8f247a4066..40c545e0357ec651b69e854227050dae7353774b 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from application_configuration.tutorial001 import app
 
index 088a96b7f8f81697eeebc2d7c3e919f72534150a..553f42c2f4526c0f895526e677f72eb72ef8b56d 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from async_sql_databases.tutorial001 import app
 
index f86f7f9dc30d878fa67d827729822a7ab76d12cc..a1381a9d5a9ef78b1d88f489caed90ae31e5d9e0 100644 (file)
@@ -1,7 +1,7 @@
 import os
 from pathlib import Path
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from background_tasks.tutorial001 import app
 
index 69c8b7f92dfa324496b166ff1f8c02c880a19696..861e83aef081bbdd1a6ed4b4e857e399bbb40be7 100644 (file)
@@ -1,7 +1,7 @@
 import os
 from pathlib import Path
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from background_tasks.tutorial002 import app
 
index 1e5bbeff4338940d926f323ca08037597643f810..b60bd6499c3859d88bbb7b73c340528d8fc18edd 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from bigger_applications.app.main import app
 
index 078e4febd43ea4ddf35271954763a5ad48839329..f3aded151eb3b3a4f1d686f5afccfd34aead728b 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from body.tutorial001 import app
 
index 8f2c21f281f942b4b31289e9df657fba0e2ec9f0..a437c62ec17b184c73fb20cbe5cc1c02015f1963 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from body_fields.tutorial001 import app
 
index 6352e5853fc37ecdbcf5d19bb59eb9b2e4afce82..6241396f361c88522765e32bc5402e6c9fb8b584 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from body_multiple_params.tutorial001 import app
 
index 7dcf9edd846a5eae9cfeb6f3fda210cc67785a27..d93da39fce182ba1539688ec99b02f4ac827abd9 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from body_multiple_params.tutorial003 import app
 
index fa1dd4e9471345c4cdfb616e2709bd986f2a2fa1..7ea7e5c74f63a7c7c15eaab9812c929d2a26a3f6 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from body_nested_models.tutorial009 import app
 
index 1626c280a0271743b84ad07e0c742352a1191a4f..d0777655601f7e4231b05e90751a6b5a5dc39a6e 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from body_updates.tutorial001 import app
 
index 1dcdb8287be22b8d06f80d1d4dd7ca801c44ed0d..7b644d9f376da20080e9017a5d0c41e0d0409237 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from cookie_params.tutorial001 import app
 
diff --git a/tests/test_tutorial/test_cors/__init__.py b/tests/test_tutorial/test_cors/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/test_tutorial/test_cors/test_tutorial001.py b/tests/test_tutorial/test_cors/test_tutorial001.py
new file mode 100644 (file)
index 0000000..dc3078e
--- /dev/null
@@ -0,0 +1,37 @@
+from fastapi.testclient import TestClient
+
+from cors.tutorial001 import app
+
+
+def test_cors():
+    client = TestClient(app)
+    # Test pre-flight response
+    headers = {
+        "Origin": "https://localhost.tiangolo.com",
+        "Access-Control-Request-Method": "GET",
+        "Access-Control-Request-Headers": "X-Example",
+    }
+    response = client.options("/", headers=headers)
+    assert response.status_code == 200
+    assert response.text == "OK"
+    assert (
+        response.headers["access-control-allow-origin"]
+        == "https://localhost.tiangolo.com"
+    )
+    assert response.headers["access-control-allow-headers"] == "X-Example"
+
+    # Test standard response
+    headers = {"Origin": "https://localhost.tiangolo.com"}
+    response = client.get("/", headers=headers)
+    assert response.status_code == 200
+    assert response.json() == {"message": "Hello World"}
+    assert (
+        response.headers["access-control-allow-origin"]
+        == "https://localhost.tiangolo.com"
+    )
+
+    # Test non-CORS response
+    response = client.get("/")
+    assert response.status_code == 200
+    assert response.json() == {"message": "Hello World"}
+    assert "access-control-allow-origin" not in response.headers
index 2b4b474cb054a4ce39e714fa9dfa3cb60242fde1..2546a1274c1c5244faaafd76a1a2a071a4f9b0b2 100644 (file)
@@ -2,8 +2,8 @@ import gzip
 import json
 
 import pytest
-from starlette.requests import Request
-from starlette.testclient import TestClient
+from fastapi import Request
+from fastapi.testclient import TestClient
 
 from custom_request_and_route.tutorial001 import app
 
index a50760b237b16b4f3d3256dcddba240b44848156..59daaf73bbf9f72c96138c90734bceffe49eb994 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from custom_request_and_route.tutorial002 import app
 
index bc4ccacbd4fa5e056e0fd632217422cf076cf01c..73905f9f5db3ea68cc59bf62b9b2e260f1d4e0c6 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from custom_request_and_route.tutorial003 import app
 
index 0a46d64b40617d253549120359f3a71105dd858a..0152d0134c9e22407a793cf7558c5cb6883b30d9 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from custom_response.tutorial001 import app
 
index 03ee004e35077b70f49df871d0a68750d20b10db..c9d120058699a17e1f8ca44182a59fc378c87183 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from custom_response.tutorial004 import app
 
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial005.py b/tests/test_tutorial/test_custom_response/test_tutorial005.py
new file mode 100644 (file)
index 0000000..4755408
--- /dev/null
@@ -0,0 +1,36 @@
+from fastapi.testclient import TestClient
+
+from custom_response.tutorial005 import app
+
+client = TestClient(app)
+
+openapi_schema = {
+    "openapi": "3.0.2",
+    "info": {"title": "FastAPI", "version": "0.1.0"},
+    "paths": {
+        "/": {
+            "get": {
+                "summary": "Main",
+                "operationId": "main__get",
+                "responses": {
+                    "200": {
+                        "description": "Successful Response",
+                        "content": {"text/plain": {"schema": {"type": "string"}}},
+                    }
+                },
+            }
+        }
+    },
+}
+
+
+def test_openapi_schema():
+    response = client.get("/openapi.json")
+    assert response.status_code == 200
+    assert response.json() == openapi_schema
+
+
+def test_get():
+    response = client.get("/")
+    assert response.status_code == 200
+    assert response.text == "Hello World"
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial006.py b/tests/test_tutorial/test_custom_response/test_tutorial006.py
new file mode 100644 (file)
index 0000000..2a90568
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi.testclient import TestClient
+
+from custom_response.tutorial006 import app
+
+client = TestClient(app)
+
+
+def test_get():
+    response = client.get("/typer", allow_redirects=False)
+    assert response.status_code == 307
+    assert response.headers["location"] == "https://typer.tiangolo.com"
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial007.py b/tests/test_tutorial/test_custom_response/test_tutorial007.py
new file mode 100644 (file)
index 0000000..90548b5
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi.testclient import TestClient
+
+from custom_response.tutorial007 import app
+
+client = TestClient(app)
+
+
+def test_get():
+    fake_content = b"some fake video bytes"
+    response = client.get("/")
+    assert response.content == fake_content * 10
diff --git a/tests/test_tutorial/test_custom_response/test_tutorial008.py b/tests/test_tutorial/test_custom_response/test_tutorial008.py
new file mode 100644 (file)
index 0000000..8f15861
--- /dev/null
@@ -0,0 +1,17 @@
+from pathlib import Path
+
+from fastapi.testclient import TestClient
+
+from custom_response import tutorial008
+from custom_response.tutorial008 import app
+
+client = TestClient(app)
+
+
+def test_get(tmp_path: Path):
+    file_path: Path = tmp_path / "large-video-file.mp4"
+    tutorial008.some_file_path = str(file_path)
+    test_content = b"Fake video bytes"
+    file_path.write_bytes(test_content)
+    response = client.get("/")
+    assert response.content == test_content
index 15e8f3a51e3a6990d7533e84458a13980005be0b..353e5c8ab7b0d263714d3bf69414a5326f3bd3a2 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from dependencies.tutorial001 import app
 
index c938c2d41cec7bfc7f8f80f30a828c30fa9b9530..7e41bbd3b503ca2a4a98c16dcb5fb7737e4e9889 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from dependencies.tutorial004 import app
 
index 98c49dfc4cacfd24e0fa9a8378bd71f749db46bc..62f13f07a5c957a17289794b5fe673dfeac0ec43 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from dependencies.tutorial006 import app
 
index 9ac638b420e07797b4aea27a4a49311a0640af66..ebd3550af5bc79c6477a0be1e50c012fc936a165 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from events.tutorial001 import app
 
index e9daeb64e5fc8e744cc8c0662ff2a566cdf7c2ed..bb1880247386604ccc1c8e10ea515fe4bea973d3 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from events.tutorial002 import app
 
index 8023bbb75a5c20af2427c7fad69db035fbf3f1ec..c0cb8ddaa6fbff3c7c64d4c10e898baf254456e3 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from extending_openapi.tutorial001 import app
 
index 1058fc18c1fa5653e5756ca89663e61a7e375a73..592fd8420901695c3e3dd202836351c99b27a785 100644 (file)
@@ -2,7 +2,7 @@ import os
 from pathlib import Path
 
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 
 @pytest.fixture(scope="module")
index fe3e4a0128c98f9937c8fbc108a337e5d1f6e4a8..9695bce26d7bc094d556c1c133669985b4fdfa04 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from extra_data_types.tutorial001 import app
 
index 3a50f5e8f0aef8be4834f82494fb4e77d48e3c7f..2662a5710011fd3ef96d384c89940b41494fab4f 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from extra_models.tutorial003 import app
 
index 22a94e09fae65f894eca49918edd8d532e32c9ea..cb3bb33602ee3b0476e0fa5296fe6d4ee851029c 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from extra_models.tutorial004 import app
 
index 3ba23888a56f73211a945b2901c6a68d24a5758e..413c147758cd7799c11c814c6cecc34d15f83da6 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from extra_models.tutorial005 import app
 
index c045b2a48e6ffad9fd4512f1add10d27d3f9d10b..454745dd7c2d4542d6322aa84e69f9e36941c095 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from first_steps.tutorial001 import app
 
index 175668e856fb8c82a7651edfab661c251beb2361..da8ee9864a3c4ee5fe98731a79db98cbf86d1e3a 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from handling_errors.tutorial001 import app
 
index d0f9774c05f643f97e8868bcd638344a3552a6e5..f822ae0a1b707a24ec70ef1de7b2a21e926b5b20 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from handling_errors.tutorial002 import app
 
index abf8b60b62dabeebc0f96e123e6fdbaf500be57e..f63dc10d2bbd1972de268f4b513c3f749b3e04d4 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from handling_errors.tutorial003 import app
 
index 4061e48bbc99abe1e149b9ec1ca7c7a26e936308..eb8d629ece567d896c572f7f25c50112e131e368 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from handling_errors.tutorial004 import app
 
index 511db14a2ae05a4a10cd8ace60a57023541f5c9d..f62c05ae5f233e044b789236bd57a1b2797e0dbd 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from handling_errors.tutorial005 import app
 
index 74f3706842610209e8ba3254e54d4c0ec236c45b..87d9df4e177063edff7c51251460606bd88ab49f 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from handling_errors.tutorial006 import app
 
index e38171bdeee8d210ce75543c4e1c39f876741f3f..f38e8bf9eb7e1d3b6bf3b2c7e677c0cf9b42e539 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from header_params.tutorial001 import app
 
index 456974e7c9e799bb12796082da8f9f9ca7699103..8340542f6fd52cf10706b1b1b83b06506f5966d9 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from openapi_callbacks.tutorial001 import app, invoice_notification
 
index 2cf97b14aa26762442d45bfb011c519bca2f7d14..9ec8bf2e9fc37d9f61566c696f20e3fb779faf41 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_operation_advanced_configuration.tutorial001 import app
 
index e71d786687c77d1f7c447343c1c90e072eec87cb..036ea138a7fece7bfc6eb9b70de8b00f2a3ebbf3 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_operation_advanced_configuration.tutorial002 import app
 
index 26e3171d89bf6a6836727ba99fc335eabc07abc7..f5c26c767ab0b97ee5d053f82bf26117c3114d50 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_operation_advanced_configuration.tutorial003 import app
 
index 519368dc37874554157beb8f7047963de4dfaf51..099710e9260158d6ad835b5235e8de378f842e86 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_operation_advanced_configuration.tutorial004 import app
 
index f0799138da2822c12bf687799eb1eeb2ada95406..b78263c8e6643ae09d63ccb085b02b28ac79c96b 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_operation_configuration.tutorial005 import app
 
index 478f78ac0ea7ee3dcf6ebb0600b356d3c12571ac..5534cb5709b2c88ca8fd529bd2db5381b8a9f7fc 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_operation_configuration.tutorial006 import app
 
index 0ec4b17479fcad54fc3eaae45edb321f8c09a182..a7004b91ad9883a3b2899906ccca77a14d444e46 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_params.tutorial004 import app
 
index aa2e268eeae4ae1dcb220f308a09639391c3eaa2..b7eac1fd25ba36bfc15a58297605031238d19410 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from path_params.tutorial005 import app
 
index f54e9214d7fb8bc319a6e5eb5a921864ac6be531..59acaae9ad276e40ce25dd221d791608c2bda6f1 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from query_params.tutorial005 import app
 
index fe1615f68fb8b2d8828ce68e121e4e53d59a4bf3..a76314e435aa6dfc10f1a3a903c3c302d8ff2421 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from query_params.tutorial006 import app
 
index b8cc9bc69037e6bab51cdec949ccf4bb9c5e3a5c..3dc4f1803c5dc8628524efcf15739b40a1969449 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from query_params.tutorial007 import app
 
index 62b8304bbbcb6b0c493bfc5ec5156d06351ecdd3..cce30d8a002fd7f482c03e7ed62660be88e74735 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from query_params_str_validations.tutorial010 import app
 
index 9d86fa3d92fed92dfbe02882408a5c3656956ced..a498bca824a6aeb97630d2daafb7d61ac8a1b458 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from query_params_str_validations.tutorial011 import app
 
index 005977c4609e5fa1c98821717ff56fcaadc9e6a1..f7fcfe5e24cdaa982f988067061dd23deefbc33b 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from query_params_str_validations.tutorial012 import app
 
index d3d037a6b8edeeaf33f3b9f13f1ca873ddf877f0..d645c4a697aa2dfba7254c09f720fa07c0ff7e17 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from query_params_str_validations.tutorial013 import app
 
index 5db608efa4dea0cd8c5a9f50608431182f1664f7..fdf4eb25455dfa2b5eb7e5f8ed90c1fac45d93e9 100644 (file)
@@ -1,6 +1,6 @@
 import os
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from request_files.tutorial001 import app
 
index bb715d1706dba669be9caa083b619f0546dc904e..811e0f1c730e506677b07505d3e44e16b50f6864 100644 (file)
@@ -1,6 +1,6 @@
 import os
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from request_files.tutorial002 import app
 
index 74b4210fd9c59504c64d020f9e46479981c91d4e..604b63d43e13d295afb64cd609db9a4a6ab80d2d 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from request_forms.tutorial001 import app
 
index bee862bd016dfa027d8c1ea19fc7ccd317d2bd33..38437ee7ebdd98277260929338f396e1d8568fd9 100644 (file)
@@ -1,7 +1,7 @@
 import os
 from pathlib import Path
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from request_forms_and_files.tutorial001 import app
 
index f52ba2070dc1ece23fae08ea12d72c878a220969..4a1675bdee4bf9b2bd87d5c8f5285017e3d88e9d 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_change_status_code.tutorial001 import app
 
index f67091900a6392333a6dc21fd6504dfd53c488b4..eef11665e9ffd7051c37b4aafeaf653bea7e15e6 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_cookies.tutorial001 import app
 
index 1444d638e1ec04a7ea10a03dfbf927f5e67b9e99..045165de3b3d54195d35ad5f30abbb44cb43fcdf 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_cookies.tutorial002 import app
 
index 9a3d172bbbf5113db4f8398fb0339adf45eacabb..8ecc053a5d1eb4e1a409217c27c3a006acbc6fcc 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_headers.tutorial001 import app
 
index 6dc7fdaf1da69896dea0017954e09daa284691da..3674fbecb4971fceebf38c34af793734fe24bcb5 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_headers.tutorial002 import app
 
index 74e2a528b1e5cea1d76b1ff2a0f54fa3ee33134e..34ecae889946dc52aa17732eaf11765e4be04e5a 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_model.tutorial003 import app
 
index deacc2c01f5d541cf3bed34667bf55290be36e5a..0df97e3995609b5bc2e11f3597d13dbbb721d8f6 100644 (file)
@@ -1,5 +1,5 @@
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_model.tutorial004 import app
 
index 37fb1d64c1e8758450b50aa25ede055913d96538..52e91b5c0ec019f35c9fb5d2edfaf69ad0cbacc9 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_model.tutorial005 import app
 
index c1f74ddced7ef3a7756c9a4f443a8660d64c40d4..b6d2cf32244a2ce331c22e9dc3804cf848521066 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from response_model.tutorial006 import app
 
index 5e3f60b42358713f6deeaf45969e77a3aaa38e26..e6257c6da205a5d2d176cb91e6fb285e0dc26ae3 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from security.tutorial001 import app
 
index 5ab0177055af47f266c55d6f5a21be12253b59bc..06a78980d2db3812cce370e0e17dd7c851b732fb 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from security.tutorial003 import app
 
index b4d3455554016437b79104985603c7b020f1312e..6ea608e874a97a53589aa6e8d75b6631db484f68 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from security.tutorial005 import (
     app,
index a0b5a5f05b3a0c448750b128d01039c30b7076a4..e54d62dfbe1e22b505e1e42ba487ce7417e6d2fe 100644 (file)
@@ -1,7 +1,7 @@
 from base64 import b64encode
 
+from fastapi.testclient import TestClient
 from requests.auth import HTTPBasicAuth
-from starlette.testclient import TestClient
 
 from security.tutorial006 import app
 
index 6c9a4cb5e121b7cd0fda01eac6f67e4c99a57c7b..acafa011c29a312cb08c6bc04967184062e413ca 100644 (file)
@@ -1,7 +1,7 @@
 from pathlib import Path
 
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 openapi_schema = {
     "openapi": "3.0.2",
index 313b139e9d0c5088ea2c4cad859ad8075d1877a6..43bc87657c23d73fe53492fa5785eb82cc0a980c 100644 (file)
@@ -1,7 +1,7 @@
 from pathlib import Path
 
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 openapi_schema = {
     "openapi": "3.0.2",
index 2f1830ac098567a1d4085f0ed3402f3398aa20c3..83d20e050400ccd45b2f8403f64c2d58bf670a5f 100644 (file)
@@ -3,7 +3,7 @@ from pathlib import Path
 from unittest.mock import MagicMock
 
 import pytest
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from ...utils import skip_py36
 
index a7158bb17da0dde81c0e0213f9922e1481142608..6ecfa9e9a6dd49c21281abc4fdad2499cdd02afe 100644 (file)
@@ -1,4 +1,4 @@
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 from sub_applications.tutorial001 import app
 
index f53030ae338816822ac5edb6bd3de98a31ce8722..48d6456b49ad109d779904db036880ddf4669ebe 100644 (file)
@@ -1,6 +1,6 @@
 import shutil
 
-from starlette.testclient import TestClient
+from fastapi.testclient import TestClient
 
 
 def test_main():
index e886140f8906d9a79d74a40556e4a8dcf9f2ec97..b30ecf477bead3646e7b961f80989fd15a1cea2a 100644 (file)
@@ -1,6 +1,6 @@
 import pytest
-from starlette.testclient import TestClient
-from starlette.websockets import WebSocketDisconnect
+from fastapi.testclient import TestClient
+from fastapi.websockets import WebSocketDisconnect
 from websockets.tutorial001 import app
 
 client = TestClient(app)
index 063f83c84d5f3f5841fcc4224f3c863eb3f82d9b..9e3e45edb419337bbc8ef6f9cefd8e778f829362 100644 (file)
@@ -1,6 +1,6 @@
 import pytest
-from starlette.testclient import TestClient
-from starlette.websockets import WebSocketDisconnect
+from fastapi.testclient import TestClient
+from fastapi.websockets import WebSocketDisconnect
 from websockets.tutorial002 import app
 
 client = TestClient(app)
diff --git a/tests/test_tutorial/test_wsgi/__init__.py b/tests/test_tutorial/test_wsgi/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/test_tutorial/test_wsgi/test_tutorial001.py b/tests/test_tutorial/test_wsgi/test_tutorial001.py
new file mode 100644 (file)
index 0000000..e5390fc
--- /dev/null
@@ -0,0 +1,17 @@
+from fastapi.testclient import TestClient
+
+from wsgi.tutorial001 import app
+
+client = TestClient(app)
+
+
+def test_flask():
+    response = client.get("/v1/")
+    assert response.status_code == 200
+    assert response.text == "Hello, World from Flask!"
+
+
+def test_app():
+    response = client.get("/v2")
+    assert response.status_code == 200
+    assert response.json() == {"message": "Hello World"}
index 0caaa4f47c34dd97c4f8b2f77826afbbaa145e81..e043041708119fbfeffbce27fc0ec04cdb8d5df7 100644 (file)
@@ -1,8 +1,8 @@
 from typing import Optional, Union
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 60ab8d0cdc5140756e0c14b692149a202312dac8..b901f28e72fb6ec6298c42eb3a51452037951cec 100644 (file)
@@ -1,8 +1,8 @@
 from typing import Optional, Union
 
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel
-from starlette.testclient import TestClient
 
 from .utils import skip_py36
 
index c0382b899438a8298fe32651662f6b06fa7e69bb..25499e8f9381f1f6a980a5977f1ed6a2adb995d2 100644 (file)
@@ -2,8 +2,8 @@ from typing import List
 
 import pytest
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import BaseModel, ValidationError
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 4a066416a6ab121b7960fedb53935dcdd3b8d068..9d78f65ec21f96c9b1f8d0cf387fbcc892e6b8a0 100644 (file)
@@ -2,9 +2,9 @@ from typing import List
 
 import pytest
 from fastapi import FastAPI
+from fastapi.testclient import TestClient
 from pydantic import ValidationError
 from pydantic.dataclasses import dataclass
-from starlette.testclient import TestClient
 
 app = FastAPI()
 
index 019d7cbc7cc1f262a6c68699050bd4e7b2a59c96..fd19e650a9ace44dec428573f6b018834b36368a 100644 (file)
@@ -1,6 +1,5 @@
-from fastapi import APIRouter, FastAPI
-from starlette.testclient import TestClient
-from starlette.websockets import WebSocket
+from fastapi import APIRouter, FastAPI, WebSocket
+from fastapi.testclient import TestClient
 
 router = APIRouter()
 prefix_router = APIRouter()