Skip to content

Routing based on the full request object #4020

Closed
@Crell

Description

@Crell

Hi folks. I want to get some feedback on this before I go any further with it.

In Drupal, we do all sorts of unholy things to the incoming path. Most notably, the path is aliased (so that internal code need deal with only a single router item, node/{node}, where the user only ever sees /about-us), and we sometimes stick a prefix onto it to specify the language (/en/about-us and /fr/about-us). So the path that gets used for routing often doesn't look a thing like the path in the original HTTP request, and when code tries to generate a URL to node/5, what actually ends up in the page could be /de/about-us/early-years.

I'm trying to figure out how to do that in the HttpKernel model. My initial thought was to have an early kernel.request listener that created a new request object based off of the original, but with a mutated path to resolve the aliasing and overwriting the Language header with information from the path, if appropriate. (The language can come from the header, the request path, or the current user's settings, just to keep life interesting.)

However, I determined that you cannot change the Request object from a kernel.request listener. I suppose that makes sense. The request object's path also cannot be changed.

I could run a subrequest from the listener, but that seems rather excessive.

Talking about it in #symfony-dev the other night, a few people suggested treating the request as immutable and just throwing the "resolved" path into attributes, then doing all of the routing based off of that. There's certainly something to that, and then we could put the resolved language there, too, along with other such things. However, the request object is never passed to UrlMatcher. The RequestContext object is, which doesn't include attributes.

The only way around that is to make my own UrlMatcher class (which we already are) and our own RouterListener, and then have a fake RequestContext object that we never use because it's required by the UrlMatcherInterface. That feels rather ugly to me. A gist of it is here (including some Drupal cruft; pay it no mind, it will go away eventually):

https://gist.github.com/2418886

Johannes suggested that an option to pass a full request object to the matcher makes sense for Symfony directly, since there's all sorts of useful information there that the request context object lacks.

So before I go any further down this path, is any of the above making sense? Is that a decent approach to take? Would something like this be more useful directly in Symfony rather than in Drupal-specific subclasses? Is there some better option I'm totally missing?

I'd love to get some feedback here before I go down the wrong rabbit hole. :-)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions