Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Routing] Redirection from route configuration#25145
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
c11e8ce to859bc4fComparenicolas-grekas commentedNov 24, 2017
PHP-based routing configuration also needs to be patched. |
| /** | ||
| * Common parsing logic between route loaders. | ||
| * | ||
| * @author Samuel Roze <samuel.roze@gmail.com> |
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.
@internal also
sroze commentedNov 24, 2017
@nicolas-grekas we did not add the |
nicolas-grekas commentedNov 24, 2017
| $defaults['_controller'] ='Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction'; | ||
| $defaults['path'] =$redirect; | ||
| }else { | ||
| $defaults['_controller'] ='Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction'; |
nicolas-grekasNov 24, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
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.
But there is a big glitch here: this is in theRouting namespace, and it references something inFrameworkBundle.
We have to fix that.
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.
Good point. For the records, here's@javiereguiluz's answer when@stof's said the same thing. I need to think a bit about it.
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.
I see a few options:
- A simple
class_existscheck on theRedirectControllerto have a user-friendly exception. This references the FrameworkBundle, but is not a hard coupling. - We use a
_redirectattribute, that will be handled by aControllerResolverInterfaceimplementation within the FrameworkBundle. - We use a
_redirectattribute that will be handled by a listener onkernel.requestwithin theHttpKernelcomponent
sroze commentedNov 24, 2017
Right, so you mean we should add a |
| privatefunctionlooksLikeUrl(string$urlOrRouteName):bool | ||
| { | ||
| foreach (array('/','//','http://','https://')as$pattern) { | ||
| if (substr($urlOrRouteName,0,strlen($pattern)) ==$pattern) { |
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 use0 === strpos() instead to be consistent with the codebase (we avoid allocating a new string)
| privatefunctionredirectToDefaults(string$redirect,bool$permanent =false):array | ||
| { | ||
| if ($this->looksLikeUrl($redirect)) { | ||
| $defaults['_controller'] ='Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction'; |
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.
would be better to write it as$defaults = array(..., ...) instead of assigning in an undefined variable
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 sure how that happened - well, I know, refactoring.. - , I'd expect PHP to tell me how bad was that.
| $defaults['_controller'] =$controller; | ||
| } | ||
| if ($redirectTo =$node->getAttribute('redirect-to')) { |
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 forbid to put it at the same time than a controller (check for$defaults['_controller'] being configured already)
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.
Done 👍
| } | ||
| if ($redirectTo =$node->getAttribute('redirect-to')) { | ||
| $defaults +=$this->redirectToDefaults($redirectTo,$node->getAttribute('redirect-permanent')); |
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 good. The attribute value will always be a string. It must be parsed into an actual boolean (see the values accepted byparseDefaultNode for the<bool> tag)
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.
But.. it's working well... not suregetAttribute actually returns onlystrings 🤔
nicolas-grekas commentedNov 24, 2017
As stated in#24640 (comment) and below, I would do it differently: instead of setting a controller, the |
sroze commentedNov 24, 2017
@nicolas-grekas definitely agree, see myproposed options here. |
| return$defaults; | ||
| } | ||
| privatefunctionlooksLikeUrl(string$urlOrRouteName):bool |
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.
I fear any guessing strategy would be fragile. Instead, what about two defaults:
_redirect_to_route_redirect_to_uri
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.
I don't think this is a valid fear: if the string starts with/ or a[scheme]:// then it's an URL seems enough to me. Having two ways of configuring the "target" reduces the DX.
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.
Moreover, we already do that guessing in other parts of the framework. E.g. thelogin_path option in the always delicate Security component.
sroze commentedNov 24, 2017
The real question now is: who is going to handle the |
nicolas-grekas commentedNov 24, 2017
Adding one more question we need to answer: |
sroze commentedNov 24, 2017
I'd say |
0fa3e8e to484121eComparesroze commentedNov 25, 2017
@stof@nicolas-grekas I've updated the PR to use |
nicolas-grekas commentedNov 26, 2017
@sroze what would be the new way of doing this configuration in yaml? Can we do without a listener (yet another one for this looks like overhead to me...) |
sroze commentedNov 26, 2017
The one in the PR description :)
Well... we could. Do you want me to merge with the existing one or doing something else? 🤔 |
62e7de8 to5a35a7fCompare8edd537 to50f9243Comparesroze commentedJan 5, 2018
AppVeyor's failure is not related. It's a network issue. Can somebody restart it? |
sroze commentedJan 15, 2018
ping@Tobion :) |
50f9243 to3266887Comparenicolas-grekas commentedFeb 11, 2018
Now that I know the router a bit better, I'd suggest leveraging |
sroze commentedFeb 11, 2018
Can you guide me through what you have in mind a little bit more? Maybe one way would be to roughly explain how you'd change this pull-request? |
nicolas-grekas commentedFeb 14, 2018
when a |
javiereguiluz commentedMar 9, 2018
I've been thinking about this proposal ... and I propose to make a minor change. Instead of using # redirect_to for absolute or relative URLsblog_show:path:/blog/{slug}redirect_to:/some-relative-urlpermanent:true# redirect_to_route without route argumentsblog_show:path:/blog/{slug}redirect_to_route:'some-other-route'# this also works, to be consistent with the next case:# redirect_to_route: ['some-other-route']# redirect_to_route with route argumentsblog_show:path:/blog/{slug}redirect_to_route:['some-other-route', { arg1: 'value1', arg2: 'value2' }] |
javiereguiluz commentedMar 19, 2018
@sroze I know you are very busy and you also have a much more important PR related to the new Message component ... but it'd be great if you could finish this feature before the Symfony 4.1 "feature freeze" starts in 12 days. Thanks! |
sroze commentedMar 19, 2018
@javiereguiluz yep, agree with you, it would be nice. I'll update the PR this week :) |
sroze commentedMar 20, 2018
I've explored the option of moving this logic directly within the router, especiallywithin the The problem with the current implementation is that is it specific to a few details about the routing and is sort of between the Routing component and the FrameworkBundle bundle. Redirection configuration (while allowed by the Routing component) wouldn't work without the FrameworkBundle, which is not what we'd like. While discussing all of that with@nicolas-grekas, we jumped back to actually... what we are trying to solve: simplifying the YAML configuration. Itmight be that the only issue, for now, is the redirect_to_admin:path:/defaults:_controller:_redirect_pathpath:/adminpermanent:true What do you all think? |
javiereguiluz commentedMar 20, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I haven't looked at the internals ... but from the outside this looks "just" a syntactic sugar that should be "easy" to implement. So, the end-user writes this in YAML: blog_show:path:/blog/{slug}redirect_to:/some-relative-urlpermanent:true And Symfony, when parsing that YAML file, transforms it to this transparently: blog_show:path:/blog/{slug}defaults:_controller:Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectActionpath:/some-relative-urlpermanent:true So, this feature "just" needs to look for a |
sroze commentedMar 20, 2018
@javiereguiluz the real problem is that:
|
javiereguiluz commentedMar 20, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@sroze this is how I imagine the implementation of this feature (the code doesn't work, I just invented it to show what I'm asking for): public function processRoutes($yamlContent){ $routesConfig = Yaml::parse($yamlContent); foreach ($routesConfig as $routeConfig) {+ if (isset($routeConfig['redirect_to'])) {+ $routeConfig['_defaults']['_controller'] = 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction';+ $routeConfig['_defaults']['path'] = $routeConfig['redirect_to'];+ unset($routeConfig['redirect_to']);+ } // ... } return $routeCollection;} |
sroze commentedMar 20, 2018
Yes, I agree with you. But it would mean the Routing component depends on the FrameworkBundle (at least, the way it is now). |
nicolas-grekas commentedMar 20, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I'm now convinced the aliasing feature is all that is needed at least as a first step. This should be a feature of RouterListener in HttpKernel IMHO (could also be in Routing matchers, but I feel better with RouterListener). So down this path, we would just need a Javier has another goal, which is to move defaults out of the "defaults" nesting level. All-in-all, the controller aliasing looks like the right next step to me. |
javiereguiluz commentedMar 22, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
To better compare the alternatives, here is a summary: Current situationblog_show:path:/blog/{slug}defaults:_controller:Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectActionpath:/some-relative-urlpermanent:true Proposal 1blog_show:path:/blog/{slug}redirect_to:/some-relative-urlpermanent:true Proposal 2blog_show:path:/blog/{slug}defaults:_controller:_redirect_pathpath:/some-relative-urlpermanent:true I think it's OK to create a |
nicolas-grekas commentedMar 22, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I'm 👎 for adding redirect specific root-options because it creates a very specific case people will have to learn, whereas the proposed alternative (2) just leverages existing and new generic knowledge. The redirect-specific entries would also prevent using new or exotic redirection options, because these are specific to the actual redirector implementation. |
sroze commentedMar 22, 2018
The only counter-argument to@nicolas-grekas' PoV I can see is that a redirection is not a "very specific case" of routing. |
| { | ||
| $requestAttributes =$event->getRequest()->attributes; | ||
| if (!$requestAttributes->has('_controller') &&$redirectTo =$requestAttributes->get('_redirect_to')) { |
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.
I would use early returns instead:
if ($requestAttributes->has('_controller')) {return;}if (!$redirectTo =$requestAttributes->get('_redirect_to')) {return;}
| ); | ||
| } | ||
| publicfunctiononKernelRequest(GetResponseEvent$event) |
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.
public function onKernelRequest(GetResponseEvent $event): void
| */ | ||
| class ResolveRedirectControllerSubscriberimplements EventSubscriberInterface | ||
| { | ||
| publicstaticfunctiongetSubscribedEvents() |
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.
public static function getSubscribedEvents(): array
fabpot commentedMar 23, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
|
sroze commentedApr 4, 2018
Let's close this one, as this direction is a dead end :) |
…le template and redirect controllers (HeahDude)This PR was merged into the 5.1-dev branch.Discussion----------[FrameworkBundle][Routing] added Configurators to handle template and redirect controllers| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | let's see| Fixed tickets | partially#24640,#25145| License | MIT| Doc PR |symfony/symfony-docs#11120While working onsymfony/symfony-docs#11085, I felt bad about the long notations required for simple [redirects](https://symfony.com/doc/current/routing/redirect_in_config.html) and [templates rendering](https://symfony.com/doc/current/templating/render_without_controller.html) template actions, but I love and use those features since always. Then I gave it a try yesterday night and now I realised I missed#24640 and that#25145 has been closed x).So here we go, here's my WIP. WDYT of this implementation? ping@javiereguiluz?I'm going to open the PR in the docs so we can discuss the DX changes there too, and keep focus on the code here.Cheers!EDIT----This PR now only update PHP-DSL configurators.______________TODO:- [x] gather reviews- ~[x] fix xml schema~- [x] add some tests- ~[ ] handle xsd auto discovery~- [x] rebase on top of#30507- [x] ~add shortcuts for#30514~Commits-------de74794 [FrameworkBundle][Routing] added Configurators to handle template and redirect controllers
Uh oh!
There was an error while loading.Please reload this page.
Following@javiereguiluz's proposal (#24640), this PR allows developers to configure the redirection directly in the routing configuration.