Compare commits

...

14 Commits
0.6.3 ... 0.6.4

Author SHA1 Message Date
Sebastián Ramírez
1f03e85f06 🔖 Release 0.6.4 2019-03-02 22:33:48 +04:00
Sebastián Ramírez
b98bf178a6 📝 Update release notes with WebSockets 2019-03-02 21:51:01 +04:00
Sebastián Ramírez
bbd2198fa2 Add docs for WebSockets (#62) 2019-03-02 21:45:15 +04:00
Sebastián Ramírez
e2723e8480 📝 Update release notes 2019-03-02 20:00:27 +04:00
Sebastián Ramírez
1896153d58 ✏️ Fix typos 2019-03-02 19:54:52 +04:00
Sebastián Ramírez
770b4421f9 📝 Add History, Design and Future to docs 2019-03-02 19:54:15 +04:00
Sebastián Ramírez
e89aacbdf7 📝 Add link to Python docs in debugging section 2019-03-02 17:56:30 +04:00
Sebastián Ramírez
cf25291650 📝 Update release notes 2019-03-02 17:55:07 +04:00
Sebastián Ramírez
13772fbd11 📝 Add note about bigger applications in Docker 2019-03-02 17:52:24 +04:00
Sebastián Ramírez
1d69b6f480 📝 Update release notes 2019-03-02 17:44:48 +04:00
Sebastián Ramírez
01d6aa3dd1 📝 Add docs for debugging 2019-03-02 17:40:01 +04:00
Sebastián Ramírez
74db8ddf9b 📝 Update release notes 2019-03-02 13:53:16 +04:00
Sebastián Ramírez
819b3b2516 📝 Add technical details about async def handling (#61)
#33
2019-03-02 13:48:06 +04:00
Sebastián Ramírez
76fb2879ed ✏️ Fix typo in release notes 2019-03-02 13:02:06 +04:00
31 changed files with 424 additions and 25 deletions

View File

@@ -123,7 +123,7 @@ There are several Flask REST frameworks, but after investing the time and work i
### <a href="https://marshmallow.readthedocs.io/en/3.0/" target="_blank">Marshmallow</a>
One of the main features needed by API systems is data "<abbr title="also called marshalling, convertion">serialization</abbr>" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
One of the main features needed by API systems is data "<abbr title="also called marshalling, conversion">serialization</abbr>" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
Another big feature needed by APIs is data validation, making sure that the data is valid, given certain parameters. For example, that some field is an `int`, and not some random string. This is especially useful for incoming data.
@@ -365,7 +365,7 @@ It is the recommended server for Starlette and **FastAPI**.
!!! check "**FastAPI** recommends it as"
The main web server to run **FastAPI** applications.
You can combine it with Gunicorn, to have an asynchronous multiprocess server.
You can combine it with Gunicorn, to have an asynchronous multi-process server.
Check more details in the <a href="/deployment/" target="_blank">Deployment</a> section.

View File

@@ -329,7 +329,7 @@ So, about the egg and the chicken, how do you call the first `async` function?
If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your path operation function, and FastAPI will know how to do the right thing.
But if you want to use `async` / `await` without FastAPI, <a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" target="_blank">check the official Python docs</a>
But if you want to use `async` / `await` without FastAPI, <a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" target="_blank">check the official Python docs</a>.
### Other forms of asynchronous code
@@ -362,3 +362,39 @@ Let's see the same phrase from above:
That should make more sense now.
All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance.
## Very Technical Details
!!! warning
You can probably skip this.
These are very technical details of how **FastAPI** works underneath.
If you have quite some technical knowledge (co-routines, threads, blocking, etc) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead.
### Path operation functions
When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
### Dependencies
The same applies for dependencies. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
### Sub-dependencies
You can have multiple dependencies and sub-dependencies requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread instead of being "awaited".
### Other utility functions
Any other utility function that you call directly can be created with normal `def` or `async def` and FastAPI won't affect the way you call it.
This is in contrast to the functions that FastAPI calls for you: *path operation functions* and dependencies.
If your utility function is a normal function with `def`, it will be called directly (as you write it in your code), not in a threadpool, if the function is created with `async def` then you should await for that function when you call it in your code.
---
Again, these are very technical details that would probably be useful if you came searching for them.
Otherwise, you should be good with the guidelines from the section above: <a href="#in-a-hurry">In a hurry?</a>.

View File

@@ -74,7 +74,7 @@ All the documentation is in Markdown format in the directory `./docs`.
Many of the tutorials have blocks of code.
In most of the cases, these blocks of code are actual complete applicactions that can be run as is.
In most of the cases, these blocks of code are actual complete applications that can be run as is.
In fact, those blocks of code are not written inside the Markdown, they are Python files in the `./docs/src/` directory.

View File

@@ -81,6 +81,18 @@ docker run -d --name mycontainer -p 80:80 myimage
Now you have an optimized FastAPI server in a Docker container. Auto-tuned for your current server (and number of CPU cores).
#### Bigger Applications
If you followed the section about creating <a href="" target="_blank">Bigger Applications with Multiple Files
</a>, your `Dockerfile` might instead look like:
```Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
COPY ./app /app/app
```
### Check it
You should be able to check it in your Docker container's URL, for example: <a href="http://192.168.99.100/items/5?q=somequery" target="_blank">http://192.168.99.100/items/5?q=somequery</a> or <a href="http://127.0.0.1/items/5?q=somequery" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (or equivalent, using your Docker host).
@@ -145,7 +157,7 @@ Now, from a developer's perspective, here are several things to have in mind whi
* It goes encrypted, but the encrypted contents are the same HTTP protocol.
It is a common practice to have one program/HTTP server runing in the server (the machine, host, etc) and managing all the HTTPS parts, sending the decrypted HTTP requests to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the HTTP response from the application, encrypt it using the appropriate certificate and sending it back to the client using HTTPS. This server is ofter called a <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" target="_blank">TLS Termination Proxy</a>.
It is a common practice to have one program/HTTP server running in the server (the machine, host, etc) and managing all the HTTPS parts, sending the decrypted HTTP requests to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the HTTP response from the application, encrypt it using the appropriate certificate and sending it back to the client using HTTPS. This server is ofter called a <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" target="_blank">TLS Termination Proxy</a>.
### Let's Encrypt

View File

@@ -71,7 +71,7 @@ my_second_user: User = User(**second_user_data)
### Editor support
All the framework was designed to be easy and intuitive to use, all the decisons where tested on multiple editors even before starting development, to ensure the best development experience.
All the framework was designed to be easy and intuitive to use, all the decisions where tested on multiple editors even before starting development, to ensure the best development experience.
In the last Python developer survey it was clear <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" target="_blank">that the most used feature is "autocompletion"</a>.
@@ -89,7 +89,7 @@ Here's how your editor might help you:
![editor support](img/pycharm-completion.png)
You will get completion in code you might even consider imposible before. As for example, the `price` key inside a JSON body (that could have been nested) that comes from a request.
You will get completion in code you might even consider impossible before. As for example, the `price` key inside a JSON body (that could have been nested) that comes from a request.
No more typing the wrong key names, coming back and forth between docs, or scrolling up and down to find if you finally used `username` or `user_name`.
@@ -201,4 +201,4 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on
* You can have deeply **nested JSON** objects and have them all validated and annotated.
* **Extendible**:
* Pydantic allows custom data types to be defined or you can extend validation with methods on a model decorated with the validator decorator.
* 100% test coverage.
* 100% test coverage.

View File

@@ -0,0 +1,83 @@
Some time ago, <a href="https://github.com/tiangolo/fastapi/issues/3#issuecomment-454956920" target="_blank">a **FastAPI** user asked</a>:
> Whats the history of this project? It seems to have come from nowhere to awesome in a few weeks [...]
Here's a little bit of that history.
## Alternatives
I have been creating APIs with complex requirements for several years (Machine Learning, distributed systems, asynchronous jobs, NoSQL databases, etc), leading several teams of developers.
As part of that, I needed to investigate, test and use many alternatives.
The history of **FastAPI** is in great part the history of its predecessors.
As said in the section <a href="https://fastapi.tiangolo.com/alternatives/" target="_blank">Alternatives</a>:
<blockquote markdown="1">
**FastAPI** wouldn't exist if not for the previous work of others.
There have been many tools created before that have helped inspire its creation.
I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools.
But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints).
</blockquote>
## Investigation
By using all the previous alternatives I had the chance to learn from all of them, take ideas, and combine them in the best way I could find for myself and the teams of developers I have worked with.
For example, it was clear that ideally it should be based on standard Python type hints.
Also, the best approach was to use already existing standards.
So, before even starting to code **FastAPI**, I spent several months studying the specs for OpenAPI, JSON Schema, OAuth2, etc. Understanding their relationship, overlap, and differences.
## Design
Then I spent some time designing the developer "API" I wanted to have as a user (as a developer using FastAPI).
I tested several ideas in the most popular Python editors: PyCharm, VS Code, Jedi based editors.
By the last <a href="https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools" target="_blank">Python Developer Survey</a>, that covers about 80% of the users.
It means that **FastAPI** was specifically tested with the editors used by 80% of the Python developers. And as most of the other editors tend to work similarly, all its benefits should work for virtually all editors.
That way I could find the best ways to reduce code duplication as much as possible, to have completion everywhere, type and error checks, etc.
All in a way that provided the best development experience for all the developers.
## Requirements
After testing several alternatives, I decided that I was going to use <a href="https://pydantic-docs.helpmanual.io/" target="_blank">**Pydantic**</a> for its advantages.
Then I contributed to it, to make it fully compliant with JSON Schema, to support different ways to define constraint declarations, and to improve editor support (type checks, autocompletion) based on the tests in several editors.
During the development, I also contributed to <a href="https://www.starlette.io/" target="_blank">**Starlette**</a>, the other key requirement.
## Development
By the time I started creating **FastAPI** itself, most of the pieces were already in place, the design was defined, the requirements and tools were ready, and the knowledge about the standards and specifications was clear and fresh.
## Future
By this point, it's already clear that **FastAPI** with its ideas is being useful for many people.
It is being chosen over previous alternatives for suiting many use cases better.
Many developers and teams already depend on **FastAPI** for their projects (including me and my team).
But still, there are many improvements and features to come.
**FastAPI** has a great future ahead.
And <a href="https://fastapi.tiangolo.com/help-fastapi/" target="_blank">your help</a> is greatly appreciated.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -49,7 +49,7 @@ But then you have to call "that method that converts the first letter to upper c
Was it `upper`? Was it `uppercase`? `first_uppercase`? `capitalize`?
Then, you try with the old programer's friend, editor autocompletion.
Then, you try with the old programmer's friend, editor autocompletion.
You type the first parameter of the function, `first_name`, then a dot (`.`) and then hit `Ctrl+Space` to trigger the completion.

View File

@@ -1,5 +1,19 @@
## Next
## 0.6.4
* Add <a href="https://fastapi.tiangolo.com/async/#very-technical-details" target="_blank">technical details about `async def` handling to docs</a>. PR <a href="https://github.com/tiangolo/fastapi/pull/61" target="_blank">#61</a>.
* Add docs for <a href="https://fastapi.tiangolo.com/tutorial/debugging/" target="_blank">Debugging FastAPI applications in editors</a>.
* Clarify <a href="https://fastapi.tiangolo.com/deployment/#bigger-applications" target="_blank">Bigger Applications deployed with Docker</a>.
* Fix typos in docs.
* Add section about <a href="https://fastapi.tiangolo.com/history-design-future/" target="_blank">History, Design and Future</a>.
* Add docs for using <a href="https://fastapi.tiangolo.com/tutorial/websockets/" target="_blank">WebSockets with **FastAPI**</a>. PR <a href="https://github.com/tiangolo/fastapi/pull/62" target="_blank">#62</a>.
## 0.6.3
* Add Favicons to docs. PR <a href="https://github.com/tiangolo/fastapi/pull/53" target="_blank">#53</a>.
@@ -44,7 +58,7 @@
## 0.4.0
* Add `openapi_prefix`, support for reverse proxy and mounting sub-applicaitons. See the docs at <a href="https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/" target="_blank">https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/</a>: <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank">#26</a> by <a href="https://github.com/kabirkhan" target="_blank">@kabirkhan</a>.
* Add `openapi_prefix`, support for reverse proxy and mounting sub-applications. See the docs at <a href="https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/" target="_blank">https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/</a>: <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank">#26</a> by <a href="https://github.com/kabirkhan" target="_blank">@kabirkhan</a>.
* Update <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">docs/tutorial for SQLAlchemy</a> including note about *DB Browser for SQLite*.

View File

@@ -0,0 +1,15 @@
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
a = "a"
b = "b" + a
return {"hello world": b}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)

View File

@@ -0,0 +1,53 @@
from fastapi import FastAPI
from starlette.responses import HTMLResponse
from starlette.websockets import WebSocket
app = FastAPI()
html = """
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
</head>
<body>
<h1>WebSocket Chat</h1>
<form action="" onsubmit="sendMessage(event)">
<input type="text" id="messageText" autocomplete="off"/>
<button>Send</button>
</form>
<ul id='messages'>
</ul>
<script>
var ws = new WebSocket("ws://localhost:8000/ws");
ws.onmessage = function(event) {
var messages = document.getElementById('messages')
var message = document.createElement('li')
var content = document.createTextNode(event.data)
message.appendChild(content)
messages.appendChild(message)
};
function sendMessage(event) {
var input = document.getElementById("messageText")
ws.send(input.value)
input.value = ''
event.preventDefault()
}
</script>
</body>
</html>
"""
@app.get("/")
async def get():
return HTMLResponse(html)
@app.websocket_route("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Message text was: {data}")
await websocket.close()

View File

@@ -0,0 +1,87 @@
You can connect the debugger in your editor, for example with Visual Studio Code or PyCharm.
## Call `uvicorn`
In your FastAPI application, import and run `uvicorn` directly:
```Python hl_lines="1 15"
{!./src/debugging/tutorial001.py!}
```
### About `__name__ == "__main__"`
The main purpose of the `__name__ == "__main__"` is to have some code that is executed when your file is called with:
```bash
python myapp.py
```
but is not called when another file imports it, like in:
```Python
from myapp import app
```
#### More details
Let's say your file is named `myapp.py`.
If you run it with:
```bash
python myapp.py
```
then the internal variable `__name__` in your file, created automatically by Python, will have as value the string `"__main__"`.
So, the section:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
will run.
---
This won't happen if you import that module (file).
So, if you have another file `importer.py` with:
```Python
from myapp import app
# Some more code
```
in that case, the automatic variable inside of `myapp.py` will not have the variable `__name__` with a value of `"__main__"`.
So, the line:
```Python
uvicorn.run(app, host="0.0.0.0", port=8000)
```
will not be executed.
!!! info
For more information, check <a href="https://docs.python.org/3/library/__main__.html" target="_blank">the official Python docs</a>.
## Run your code with your debugger
Because you are running the Uvicorn server directly from your code, you can call your Python program (your FastAPI application) directly form the debugger.
---
For example, in Visual Studio Code, you can:
* Go to the "Debug" panel.
* "Add configuration...".
* Select "Python"
* Run the debugger with the option "`Python: Current File (Integrated Terminal)`".
It will then start the server with your **FastAPI** code, stop at your breakpoints, etc.
Here's how it might look:
<img src="/img/tutorial/debugging/image01.png">

