Before hook check moved out of routes matching in dispatcher #464

wants to merge 4 commits into


None yet
3 participants

cym0n commented Sep 15, 2013

Run the test in the branch: t/hook_changing_path.t
It will go well.
Now take it in a different directory and run it again (obviously still with Dancer2 in your @inc). It will fail.

It's a self contained test, why should it fail?

Problem is that the dispatcher runs before hooks during the route matching and the before hook we introduced change routes, modifying something we didn't configure (/prefix/configured) in something we did (/configured).

When the script is in the t directory this is not a problem because the Dancer2::Handler::File appends a megasplat route to the app's routes and the before hook can be triggered when testing /prefix/configured against it.
In a directory different from t, Dancer2 environment can't determinate a public directory (under t we have a public...) so the Dancer2::Handler::File can't register itself to the app and the megasplat can't come saving us.

I tried to make the before hook triggered before the route matching, but I'm not sure this is the right thing to do. It makes sense for you?

This is still very dirty code. I left all the old halted context management inside the loop, just copying it also beofre it. But I want your feedback about the question before refactoring.

Problem I exposed has bad side effects in real world. I have a plugin that fails dzil test for that. A good workaround is creating a public directory under the t, but it's a bit dirty...


veryrusty commented Sep 17, 2013

One side effect of moving the call to the before hook prior to route matching is that route params will no longer be available to before hooks.

@cym0n - could you elaborate on what your plugin does and/or why you need to modify the request like you have in the test case in the pull request?


cym0n commented Sep 17, 2013

It's a multilang plugin. Here's the code:
I designed it to have a transparent management of the language routes (/it/, /en/...).

As i said, I was afraid that a modification like this could have side-effect :-)
Problem is that, at this time, every before hook that try to modify path works only for a side effect of a feature completely not related (File Handler).

I was thinking about a new status, different from halted, that could be configured in the Context to manage situations like this.
This way the developer could decide if he needs the path-parsing or if he's changing the path itself and he can trigger the hook before it.

What do you think about a solution like this?


cym0n commented Sep 18, 2013

One side effect of moving the call to the before hook prior to route matching is that route params will no longer be available to before hooks.

I added to the branch a test to keep an eye on this.


cym0n commented Sep 28, 2013

New solution for the problem.
Thinkinkg about it, before hook works well as it is, also managing the route params and it has to be executed after route match to manage them.
So, for situations where you know you're going to rewrite the path and route params are not important I introduced a new hook, the before_match, working before the matching loop.

I'll wait for feedback on this solution before doing some refactoring and documentation.


xsawyerx commented May 19, 2014



cym0n commented May 19, 2014

I suspended my work on this because at the time there was the big refactoring about routes, redirects and forward.
Anyway, my question is still there: do you think it's a good idea add an hook before route matching? In my opinion it could be used by plugin that modify paths...


xsawyerx commented Sep 12, 2014

If it's meant to change the path, people should use Plack::Middleware::Rewrite. This would basically be replacing that for every request inside Dancer. I'd really prefer not to do that.


cym0n commented Sep 13, 2014

My idea was to give the opportunity to develope plugins that can change App routing, using forward directive, keeping all the development inside Dancer2.
Consider that this is already possible for a side effect of the File Handler. The File Handler introduces a megasplat on the bottom of all the routes so route checking always return true and you can manipulate any route.
Introducing an hook as i considered is just a way to avoid route matching in a cleaner way.


xsawyerx commented Sep 13, 2014

While I see your point, I can't think of a single reason to do that other than reimplementing Plack::Middleware::Rewrite at the moment.

I think it would be useful to raise this again when there's an specific thing wished to be implemented. What do you think?


cym0n commented Sep 13, 2014

Actually my Dancer2::Plugin::Multilang use that behaviour, exploiting the File Handler megasplat.
I understand that you see this kind of rewrite work at an architectural level higher then inside the framework and you're right about that.
Allowing rewrite inside a plugin, however, allows developers to create solutions easy to install e ready to work out of the box. Someone could use them with no knowledge about the architecture under the hood.


xsawyerx commented Aug 15, 2015

I'm closing this issue for the following reasons:

  1. The code is quite rough.
  2. It would likely need to be updated to the latest version. (It's been a while.)
  3. I still have not seen a use-case that justifies having a hook for after match and using that instead of something like Plack::Middleware::Rewrite and forward.
  4. I'd like to clean the pull request backlog.

You're more than welcomed to open a PR with a new rebased version and we could discuss it again. I hope that's okay.

Thanks for understanding.

xsawyerx closed this Aug 15, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment