HttpHook and HttpAsyncHook disagree on allowed HTTP methods (surfaced by QUERY) #72619
Replies: 1 comment
|
Thanks for the write-up — I read the provider source to check the asymmetry, and it is exactly as you describe. Two things I can add. 1. Option 1 is verified to work with aiohttp. I ran a local aiohttp server and client (
2. The method whitelist is not the only closed set to fix. The body/payload mapping has the same shape, in params=data if method == "GET" else None
data=data if method in {"POST", "PUT", "PATCH"} else Noneso with For completeness, the third spot you mention is real and already consistent with the divergence: On the direction: option 1 also removes the validation that currently makes a typo'd method fail loudly ( |
Uh oh!
There was an error while loading. Please reload this page.
Summary
HttpHookandHttpAsyncHookdisagree about which HTTP methods they accept. Thesync hook forwards any method it is given, while the async hook rejects anything
outside a hardcoded list. The HTTP
QUERYmethod(draft-ietf-httpbis-safe-method-w-body)
is the case that surfaced this, but the asymmetry is broader than any one method.
I would like to check what the community thinks before opening a PR.
The asymmetry
HttpHook.run()dispatches onGET/HEADand sends everything else through ageneric branch, so an unusual method is passed to
requestsuntouched:method="QUERY"works today on this path — the method and the request body bothreach the wire.
HttpAsyncHook._get_request_func()instead maps method names onto per-verbaiohttphelpers and raises on anything unlisted:So the same
method=value that works withHttpOperatorfails withdeferrable=True. Two further spots encode a similar closed set: the async_request()attaches a body only for{"POST", "PUT", "PATCH"}, andIDEMPOTENT_METHODSinoperators/http.pylists the methods eligible for retry.Why QUERY specifically
QUERY is a safe, idempotent method that carries a request body — intended for
searches too large or too structured for a query string. Several systems people
reach through
HttpOperator(search and graph backends in particular) have begunexposing QUERY endpoints, and the sync/async split means such a Dag silently
stops working the moment it is switched to
deferrable=True.I want to flag the standards caveat honestly: QUERY is an active IETF draft, not
part of RFC 9110, and
aiohttphas nosession.query()helper — a genericsession.request(method, ...)call would be needed. So this is a question aboutwhether Airflow wants to track a draft method, not a settled matter.
Options
Generalise the async dispatch. Replace the per-verb mapping with
session.request(http_method, ...), so the async hook accepts whatever thesync hook accepts. Removes the asymmetry for every method at once rather than
special-casing QUERY. Loosens a currently explicit validation, which may be
deliberate — that is the main thing worth discussing.
Add QUERY to the existing lists. Smaller and more conservative: add it to
the async dispatch, the body-carrying set, and
IDEMPOTENT_METHODS. Keepsvalidation strict, but leaves the underlying divergence in place and commits
the provider to a draft spec by name.
Do nothing for now, and revisit once QUERY is standardised.
I lean toward (1), because the sync/async divergence is a bug in its own right
regardless of what happens to QUERY — but I do not have the history behind the
explicit method list, so I may well be missing the reason it is written that way.
Happy to write the PR and tests for whichever direction people prefer.
Drafted-by: Claude Code (Opus 5); reviewed by @regarmukesh3g before posting
All reactions