Commit Graph

93 Commits

Author SHA1 Message Date
Anders Kaseorg
e769e546b6 tornado: Use Signal.asend.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2025-02-14 15:27:51 -08:00
Alex Vandiver
7c20f1d3ea tornado: Always copy requester_for_logs from initial request.
The previous logic over-wrote the requester with the old value if it
had been set to anything in the new request, which it never could have
been.  This logic likely stems from confusion in the hasattr
introduced in `89394fc1ebee`.

Always copy the `requester_for_logs` from the first half of the
request.
2025-02-13 12:40:53 -08:00
Alex Vandiver
7ed35845df tornado: Remove incorrect rate_limit request note.
1ea2f188ce mistakenly introduced a `_rate_limit` member of the
request, which was dutifully transcribed in 3f9a5e1e17.  However,
`_rate_limit` was never read from, nor written to -- `_ratelimit` (with
no middle `_`) was the dict that contained rate-limiting data.  This
`_ratelimit` dict was later renamed to the `_ratelimits_applied` list,
in e86cfbdbd7, which became the `ratelimits_applied` request note
field in 03693cd27e.

Remove the entirely unused `rate_limit` note, and properly copy the
`ratelimits_applied` data into the new request.
2025-02-13 12:40:53 -08:00
Anders Kaseorg
0fa5e7f629 ruff: Fix UP035 Import from collections.abc, typing instead.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg
531b34cb4c ruff: Fix UP007 Use X | Y for type annotations.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg
e08a24e47f ruff: Fix UP006 Use list instead of List for type annotation.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg
f13e94d9ae requirements: Upgrade Python requirements.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-05-06 12:56:30 -07:00
Alex Vandiver
7e1f212366 tornado: Handle the handler having been cleared by connection close.
As premonitioned in c741c527d7, it is
indeed possible for `get_handler_by_id` to error out by cause the
handler has been unset elsewhere.

Protect the callsites of `get_handler_by_id` to be able to gracefully
handle when the handler has already done away.
2023-12-12 10:29:37 -08:00
Anders Kaseorg
55b26da82b run-dev: Rewrite development proxy with aiohttp.
This allows request cancellation to be propagated to the server.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-12-12 08:07:41 -08:00
Alex Vandiver
c741c527d7 tornado: Support clearing a handler more than once.
4af00f61a8 claimed that `on_finish` and
`on_connection_close` were mutually exclusive.  In cases where a
`DELETE` is called on the queue while a longpoll is in progress, this
can cause _both_ to happen:

- The `DELETE` pushes a `cleanup_queue` event, which triggers
`finish_handler` to begin pushing out an empty event response to the
longpoll connection.

- In the midst of that, in an `await`, the longpoll connection drops,
and `on_connection_close` clears the handler.

- The `await` resumes, calls `finish`, and attempts to clear the
handler.

The easiest solution is to make `clear_handler_by_id` tolerant to
multiple attempts to clear it.  Since these processes run in parallel,
it means that parts may have a `handler_id` but `get_handler_by_id`
may error in attempting to look it up.  We have not observed this in
testing, and I cannot currently prove it is impossible.
2023-12-11 21:05:50 -08:00
Alex Vandiver
4af00f61a8 tornado: Explicitly remove handler when clients disconnect.
This partially reverts 579bdc18f85ea8599c8cf1f53ddb02fd41d97993; it
assumed (based on its documentation) that `on_finish` was called for
all requests, even client-terminated ones.  This is not accurate; it
is only called when the request calls `finish`, which only happens for
successful requests.  This caused every client-closed connection to
leak a handler (ironically, exactly re-introducing the bug previously
fixed in 12a5a3a6e1).

This behaviour was obscured by the development environment's proxy;
see comment added in the previous commit.

Instead of replacing the `clear_handler_by_id` call into
`ClientDescriptor.disconnect_handler`, we instead place it on
`AsyncDjangoHandler.on_connection_close`.  This is more correct for
a few reasons:

- `on_connection_close` will be called if the client goes away during
a request without a client descriptor.  If the handler garbage
collection of handlers runs inside the ClientDescriptor, we leak
handlers.

- `disconnect_handler` also runs when successfully sending an event,
which already calls `on_finish`.  We avoid double-calling
`clear_handler_by_id` by doing it in two clearly exclusive cases,
`on_finish` and `on_connection_close`.