View File

@@ -109,7 +109,7 @@ UserInDB(**user_in.dict())
So, we get a Pydantic model from the data in another Pydantic model.
#### Unrapping a `dict` and extra keywords
#### Unwrapping a `dict` and extra keywords
And then adding the extra keyword argument `hashed_password=hashed_password`, like in:

View File

@@ -69,7 +69,7 @@ A "schema" is a definition or description of something. Not the code that implem
In this case, OpenAPI is a specification that dictates how to define a schema of your API.
This OpenAPI schema would include your API paths, the posible parameters they take, etc.
This OpenAPI schema would include your API paths, the possible parameters they take, etc.
#### Data "schema"

View File

@@ -96,4 +96,4 @@ For example, you could override the default exception handler with:
!!! info
Note that in this example we set the exception handler with Starlette's `HTTPException` instead of FastAPI's `HTTPException`.
This would ensure that if you use a plug-in or any other third-party tool that raises Starlette's `HTTPException` directly, it will be catched by your exception handler.
This would ensure that if you use a plug-in or any other third-party tool that raises Starlette's `HTTPException` directly, it will be caught by your exception handler.

View File

@@ -1,6 +1,6 @@
This tutorial shows you how to use **FastAPI** with all its features, step by step.
Eeach section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
Each section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
It is also built to work as a future reference.

View File

@@ -1,4 +1,4 @@
**FastAPI** allows you to declare additonal information and validation for your parameters.
**FastAPI** allows you to declare additional information and validation for your parameters.
Let's take this application as example:

View File

@@ -35,7 +35,7 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
But when the form includes files, it is encoded as `multipart/form-data`. If you use `File`, **FastAPI** will know it has to get the files from the correct part of the body.
If you want to read more about these encondings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
!!! warning

View File

@@ -39,7 +39,7 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
But when the form includes files, it is encoded as `multipart/form-data`. You'll read about handling files in the next chapter.
If you want to read more about these encondings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
If you want to read more about these encodings and form fields, head to the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
!!! warning

View File

@@ -40,7 +40,7 @@ And we are using this model to declare our input and the same model to declare o
Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
In this case, it might not be a problem, becase the user himself is sending the password.
In this case, it might not be a problem, because the user himself is sending the password.
But if we use the same model for another path operation, we could be sending the passwords of our users to every client.

View File

@@ -30,7 +30,7 @@ So, we can have sub-dependencies using `Security` too.
`get_current_user` will have a `Security` dependency with the same `oauth2_scheme` we created before.
The same as we were doing before in the path operation direclty, our new dependency will receive a `token` as a `str` from the `Security` dependency:
The same as we were doing before in the path operation directly, our new dependency will receive a `token` as a `str` from the `Security` dependency:
```Python hl_lines="25"
{!./src/security/tutorial002.py!}

View File

@@ -24,14 +24,14 @@ The form field name is `scope` (in singular), but it is actually a long string w
Each "scope" is just a string (without spaces).
They are normally used to declare specific security permissions, for exampe:
They are normally used to declare specific security permissions, for example:
* `"users:read"` or `"users:write"` are common examples.
* `instagram_basic` is used by Facebook / Instagram.
* `https://www.googleapis.com/auth/drive` is used by Google.
!!! info
In OAuth2 a "scope" is just a string that declares a specific permision required.
In OAuth2 a "scope" is just a string that declares a specific permission required.
It doesn't matter if it has other characters like `:`, or if it is a URL.

