1

I've recently started working with Symfony Routing component.

My routes yaml look like this:

custom:
  path: /custom
  defaults: {controller: custom, action: refresh}
  methods: [POST]
  schemes: [https]
default:
    path: /{controller}/{action}
    defaults: {controller : index, action: index}

However url https://my.domain.com/custom" gets resolved to the default route even if it goes after the custom one in yaml file. Request method, according to my jQuery .ajax settings and Chrome console, is POST:

XHR finished loading: POST "https://my.domain.com/custom".

or according to Chrome network -> headers:

Request URL:https://my.domain.com/custom
Request Method:POST

If I change request method to get, leaving yaml configuration the same, it does not work either, which is of course expected. If I change yaml configuration for custom route to accept GET instead of POST, and send a GET request, it does work, as expected again. But if I change yaml configuration for custom route to accept GET and send a POST request, it works, i.e. custom rule is matched! It seems like browser's POST request is interpreted as GET on the server side, in some sense.

In a case it's some sort of weird Chrome bug, I've tried Firefox, with the same results.

Then I've tried printing $_SERVER['REQUEST_METHOD'] and it's results are as expected, POST if request was POST, GET if request was GET. So it seems to me it's Symfony's fault somewhere, maybe I misconfigured something.

Here's my relevant PHP code:

$args       = isset($_REQUEST['args']) ? $_REQUEST['args'] : '';
$request    = Request::createFromGlobals();
$locator    = new FileLocator(HOME_PATH . 'config');
$loader     = new YamlFileLoader($locator);
$routes     = $loader->load('routes.yml');
$context    = new RequestContext($_SERVER['REQUEST_URI']);
$context->setScheme($request->getScheme());
$context->setHost($_SERVER['SERVER_NAME']);
$matcher    = new UrlMatcher($routes, $context);

try
{
    $match          = $matcher->match('/' . rtrim($args, '/'));
....
}
....

I have a strong feeling I'm just doing something fundamentally wrong with request and context here, but that's how I managed to get them working, and it used to work well so far, with GET routes at least. Thanks in advance for your help!

3
  • Are you using the routing component inside symfony2 standard edition or not? Commented Jan 27, 2015 at 15:58
  • No, I use it separately as a component Commented Jan 28, 2015 at 9:00
  • Ok than I can't help you sry. Commented Jan 28, 2015 at 9:27

2 Answers 2

2

Sorry to be nearly two years late, but I just solved this myself.

You've got to seed the RequestContext object with the Request object:

$request = Request::createFromGlobals();
$context = new RequestContext($_SERVER['REQUEST_URI']);
$context->fromRequest($request);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Explanation:

I was running into the same issue (and frustated when I found this unanswered question), and dug into the source code to figure out why it was claiming "GET" as the method for every request.

My mistake was thinking that the UrlMatcher was using the Request object (which showed 'POST' when dumped), but it doesn't; it uses the RequestContext object.

You can see this on line 153 of symfony/routing/Matcher/UrlMatcher.php

151 if ($requiredMethods = $route->getMethods()) {
152     // HEAD and GET are equivalent as per RFC
153     if ('HEAD' === $method = $this->context->getMethod()) {
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
154         $method = 'GET';
155     }

... and when I examined the RequestContext class, I found that the constructor defaults to GET:

52     public function __construct($baseUrl = '', $method = 'GET', $host = 'loc....

But I was pleased to also discover the fromRequest method, which happily explains how it solves our problem right in the docblock:

64     /**
65      * Updates the RequestContext information based on a HttpFoundation Request.
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
66      *
67      * @param Request $request A Request instance
68      *
69      * @return RequestContext The current instance, implementing a fluent interface
70      */
71     public function fromRequest(Request $request)
72     {
73         $this->setBaseUrl($request->getBaseUrl());
74         $this->setPathInfo($request->getPathInfo());
75         $this->setMethod($request->getMethod());
76         $this->setHost($request->getHost());
77         $this->setScheme($request->getScheme());
78         $this->setHttpPort($request->isSecure() ? $this->httpPort : $request->getPort());
79         $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort);
80         $this->setQueryString($request->server->get('QUERY_STRING', ''));
81
82         return $this;
83     }

Cheers!

Sign up to request clarification or add additional context in comments.

1 Comment

I can imagine how you were constantly debugging this for 2 years... thats the spirit!
0

my problem was that I couldn't match route when URL ended with / (slash)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.