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
Add Mount middleware #267
Add Mount middleware #267
Conversation
|
||
use hyper::uri::RequestUri::AbsolutePath; | ||
|
||
pub struct Mount { |
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.
Should be able to get static dispatch with the following:
pub struct Mount<M: Middleware + Send + Sync + 'static> {
mount_point: String,
middleware: M
}
(It may not be required to specify +Send+Sync+'static
as they are implied by Middleware
but I forget if that propagates)
Looks like it could do the job 👍 I did take a look at iron's version mentioned in #259 and after looking at the code I'm left wondering a bit if we could abstract the core logic and both benefit from improvements, something to consider for the future I guess. As for the api, it does contrast a bit with iron's version where they can mount multiple things with the same mount instance, which I guess could potentially have efficiency benefits if mounting multiple things (while being less efficient for single mounts). I'm happy enough with single mounts for now, but I'm wondering if it's a substantial usecase. Finally, I'm wondering if this is worth isolating in a separate crate? Or do we just hold off until we have infrastructure in place to make that easy (whenever that is)? Again, I'm probably happy enough either way currently. |
@Ryman, I've been through all your comments and adressed everything except the unnecessary copy when the matching branch is not taken. I can't seem to find an elegant way to solve that. If you can, please tell :) My problem is that all solutions I can think of introduces an extra |
What's the concern with an extra branch? |
* Fall-through behaviour, if StaticFilesHandler does not find a matching file, | ||
* the request uri must be reset so that it can be matched against other middleware. | ||
*/ | ||
server.mount("/static/files/", StaticFilesHandler::new("examples/assets/")); |
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.
Looking at this again, the rewrite rules would make this "/static/files"
? In that case, does this mean that the mount will activate for paths such as "/static/files_and_stuff/bar"
and pass the uri as "_and_stuff/bar"
?
I'm also curious about the behavior of "/"
, as the uri passed to the mounted middleware would be ""
if the base route is caught (i.e. the client sends "/"
)? I would have expected "/"
to be passed?
I'm not really sure what motivates the rewrite rules, can you add a comment to rewrite_mount_point
with expected behavior?
No big concerns, just that it looks a bit ugly. If there's a way around it, I'd like to avoid it. Otherwise, no big deal.
Good catch, that's probably right! It's not really related to the rewrite rules though, even without those, this same issue would arise. If the mount path is "/static/files", then we also match "/static/files_and_stuff". If the mount path is "/static/files/", then a request to "/static/files/abc" ends up with the path "abc" where I'd expect it to be "/abc". I think this will work if we make sure that mount paths always end with a slash, and then prepend a slash to the path before calling the underlying middleware. That should solve both those failing cases.
I'm not sure about them either. We can also just document which format mount points must be written in and hope that users get it right. Or, we could check for leading and trailing slash and return an error if the user got it wrong. |
Assuming no-one is trying to mount things on an already running server I think this is a good option which allows people to fail quickly at runtime so they can get their stuff working with least surprise. Does make the usage kind of ugly though if it requires an unwrap, would this be a good place to just panic on the basis that it's most likely not what the user intended? cc @cburgdorf |
impl<M: Middleware> Middleware for Mount<M> { | ||
fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn>, res: Response<'mw>) | ||
-> MiddlewareResult<'mw> { | ||
if let AbsolutePath(path) = req.origin.uri.clone() { |
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.
untested but might work and isn't totally ugly?
let subpath = match req.origin.uri {
AbsolutePath(ref path) if path.starts_with(self.mount_point) => {
AbsolutePath(path[self.mount_point.len()..].to_owned())
},
_ => return Ok(Continue(res))
};
let original = mem::replace(&mut req.origin.uri, subpath);
let result = self.middleware.invoke(req, res);
req.origin.uri = original;
result
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.
Of course! I never thought to return early in the non mathing case! This will probably work and looks nicer than what I could think of :)
I've no idea why github doesn't let me add my comment where it belongs so I'll add it here.
I'm absolutely in favor of the |
Thanks for contributing! Unfortunately, I'm here to tell you there were style issues with your Pull Request:
Guidelines are available at https://github.com/nickel-org/nickel.rs/blob/master/contributing.md This message was auto-generated by https://gitcop.com |
I've fixed the broken logic discovered by @Ryman, removed the rewrite rules and replaced them with a |
☔ The latest upstream changes (presumably #270) made this pull request unmergeable. Please resolve the merge conflicts. |
Yay! We finally have a bot! Love it :) |
Thanks for contributing! Unfortunately, I'm here to tell you there were style issues with your Pull Request:
Guidelines are available at https://github.com/nickel-org/nickel.rs/blob/master/contributing.md This message was auto-generated by https://gitcop.com |
Thanks for contributing! Unfortunately, I'm here to tell you there were style issues with your Pull Request:
Guidelines are available at https://github.com/nickel-org/nickel.rs/blob/master/contributing.md This message was auto-generated by https://gitcop.com |
@simonpersson If you reword commits or squash I think we're good to go with this for now? Or perhaps we should test @cburgdorf's project with commits from this branch? |
I squashed the commits, let's see if the tests pass and you can feel free to merge it! |
@homu r+ |
📌 Commit 0000000 has been approved by |
Err, it's definitely not commit 00000000 |
@homu r- |
@homu r+ |
📌 Commit 0000000 has been approved by |
Sigh :D, let's see what happens I guess |
@homu r+ |
💊 [DEBUG] head_sha reset from 0000000000000000000000000000000000000000 to 0f25836 |
📌 Commit 0f25836 has been approved by |
Add Mount middleware Attempt at #259. This middleware takes a mount point and a `Middleware`. When invoked, the mount point is compared with the incoming request, and if they match the underlying middleware is invoked but with the request path rewritten to have the mount point as root. Ping @cburgdorf
☀️ Test successful - status |
Thanks @barosl! 🏄 |
That's awesome! I'll test that with my classroom project later this week. |
Attempt at #259.
This middleware takes a mount point and a
Middleware
. When invoked, the mount point is compared with the incoming request, and if they match the underlying middleware is invoked but with the request path rewritten to have the mount point as root.Ping @cburgdorf