Skip to content
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

Merged
merged 1 commit into from Aug 29, 2015
Merged

Add Mount middleware #267

merged 1 commit into from Aug 29, 2015

Conversation

SimonTeixidor
Copy link
Member

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


use hyper::uri::RequestUri::AbsolutePath;

pub struct Mount {
Copy link
Member

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)

@Ryman
Copy link
Member

Ryman commented Aug 23, 2015

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 Ryman mentioned this pull request Aug 24, 2015
@SimonTeixidor
Copy link
Member Author

@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 if, and I'd like to not introduce an extra branch where it is not really needed.

@Ryman
Copy link
Member

Ryman commented Aug 25, 2015

My problem is that all solutions I can think of introduces an extra if, and I'd like to not introduce an extra branch where it is not really needed.

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/"));
Copy link
Member

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?

@SimonTeixidor
Copy link
Member Author

My problem is that all solutions I can think of introduces an extra if, and I'd like to not introduce an extra branch where it is not really needed.

What's the concern with an extra branch?

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.

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"?

Im 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?

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 really sure what motivates the rewrite rules, can you add a comment to rewrite_mount_point with expected behavior?

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.

@Ryman
Copy link
Member

Ryman commented Aug 25, 2015

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() {
Copy link
Member

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

Copy link
Member Author

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 :)

@cburgdorf
Copy link
Member

I've no idea why github doesn't let me add my comment where it belongs so I'll add it here.

would this be a good place to just panic on the basis that it's most likely not what the user intended?

I'm absolutely in favor of the panic! here. It's probably the best way to notify the developer about a misconfiguration.

@GitCop
Copy link

GitCop commented Aug 25, 2015

Thanks for contributing! Unfortunately, I'm here to tell you there were style issues with your Pull Request:

  • Commit: a023aa1
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: dc8043c
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 9169c1d
    • Commits must be in the following format: %{type}(%{scope}): %{description}

Guidelines are available at https://github.com/nickel-org/nickel.rs/blob/master/contributing.md


This message was auto-generated by https://gitcop.com

@SimonTeixidor
Copy link
Member Author

I've fixed the broken logic discovered by @Ryman, removed the rewrite rules and replaced them with a panic!, and fixed the unnecessary copy when the mount point does not match the request.

@homu
Copy link
Contributor

homu commented Aug 25, 2015

☔ The latest upstream changes (presumably #270) made this pull request unmergeable. Please resolve the merge conflicts.

@cburgdorf
Copy link
Member

Yay! We finally have a bot! Love it :)

@GitCop
Copy link

GitCop commented Aug 25, 2015

Thanks for contributing! Unfortunately, I'm here to tell you there were style issues with your Pull Request:

  • Commit: a023aa1
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: dc8043c
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 9169c1d
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 3e7bda5
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 807566e
    • Commits must be in the following format: %{type}(%{scope}): %{description}

Guidelines are available at https://github.com/nickel-org/nickel.rs/blob/master/contributing.md


This message was auto-generated by https://gitcop.com

@GitCop
Copy link

GitCop commented Aug 26, 2015

Thanks for contributing! Unfortunately, I'm here to tell you there were style issues with your Pull Request:

  • Commit: a023aa1
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: dc8043c
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 9169c1d
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 3e7bda5
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 807566e
    • Commits must be in the following format: %{type}(%{scope}): %{description}
  • Commit: 4193447
    • Commits must be in the following format: %{type}(%{scope}): %{description}

Guidelines are available at https://github.com/nickel-org/nickel.rs/blob/master/contributing.md


This message was auto-generated by https://gitcop.com

@Ryman
Copy link
Member

Ryman commented Aug 28, 2015

@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?

@SimonTeixidor
Copy link
Member Author

I squashed the commits, let's see if the tests pass and you can feel free to merge it!

@Ryman
Copy link
Member

Ryman commented Aug 29, 2015

@homu r+

@homu
Copy link
Contributor

homu commented Aug 29, 2015

📌 Commit 0000000 has been approved by Ryman

@Ryman
Copy link
Member

Ryman commented Aug 29, 2015

Err, it's definitely not commit 00000000

@Ryman
Copy link
Member

Ryman commented Aug 29, 2015

@homu r-

@Ryman
Copy link
Member

Ryman commented Aug 29, 2015

@homu r+

@homu
Copy link
Contributor

homu commented Aug 29, 2015

📌 Commit 0000000 has been approved by Ryman

@Ryman
Copy link
Member

Ryman commented Aug 29, 2015

Sigh :D, let's see what happens I guess

@Ryman
Copy link
Member

Ryman commented Aug 29, 2015

@homu r+

@homu
Copy link
Contributor

homu commented Aug 29, 2015

💊 [DEBUG] head_sha reset from 0000000000000000000000000000000000000000 to 0f25836

@homu
Copy link
Contributor

homu commented Aug 29, 2015

📌 Commit 0f25836 has been approved by Ryman

homu added a commit that referenced this pull request Aug 29, 2015
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
@homu
Copy link
Contributor

homu commented Aug 29, 2015

⌛ Testing commit 0f25836 with merge 0622106...

@homu
Copy link
Contributor

homu commented Aug 29, 2015

☀️ Test successful - status

@homu homu merged commit 0f25836 into nickel-org:master Aug 29, 2015
@Ryman
Copy link
Member

Ryman commented Aug 29, 2015

Thanks @barosl! 🏄

@cburgdorf
Copy link
Member

That's awesome! I'll test that with my classroom project later this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants