4
4
.. contents ::
5
5
:local:
6
6
7
- Are there any plans for @app.route decorator like in Flask?
8
- -----------------------------------------------------------
7
+ Are there plans for an @app.route decorator like in Flask?
8
+ ----------------------------------------------------------
9
9
10
- We have it already (*aiohttp>=2.3 * required):
10
+ As of aiohttp 2.3, :class: `~aiohttp.web.RouteTableDef ` provides an API
11
+ similar to Flask's ``@app.route ``. See
11
12
:ref: `aiohttp-web-alternative-routes-definition `.
12
13
13
- The difference is: ``@app.route `` should have an ``app `` in module
14
- global namespace, which makes *circular import hell * easy.
14
+ Unlike Flask's ``@app.route ``, :class: `~aiohttp.web.RouteTableDef `
15
+ does not require an ``app `` in the module namespace (which often leads
16
+ to circular imports).
15
17
16
- *aiohttp * provides a :class: `~aiohttp.web.RouteTableDef ` decoupled
17
- from an application instance::
18
+ Instead, a :class: `~aiohttp.web.RouteTableDef ` is decoupled from an application instance::
18
19
19
20
routes = web.RouteTableDef()
20
21
@@ -30,36 +31,35 @@ global namespace, which makes *circular import hell* easy.
30
31
app.router.add_routes(routes)
31
32
32
33
33
- Has aiohttp the Flask Blueprint or Django App concept ?
34
- ------------------------------------------------------
34
+ Does aiohttp have a concept like Flask's "blueprint" or Django's "app" ?
35
+ -----------------------------------------------------------------------
35
36
36
- If you're planing to write big applications, maybe you must consider
37
- use nested applications. They acts as a Flask Blueprint or like the
38
- Django application concept .
37
+ If you're writing a large application, you may want to consider
38
+ using :ref: ` nested applications < aiohttp-web-nested-applications >`, which
39
+ are similar to Flask's "blueprints" or Django's "apps" .
39
40
40
- Using nested application you can add sub -applications to the main application .
41
+ See: :ref: ` aiohttp-web- nested-applications` .
41
42
42
- see: :ref: `aiohttp-web-nested-applications `.
43
43
44
+ How do I create a route that matches urls with a given prefix?
45
+ --------------------------------------------------------------
44
46
45
- How to create route that catches urls with given prefix?
46
- ---------------------------------------------------------
47
- Try something like::
47
+ You can do something like the following: ::
48
48
49
49
app.router.add_route('*', '/path/to/{tail:.+}', sink_handler)
50
50
51
- Where first argument, star, means catch any possible method
52
- (*GET, POST, OPTIONS *, etc), second matching `` url `` with desired prefix,
53
- third -- handler.
51
+ The first argument, `` * ``, matches any HTTP method
52
+ (*GET, POST, OPTIONS *, etc). The second argument matches URLS with the desired prefix.
53
+ The third argument is the handler function .
54
54
55
55
56
- Where to put my database connection so handlers can access it?
57
- --------------------------------------------------------------
56
+ Where do I put my database connection so handlers can access it?
57
+ ----------------------------------------------------------------
58
58
59
- :class: `aiohttp.web.Application ` object supports :class: `dict `
60
- interface, and right place to store your database connections or any
61
- other resource you want to share between handlers. Take a look on
62
- following example ::
59
+ :class: `aiohttp.web.Application ` object supports the :class: `dict `
60
+ interface and provides a place to store your database connections or any
61
+ other resource you want to share between handlers.
62
+ ::
63
63
64
64
async def go(request):
65
65
db = request.app['db']
@@ -77,71 +77,70 @@ following example::
77
77
return app
78
78
79
79
80
- Why the minimal supported version is Python 3.5.3?
81
- --------------------------------------------------
80
+ Why is Python 3.5.3 the lowest supported version ?
81
+ -------------------------------------------------
82
82
83
- Python 3.5.2 has fixed protocol for async iterators: ``__aiter()__ `` is
84
- not a coroutine but regular function.
83
+ Python 3.5.2 fixes the protocol for async iterators: ``__aiter()__ `` is
84
+ not a coroutine but a regular function.
85
85
86
- Python 3.5.3 is even more important: :func: `asyncio.get_event_loop `
86
+ Python 3.5.3 has a more important change : :func: `asyncio.get_event_loop `
87
87
returns the running loop instance if called from a coroutine
88
- (previously was returning a *default * one , set by
88
+ Previously it returned a *default * loop , set by
89
89
:func: `asyncio.set_event_loop `.
90
90
91
- The change is very crucial, in Python < 3.5.3
92
- :func: `asyncio.get_event_loop ` was not reliable, thus user *was
93
- forced * to pass the event loop instance explicitly everywhere.
94
-
95
- Otherwise if a future object was created for using one event loop
96
- (e.g. default) but a coroutine was run by other loop -- the coroutine
97
- was never awaited, task was *hung *.
91
+ Previous to Python 3.5.3,
92
+ :func: `asyncio.get_event_loop ` was not reliable, so users were
93
+ forced to explicitly pass the event loop instance everywhere.
94
+ If a future object were created for one event loop
95
+ (e.g. the default loop) but a coroutine was run by another loop, the coroutine
96
+ was never awaited. As a result, the task would hang.
98
97
99
- Keep in mind that every ``await `` expression internally either passed
100
- instantly or paused by waiting for a future.
98
+ Keep in mind that every internal ``await `` expression either passed
99
+ instantly or paused, waiting for a future.
101
100
102
101
It's extremely important that all tasks (coroutine runners) and
103
- futures are using the same event loop.
102
+ futures use the same event loop.
104
103
105
104
106
- How a middleware may store a data for using by web-handler later ?
107
- -----------------------------------------------------------------
105
+ How can middleware store data for web handlers to use ?
106
+ ------------------------------------------------------
108
107
109
- :class: `aiohttp.web.Request ` supports :class: `dict ` interface as well
110
- as :class: `aiohttp.web.Application ` .
108
+ Both :class: `aiohttp.web.Request ` and :class: `aiohttp.web.Application `
109
+ support the :class: `dict ` interface .
111
110
112
- Just put data inside * request * ::
111
+ Therefore, data may be stored inside a request object. ::
113
112
114
113
async def handler(request):
115
114
request['unique_key'] = data
116
115
117
- See https://github.com/aio-libs/aiohttp_session code for inspiration,
118
- ``aiohttp_session.get_session(request) `` method uses ``SESSION_KEY ``
119
- for saving request specific session info .
116
+ See https://github.com/aio-libs/aiohttp_session code for an example.
117
+ The ``aiohttp_session.get_session(request) `` method uses ``SESSION_KEY ``
118
+ for saving request- specific session information .
120
119
121
- As of aiohttp 3.0 all response objects are * dict-like * structures as
120
+ As of aiohttp 3.0, all response objects are dict-like structures as
122
121
well.
123
122
124
123
125
124
.. _aiohttp_faq_parallel_event_sources :
126
125
127
- How to receive an incoming events from different sources in parallel?
128
- ---------------------------------------------------------------------
126
+ Can a handler receive incoming events from different sources in parallel?
127
+ -------------------------------------------------------------------------
129
128
130
- For example we have two event sources:
129
+ Yes.
131
130
132
- 1. WebSocket for event from end user
131
+ As an example, we may have two event sources:
133
132
134
- 2. Redis PubSub from receiving events from other parts of app for
135
- sending them to user via websocket.
133
+ 1. WebSocket for events from an end user
136
134
137
- The most native way to perform it is creation of separate task for
138
- pubsub handling.
135
+ 2. Redis PubSub for events from other parts of the application
139
136
140
- Parallel :meth: ` aiohttp.web.WebSocketResponse.receive ` calls are forbidden, only
141
- the single task should perform websocket reading .
137
+ The most native way to handle this is to create a separate task for
138
+ PubSub handling .
142
139
143
- But other tasks may use the same websocket object for sending data to
144
- peer::
140
+ Parallel :meth: `aiohttp.web.WebSocketResponse.receive ` calls are forbidden;
141
+ a single task should perform WebSocket reading.
142
+ However, other tasks may use the same WebSocket object for sending data to
143
+ peers. ::
145
144
146
145
async def handler(request):
147
146
@@ -172,18 +171,17 @@ peer::
172
171
173
172
.. _aiohttp_faq_terminating_websockets :
174
173
175
- How to programmatically close websocket server-side?
176
- ----------------------------------------------------
177
-
174
+ How do I programmatically close a WebSocket server-side?
175
+ --------------------------------------------------------
178
176
179
- For example we have an application with two endpoints:
177
+ Let's say we have an application with two endpoints:
180
178
181
179
182
- 1. ``/echo `` a websocket echo server that authenticates the user somehow
183
- 2. ``/logout_user `` that when invoked needs to close all open
184
- websockets for that user.
180
+ 1. ``/echo `` a WebSocket echo server that authenticates the user
181
+ 2. ``/logout_user `` that, when invoked, closes all open
182
+ WebSockets for that user.
185
183
186
- One simple solution is keeping a shared registry of websocket
184
+ One simple solution is to keep a shared registry of WebSocket
187
185
responses for a user in the :class: `aiohttp.web.Application ` instance
188
186
and call :meth: `aiohttp.web.WebSocketResponse.close ` on all of them in
189
187
``/logout_user `` handler::
@@ -227,11 +225,11 @@ and call :meth:`aiohttp.web.WebSocketResponse.close` on all of them in
227
225
web.run_app(app, host='localhost', port=8080)
228
226
229
227
230
- How to make request from a specific IP address?
231
- -----------------------------------------------
228
+ How do I make a request from a specific IP address?
229
+ ---------------------------------------------------
232
230
233
- If your system has several IP interfaces you may choose one which will
234
- be used used to bind socket locally::
231
+ If your system has several IP interfaces, you may choose one which will
232
+ be used used to bind a socket locally::
235
233
236
234
conn = aiohttp.TCPConnector(local_addr=('127.0.0.1', 0), loop=loop)
237
235
async with aiohttp.ClientSession(connector=conn) as session:
@@ -240,18 +238,18 @@ be used used to bind socket locally::
240
238
.. seealso :: :class:`aiohttp.TCPConnector` and ``local_addr`` parameter.
241
239
242
240
243
- API stability and deprecation policy
244
- ------------------------------------
241
+ What is the API stability and deprecation policy?
242
+ -------------------------------------------------
245
243
246
- *aiohttp * follows strong [SemVer]( https://semver.org/) schema .
244
+ *aiohttp * follows strong ` Semantic Versioning < https://semver.org >`_ (SemVer) .
247
245
248
- Obsolete attributes and methods are marked as *deprecated * in
249
- documentation and raises :class: `DeprecationWarning ` on usage.
246
+ Obsolete attributes and methods are marked as *deprecated * in the
247
+ documentation and raise :class: `DeprecationWarning ` upon usage.
250
248
251
- Let's assume now we have aiohttp ``X.Y.Z `` where ``X `` is * major * version,
249
+ Assume aiohttp ``X.Y.Z `` where ``X `` is major version,
252
250
``Y `` is minor version and ``Z `` is bugfix number.
253
251
254
- E.g. now the latest released version is ``aiohttp==3.0.6 ``.
252
+ For example, if the latest released version is ``aiohttp==3.0.6 ``:
255
253
256
254
``3.0.7 `` fixes some bugs but have no new features.
257
255
@@ -262,61 +260,60 @@ remove it, also all bug fixes from previous release are merged.
262
260
**except ** deprecations from the **last ** ``3.Y `` release. These
263
261
deprecations will be removed by ``5.0.0 ``.
264
262
265
- Unfortunately we have break the rules in case of found **security
266
- vulnerability **.
267
-
263
+ Unfortunately we may have to break these rules when a **security
264
+ vulnerability ** is found.
268
265
If a security problem cannot be fixed without breaking backward
269
- compatibility -- a bugfix release may do it. The probability for this
270
- is very low but shit happens, sorry .
266
+ compatibility, a bugfix release may break compatibility. This is unlikely, but
267
+ possible .
271
268
272
- All * backward incompatible * changes are explicitly marked in
273
- :ref: `CHANGES <aiohttp_changes >` chapter .
269
+ All backward incompatible changes are explicitly marked in
270
+ :ref: `the changelog <aiohttp_changes >`.
274
271
275
272
276
- How to enable gzip compression globally for the whole application?
277
- ------------------------------------------------------------------
273
+ How do I enable gzip compression globally for my entire application?
274
+ --------------------------------------------------------------------
278
275
279
- It's impossible. Choosing what to compress and where don't apply such
280
- time consuming operation is very tricky matter.
276
+ It's impossible. Choosing what to compress and what not to compress is
277
+ is a tricky matter.
281
278
282
- If you need global compression -- write own custom middleware. Or
279
+ If you need global compression, write a custom middleware. Or
283
280
enable compression in NGINX (you are deploying aiohttp behind reverse
284
- proxy, is not it ).
281
+ proxy, right? ).
285
282
286
283
287
- How to manage ClientSession inside web server?
288
- ----------------------------------------------
284
+ How do I manage a ClientSession within a web server?
285
+ ----------------------------------------------------
289
286
290
287
:class: `aiohttp.ClientSession ` should be created once for the lifetime
291
288
of the server in order to benefit from connection pooling.
292
289
293
- Session saves cookies internally. If you don't need cookies processing
290
+ Sessions save cookies internally. If you don't need cookie processing,
294
291
use :class: `aiohttp.DummyCookieJar `. If you need separate cookies
295
- for different http calls but process them in logical chains use single
292
+ for different http calls but process them in logical chains, use a single
296
293
:class: `aiohttp.TCPConnector ` with separate
297
- client session and ``own_connector=False ``.
294
+ client sessions and ``own_connector=False ``.
298
295
299
296
300
- How to access db connection stored in app from subapplication?
301
- --------------------------------------------------------------
297
+ How do I access database connections from a subapplication?
298
+ -----------------------------------------------------------
302
299
303
- Restricting access from subapplication to main (or outer) app is the
300
+ Restricting access from subapplication to main (or outer) app is a
304
301
deliberate choice.
305
302
306
- Subapplication is an isolated unit by design. If you need to share
307
- database object please do it explicitly::
303
+ A subapplication is an isolated unit by design. If you need to share a
304
+ database object, do it explicitly::
308
305
309
306
subapp['db'] = mainapp['db']
310
307
mainapp.add_subapp('/prefix', subapp)
311
308
312
309
313
- How to perform operations in request handler after sending the response?
314
- ------------------------------------------------------------------------
310
+ How do I perform operations in a request handler after sending the response?
311
+ ----------------------------------------------------------------------------
315
312
316
313
Middlewares can be written to handle post-response operations, but
317
314
they run after every request. You can explicitly send the response by
318
315
calling :meth: `aiohttp.web.Response.write_eof `, which starts sending
319
- before the handler returns, giving you space to add follow-up
316
+ before the handler returns, giving you a chance to execute follow-up
320
317
operations::
321
318
322
319
def ping_handler(request):
@@ -332,6 +329,6 @@ operations::
332
329
333
330
return resp
334
331
335
- The :class: `aiohttp.web.Response ` object must be returned. This is
336
- required by aiohttp web contracts, but actually the response has
332
+ A :class: `aiohttp.web.Response ` object must be returned. This is
333
+ required by aiohttp web contracts, even though the response
337
334
already been sent.
0 commit comments