View File

@@ -130,7 +130,7 @@ This will then give us better editor support inside the path operation function,
{!./src/sql_databases/tutorial001.py!}
```
!!! info "Technical Detail"
!!! info "Technical Details"
The parameter `db` is actually of type `SessionLocal`, but this class (created with `sessionmaker()`) is a "proxy" of a SQLAlchemy `Session`, so, the editor doesn't really know what methods are provided.
But by declaring the type as `Session`, the editor now can know the available methods (`.add()`, `.query()`, `.commit()`, etc) and can provide better support (like completion). The type declaration doesn't affect the actual object.
@@ -247,6 +247,9 @@ Then we should declare the path operation without `async def`, just with a norma
{!./src/sql_databases/tutorial001.py!}
```
!!! note "Very Technical Details"
If you are curious and have a deep technical knowledge, you can check <a href="https://fastapi.tiangolo.com/async/#very-technical-details" target="_blank">the very technical details of how this `async def` vs `def` is handled</a>.
## Migrations
Because we are using SQLAlchemy directly and we don't require any kind of plug-in for it to work with **FastAPI**, we could integrate database <abbr title="Automatically updating the database to have any new column we define in our models.">migrations</abbr> with <a href="https://alembic.sqlalchemy.org" target="_blank">Alembic</a> directly.
@@ -297,7 +300,7 @@ That's something that you can improve in this example application, here's the cu
}
```
## Interact with the database direclty
## Interact with the database directly
If you want to explore the SQLite database (file) directly, independently of FastAPI, to debug its contents, add tables, columns, records, modify data, etc. you can use <a href="https://sqlitebrowser.org/" target="_blank">DB Browser for SQLite</a>.

View File

@@ -21,7 +21,7 @@ Although any other parameter declared normally (for example, the body with a Pyd
But there are specific cases where it's useful to get the `Request` object.
## Use the `Request` object direclty
## Use the `Request` object directly
Let's imagine you want to get the client's IP address/host inside of your *path operation function*.

View File

@@ -0,0 +1,93 @@
You can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" target="_blank">WebSockets</a> with **FastAPI**.
## WebSockets client
### In production
In your production system, you probably have a frontend created with a modern framework like React, Vue.js or Angular.
And to communicate using WebSockets with your backend you would probably use your frontend's utilities.
Or you might have a native mobile application that communicates with your WebSocket backend directly, in native code.
Or you might have any other way to communicate with the WebSocket endpoint.
---
But for this example, we'll use a very simple HTML document with some JavaScript, all inside a long string.
This, of course, is not optimal and you wouldn't use it for production.
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"
{!./src/websockets/tutorial001.py!}
```
## Create a `websocket_route`
In your **FastAPI** application, create a `websocket_route`:
```Python hl_lines="3 47 48"
{!./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.
That is not required, but it's recommended as it will provide you completion and checks inside the function.
!!! info
This `websocket_route` we are using comes directly from <a href="https://www.starlette.io/applications/" target="_blank">Starlette</a>.
That's why the naming convention is not the same as with other API path operations (`get`, `post`, etc).
## 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"
{!./src/websockets/tutorial001.py!}
```
You can receive and send binary, text, and JSON data.
To learn more about the options, check Starlette's documentation for:
* <a href="https://www.starlette.io/applications/" target="_blank">Applications (`websocket_route`)</a>.
* <a href="https://www.starlette.io/websockets/" target="_blank">The `WebSocket` class</a>.
* <a href="https://www.starlette.io/endpoints/#websocketendpoint" target="_blank">Class-based WebSocket handling</a>.
## Test it
If your file is named `main.py`, run your application with:
```bash
uvicorn main:app --debug
```
Open your browser at <a href="http://127.0.0.1:8000" target="_blank">http://127.0.0.1:8000</a>.
You will see a simple page like:
<img src="/img/tutorial/websockets/image01.png">
You can type messages in the input box, and send them:
<img src="/img/tutorial/websockets/image02.png">
And your **FastAPI** application with WebSockets will respond back:
<img src="/img/tutorial/websockets/image03.png">
You can send (and receive) many messages:
<img src="/img/tutorial/websockets/image04.png">
And all of them will use the same WebSocket connection.

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.6.3"
__version__ = "0.6.4"
from .applications import FastAPI
from .routing import APIRouter

View File

@@ -62,10 +62,13 @@ nav:
- Sub Applications - Behind a Proxy: 'tutorial/sub-applications-proxy.md'
- Application Configuration: 'tutorial/application-configuration.md'
- GraphQL: 'tutorial/graphql.md'
- WebSockets: 'tutorial/websockets.md'
- Debugging: 'tutorial/debugging.md'
- Concurrency and async / await: 'async.md'
- Deployment: 'deployment.md'
- Project Generation - Template: 'project-generation.md'
- Alternatives, Inspiration and Comparisons: 'alternatives.md'
- History, Design and Future: 'history-design-future.md'
- Benchmarks: 'benchmarks.md'
- Help FastAPI - Get Help: 'help-fastapi.md'
- Development - Contributing: 'contributing.md'