- It combines the creation and garbage collection logic into one
file, decreasing action at a distance which causes memory leaks.
2023-12-11 14:10:39 -08:00
Alex Vandiver
b032b2a4da tornado: Replace a TODO comment with an explanation. 2023-12-11 14:10:39 -08:00
Alex Vandiver
579bdc18f8 tornado: Consistently clear handler, via on_finish.
initialize() is called on every request, and stored the
`RequestHandler` (and thus `HTTPServerRequest`) in a global shared
dict.  However, the object is only removed from that structure if the
request was successful.  This means that failed requests (such as 405
Method Not Allowed) leaked `RequestHandler`s and
`HTTPServerRequest`s.

Move the cleanup to `on_finish`, which is called at the close of all
requests, async and not, successful or not.
2023-12-08 09:23:30 -08:00
Alex Vandiver
8eccb3af20 tornado: Stop supporting HEAD requests.
These are not part of the API, and lead to moderately confusing
behaviour -- they block (or not) requested, but of course send no
actual data in the body.
2023-12-08 09:23:30 -08:00
Alex Vandiver
875622fe57 tornado: Set an explicit SUPPORTED_METHODS. 2023-12-08 09:23:30 -08:00
Anders Kaseorg
3853fa875a python: Consistently use from…import for urllib.parse.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-12-05 13:03:07 -08:00
Anders Kaseorg
a50eb2e809 mypy: Enable new error explicit-override.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-10-12 12:28:41 -07:00
Anders Kaseorg
c09e7d6407 codespell: Correct “requestor” to “requester”.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-06-20 16:17:55 -07:00
Anders Kaseorg
03b3c8522d requirements: Upgrade Python requirements.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-04-25 21:20:33 -07:00
Anders Kaseorg
ff1971f5ad ruff: Fix SIM105 Use contextlib.suppress instead of try-except-pass.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-01-23 11:18:36 -08:00
Anders Kaseorg
fcd81a8473 python: Replace avoidable uses of __special__ attributes.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-10-10 08:32:29 -07:00
Anders Kaseorg
7dcffca50e tornado: Construct Django BaseHandler once, not per-request.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-09-30 11:20:45 -07:00
Anders Kaseorg
4fc3845dc2 tornado: Ignore StreamClosedError.
This was also hidden until 81f7192ca3
(#22301).

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-06-28 16:35:49 -07:00
Anders Kaseorg
0d93ec6214 tornado: Remove dead check for message format.
This was for the old /messages/latest API that was removed in commit
e06722657a.

If we wanted a new check like this, it shouldn’t go in zulip_finish,
because that only runs when the client gets an asynchronous response
from polling an initially-empty queue, and not when the client gets a
synchronous response from polling a nonempty queue.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-06-28 16:35:49 -07:00
Zixuan James Li
a9029c68ea tornado: Make _request an attribute on AsyncDjangoHandler.
For the same reason as `handler_id` has, we define `_request`
as an attribute. Note that the name `request` is already taken.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
2022-06-28 16:03:09 -07:00
Zixuan James Li
56e1f3b725 tornado: Make handler_id an attribute on AsyncDjangoHandler.
This prevents us from relying on a side-effect of `allocate_handler_id`
that monkey-patches `handler_id` on the `AsyncDjangoHandler` object,
allowing mypy to acknowledge the existence of `handler_id` as an `int`.

Signed-off-by: Zixuan James Li <p359101898@gmail.com>
2022-06-28 16:03:09 -07:00
Anders Kaseorg
a7e10ee47e tornado: Send request_started signal in Django thread.
Django’s ASGIHandler does this too and it seems like a good idea.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-06-27 10:14:02 -07:00
Anders Kaseorg
5033beb99c request: Replace tornado_handler weak reference with tornado_handler_id.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-06-25 08:42:23 -07:00
Anders Kaseorg
81f7192ca3 tornado: Add missing await for finish calls.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-06-23 19:22:12 -07:00
Anders Kaseorg
a7f9c4f958 logging: Pass more format arguments to logging.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-06-03 12:27:23 -07:00
Anders Kaseorg
bb6bd900cd response: Replace response.asynchronous attribute with new class.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-05-27 14:27:34 -07:00
Anders Kaseorg
7acb642fa5 requirements: Upgrade to Tornado 6.
Fixes #8913.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-05-02 17:41:49 -07:00
Anders Kaseorg
6fd1a558b7 runtornado: Switch to asyncio event loop.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2022-05-02 17:41:49 -07:00
PIG208
53888e5a26 request: Refactor ZulipRequestNotes to RequestNotes.
This utilizes the generic `BaseNotes` we added for multipurpose
patching. With this migration as an example, we can further support
more types of notes to replace the monkey-patching approach we have used
throughout the codebase for type safety.
2021-09-03 08:48:45 -07:00
PIG208
aa9d73c9f6 typing: Improve typing with assertions.
This fixes some mypy errors discovered with django-stubs.
2021-08-20 05:54:19 -07:00
Anders Kaseorg
fd0ab7c4ec tornado: Call close() on Django HttpResponse objects.
This is necessary to break the uncollectable reference cycle created
by our ‘request_notes.saved_response = json_response(…)’, Django’s
‘response._resource_closers.append(request.close)’, and Python’s
https://bugs.python.org/issue44680.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-20 11:07:36 -07:00
Anders Kaseorg
6564b258f1 request: Weaken ZulipRequestNotes.tornado_handler reference.
This prevents a memory leak arising from Python’s inability to collect
a reference cycle from a WeakKeyDictionary value to its key
(https://bugs.python.org/issue44680).

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-19 16:48:23 -07:00
Anders Kaseorg
7c32134fb5 Revert "Revert "request: Refactor to record rate limit data using ZulipRequestNotes.""
This reverts commit 49eab4efef.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-19 16:48:23 -07:00
PIG208
49eab4efef Revert "request: Refactor to record rate limit data using ZulipRequestNotes."
This reverts commit 3f9a5e1e17.
2021-07-16 09:01:20 -07:00
PIG208
c03b9c95ad request: Store client information using ZulipRequestNotes.
This concludes the HttpRequest migration to eliminate arbitrary
attributes (except private ones that are belong to django) attached
to the request object during runtime and migrated them to a
separate data structure dedicated for the purpose of adding
information (so called notes) to a HttpRequest.
2021-07-14 12:01:07 -07:00
PIG208
5167a93229 request: Move tornado_handler to ZulipRequestNotes. 2021-07-14 12:01:07 -07:00
PIG208
742c17399e request: Move miscellaneous attributes to ZulipRequestNotes.
This includes the migration of fields that require trivial changes
to be migrated to be stored with ZulipRequestNotes.

Specifically _requestor_for_logs, _set_language, _query, error_format,
placeholder_open_graph_description, saveed_response, which were all
previously set on the HttpRequest object at some point. This migration
allows them to be typed.
2021-07-14 12:01:07 -07:00
PIG208
5475334b16 request: Refactor to store requestor_for_logs in ZulipRequestNotes. 2021-07-14 12:01:07 -07:00
PIG208
3f9a5e1e17 request: Refactor to record rate limit data using ZulipRequestNotes.
We will no longer use the HttpRequest to store the rate limit data.
Using ZulipRequestNotes, we can access rate_limit and ratelimits_applied
with type hints support. We also save the process of initializing
ratelimits_applied by giving it a default value.
2021-07-14 12:01:07 -07:00
PIG208
da6e5ddcae request: Move log_data from HttpRequest to ZulipRequestNotes. 2021-07-14 12:01:05 -07:00
PIG208
03693cd27e request: Map HttpRequest to ZulipRequestNotes for typing.
We create a class called ZulipRequestNotes as a new home to all the
additional attributes that we add to the Django HttpRequest object.
This allows mypy to do the typecheck and also enforces type safety.

Most of the attributes are added in the middleware, and thus it is
generally safe to assert that they are not None in a code path that
goes through the middleware. The caller is obligated to do manual
the type check otherwise.

This also resolves some cyclic dependencies that zerver.lib.request
have with zerver.lib.rate_limiter and zerver.tornado.handlers.
2021-07-14 11:52:42 -07:00
Anders Kaseorg
4a04cda956 tornado: Remove unused logger variable.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-07-07 15:13:40 -07:00
orientor
ac203cd9f1 middleware: Add client_version attribute to request. 2021-04-29 17:03:40 -07:00
orientor
6224d83dea middleware: Get client name in LogRequests instead of process_client.
This ensures it is present for all requests; while that was already
essentially true via process_client being called from every standard
decorator, this allows middleware and other code to rely on this
having been set.
2021-04-29 17:03:05 -07:00
Alex Vandiver
4f6fc728cd tornado: Explicitly mark requests as varying by cookie.
The Session middleware only adds `Vary: cookie` if it sees an access
to the from inside of it.  Because we are effectively, from the Django
session middleware's point of view, returning the static content of
`request.saved_response` and never accessing the session, it does not
set `Vary: cookie` on longpoll requests.

Explicitly mark Tornado requests as varying by cookie.
2021-04-02 14:55:22 -07:00