Symfony2路由无法识别http POST?

时间:2015-01-27 15:29:54

标签: php symfony routing

我最近开始使用Symfony Routing组件。

我的路线yaml看起来像这样:

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

然而网址https://my.domain.com/custom"即使它在yaml文件中的自定义之后,它也会被解析为默认路由。请求方法,根据我的jQuery .ajax设置和Chrome控制台, POST:

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

或根据Chrome网络 - >头:

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

如果我更改请求方法以获取,使yaml配置保持不变,它也不起作用,这当然是预期的。如果我更改自定义路由的yaml配置以接受GET而不是POST,并发送GET请求,它会再次正常工作。但是,如果我更改自定义路由的yaml配置以接受GET并发送POST请求,则它会起作用,即自定义规则匹配!在某种意义上,似乎浏览器的POST请求在服务器端被解释为GET。

如果是某种奇怪的Chrome漏洞,我已尝试使用Firefox,结果相同。

然后我尝试打印$ _SERVER [' REQUEST_METHOD']并且它的结果如预期的那样,如果请求是POST则为POST,如果请求是GET则为GET。所以在我看来Symfony的错在哪里,也许我错误配置了一些东西。

这是我的相关PHP代码:

$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, '/'));
....
}
....

我有一种强烈的感觉,我只是在这里做了一些与请求和上下文根本错误的事情,但这就是我如何设法让它们工作,并且到目前为止它已经很好地运行了GET路线至少。在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

抱歉迟到了近两年,但我自己就解决了这个问题。

您必须使用Request对象为RequestContext对象设置种子:

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

说明:

我遇到了同样的问题(当我发现这个悬而未决的问题时感到沮丧),并深入挖掘源代码,找出为什么它声称“GET”作为每个请求的方法。

我的错误是认为UrlMatcher正在使用Request对象(在转储时显示'POST'),但它没有;它使用RequestContext对象。

你可以在symfony / routing / Matcher / UrlMatcher.php的第153行看到这个

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     }

...当我检查RequestContext类时,我发现构造函数默认为GET:

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

但我很高兴也发现了fromRequest方法,它很好地解释了它如何在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     }

干杯!

答案 1 :(得分:0)

我的问题是,当URL以/(斜线)结尾时,我无法匹配路由