Silex 中的内部转发而不向浏览器发送 301/302

Internal Forward in Silex Without a Sending a 301/302 to the Browser

我正在使用 Silex 的内部转发将 public URL 映射到内部 URL,即 my.domain.com/something 实际上使用

服务于 my.domain.com/something_else
$subRequest = Request::create(
    $redirect,
    $method, 
    [], // params
    $request->cookies->all(), 
    $request->files->all(), 
    $request->server->all()
);

if ($request->getSession())
{
    $subRequest->setSession($request->getSession());
}

return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);

但是,在 Chrome 的检查工具中,这显示为生成页面的 301,然后该页面会提供结果。这是 "by design" 因为它代表了一个有趣的安全问题吗?有没有办法绕过这个限制?

虽然我不能 post 为 something_else 路由控制器编写代码,但要点是

// controller provider
$controller_factory->match('/something_else/{param}', function(...) {
    include 'path/to/some/file';
});

// some/file - prepares a file to be downloaded
...
return new BinaryFileResponse();

该文件中没有 RedirectResponses

编辑 我在上面的例子中过度简化了。实际上,/something 是一个随机字符串(即 /abcdefghijklmnopqrstuvwxyz 映射到许多内部路由之一 (-> /something_else, -> /something_else_2, -> etc)。

不,我不这么认为。我相信这是你的 something_else 控制器不喜欢子请求和 returns 重定向响应,你的 something 控制器无条件地 returns 到浏览器。

可以是任何东西。 Silex 是一个微框架,这意味着事情可以用数百种不同的方式实现,如果不看实际代码就几乎不可能提出任何建议。这是它带来的灵活性的另一面。它可能是 RedirectableUrlMatcher,或者您的控制器、路由器、包含的文件、错误处理程序或中间件中的任何内容,这会导致重定向响应。

考虑这个更加简化的单脚本应用程序示例:

<?php
// web/index.php
require_once __DIR__.'/../vendor/autoload.php';

$app = new Silex\Application();

$app->get(
    '/the-only-functional',
    function() use ($app) {
        return new \Symfony\Component\HttpFoundation\Response(
            $app['request']->get('q')
        );
    }
);

$app->get(
    '/{whatever}',
    function($whatever) use ($app) {
        $subRequest = \Symfony\Component\HttpFoundation\Request::create(
            '/the-only-functional',
            'GET',
            ['q'=>$whatever]
        );
        $response = $app->handle($subRequest);

        if (200 != $response->getStatusCode()) {
            throw new \Exception(
                "Aha, that's where the problem lies"
                . $response->getStatusCode() . ":"
                . $response->getContent()
            );
        }

        return $response;
    }
)->value('whatever', 'nothing');

$app->run();

http 服务器 运行 为:

php -S localhost:8081 -d "date.timezone=UTC" -t web  web/index.php

您可以尝试不同的排列方式:

curl -v http://localhost:8081/
curl -v http://localhost:8081/blah-blah
curl -v http://localhost:8081/the-only-functional?q=direct
curl -v http://localhost:8081/?q=this+example+does+not+forward+query+string

而你总是 得到 200 个响应。

遗憾的是,如果不共享代码,您只能自己调试您的应用程序。唯一明智的建议是在返回之前分析子响应,并且可能会记录回溯以定位问题。

你可以看看子请求: http://silex.sensiolabs.org/doc/cookbook/sub_requests.html

use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;

$app->get('/something', function (Application $app, Request $request) {
    $subRequest = Request::create('/something_else', ...);
    $response = $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);

    return $response;
}); 

这个问题的解决方案原来是单个字符修复:/

给定以下定义:

$controller_factory->match('/something_else/{param}/', function($app, $param) { ... });
$controller_factory->match('/something', function($app) {
    // do the redirect to /something_else/{param}
    $redirect = '/something_else/hello';
    ...
});

你能看出来吗?事实证明,Symfony 智能地转发了没有尾部斜线的路由,将带有尾部斜线的路由与带有斜线的路由相匹配。我的问题是我 "correctly" 从我的随机字符串中解析 /something_else/something (如果你错过了这个,请参阅我的编辑),但它在应该解析为 [=13= 的意义上是不正确的](注意结尾的斜线)