-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only allow last extractor to mutate the request #1121
Conversation
axum-core/src/extract/mod.rs
Outdated
/// See [`FromRequest`] for more details. | ||
// TODO(david): naming | ||
#[derive(Debug, Clone, Copy)] | ||
pub struct Mut(Infallible); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of this name. Should come up with a better one.
* Panic on overlapping routes in `MethodRouter` * changelog link * add test to ensure `head` and `get` don't overlap
c57b5e4
to
8f5c055
Compare
f6dbabe
to
f6bab0f
Compare
Gonna mark this as a draft until #1086 is merged. |
I think given how hard it was to review #1155 I'll close this and break it up into smaller PRs. Those individual PRs wont compile but I think it'll be easier to review and discuss if the changes are smaller. Then once we're happy with the lower level changes we can fix all the downstream errors. |
Don't worry too much about the large diff. The vast majority of the changes is from code that previously was a
macro_rules
macro now being expanded and committed.Fixes #1115
This is an implementation of the design I suggested here.
All these changes are to address the long standing issue that this fails at
runtime:
It fails because
Request<Body>
removes all the extensions soExtension<Foo>
fails. The solution is to swap the lines so
Request<Body>
runs last.With this change that becomes a compile error:
#[debug_handler]
will give a more precise error.It also makes multiple body extractors a compile error:
It works by changing
FromRequest
toIn practice
R
is eitherMut
orOnce
which are zero sized marker types. Not stokedabout the names 🤷
If you have a
RequestParts<Mut, _>
you cannot remove all the extensions, allheaders, or the body. I.e. the extractor is safe to run multiple times. If you
have a
RequestParts<Once, _>
then you can consume all the headers, extensions,or the body.
So if your extractor needs to consume the body you implement
FromRequest<Once, _>
otherwise you implement
FromRequest<R, _>
.Then the
Handler
impls all now require the last extractor to implementFromRequest<Once, _>
and all the first to implementFromRequest<Mut, _>
.Thus if you have multiple extractors that consume the body that function wont
implement
Handler
.What to focus on when reviewing
Most changes are very mechanical. Just adding an
R
type param to extractorsthat don't care about the body and
Once
if they do.So reviewing should be focused on
axum-core/src/extract/mod.rs
andspecifically which methods
RequestParts<Mut, _>
andRequestParts<Once, _>
gives you access to. All other changes fall from that.
Why is the diff so big?!
The diff is so large because we couldn't use a declarative macro to make all the
Handler
impls, since we have to generate trait bounds in the macro. So I wrotea little internal script that generates the code with
quote
and writes it to afile.
#[derive(FromRequest)]
I removed
#[derive(FromRequest)]
for now since making it work with the newsetup is a lot of work.
For example how should this
implement
FromRequest
? To work it must implementFromRequest<Once, _>
because otherwise it cannot extract
String
. But how can the macro know that?I suppose we could do
but we'd have to be careful not to allow
We could do that in a similar way by requiring only the last field to implement
FromRequest<Once, _>
.All this is a lot of work that I didn't wanna do in this PR. I might work on it
after this is merged but I don't think it should block the release.
TODO
to the new.