【问题标题】:Symfony2 functional test client force server param SERVER_NAMESymfony2 功能测试客户端强制服务器参数 SERVER_NAME
【发布时间】:2023-03-14 10:48:01
【问题描述】:

我设计了一个多路应用程序。有多站点管理员(即http://root.com/admin)以及所有站点访问权限(即http://site1.comhttp://site2.com..。)。

为了处理路由(多站点管理员或子站点),我在 vhost 配置上设置了 UseCanonicalName:

ServerName root.com
ServerAlias media.site1.com site1.com media.site2.com, site2.com ...

UseCanonicalName On

这样做,我确信 $request->server->get('SERVER_NAME') 在给定的情况下总是会返回 root.com,我在路由过程中使用它来区分根域(对于管理员目的)、子网站和 404 内容。

它在现实生活中运行良好,但在测试方面,UseCanonicalName 似乎不会强制使用在 vhost 中定义的 ServerName 的 SERVER_NAME。

从常规 Chrome 客户端转储:

array(34) {
  'HTTP_HOST' => 
   string(9) string 'site1.com'
   ...
  'HTTP_USER_AGENT' => 
   string(105) 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36'
  'SERVER_NAME' => 
   string(8) 'root.com'
   ...
}

从测试客户端转储

array(16) {
  'SERVER_NAME' =>
  string(9) "site1.com"
  'HTTP_HOST' =>
  string(9) "site1.com"
  'HTTP_USER_AGENT' =>
  string(19) "Symfony2 BrowserKit"
  ...
}

我试图在测试客户端上强制使用 SERVER_NAME:

$crawler = $this->client->request('GET', $route, [], [], ['SERVER_NAME' => 'root.com']);

但这并没有改变任何事情,我仍然拥有等于 HTTP_HOST 的 SERVER_NAME 值,这在测试子站点 FO 或 BO 时会搞砸一切(当 SERVER_NAME 和 HTTP_HOST 之间的差异很重要时)。

所以,

  • 为什么 Symfony2 BrowserKit 对 UseCanonicalName 指令不敏感?
  • 如何使用客户端类参数强制它?

【问题讨论】:

    标签: php apache symfony testing client


    【解决方案1】:

    严格来说,我终于设法解决了上述问题:我重载了客户端类(Symfony\Bundle\FrameworkBundle\Client),特别是在 filterRequest 调用之后的请求方法:

    public function request($method, $uri, array $parameters = array(), array $files = array(), array $server = array(), $content = null, $changeHistory = true)
        {
            if ($this->isMainRequest) {
                $this->redirectCount = 0;
            } else {
                ++$this->redirectCount;
            }
    
            $uri = $this->getAbsoluteUri($uri);
    
            $server = array_merge($this->server, $server);
    
            if (isset($server['HTTPS'])) {
                $uri = preg_replace('{^'.parse_url($uri, PHP_URL_SCHEME).'}', $server['HTTPS'] ? 'https' : 'http', $uri);
            }
    
            if (!$this->history->isEmpty()) {
                $server['HTTP_REFERER'] = $this->history->current()->getUri();
            }
    
            if (empty($server['HTTP_HOST'])) {
                $server['HTTP_HOST'] = $this->extractHost($uri);
            }
    
            $server['HTTPS'] = 'https' == parse_url($uri, PHP_URL_SCHEME);
    
    
            $this->internalRequest = new Request($uri, $method, $parameters, $files, $this->cookieJar->allValues($uri), $server, $content);
    
            $this->request = $this->filterRequest($this->internalRequest);
    
            // MY ADDITION
            //
            $this->request->server->replace(array_merge($this->request->server->all(), $server));
    
            // /MY ADDITION
            //
    
            if (true === $changeHistory) {
                $this->history->add($this->internalRequest);
            }
    
            if ($this->insulated) {
                $this->response = $this->doRequestInProcess($this->request);
            } else {
                $this->response = $this->doRequest($this->request);
            }
    
            $this->internalResponse = $this->filterResponse($this->response);
    
            $this->cookieJar->updateFromResponse($this->internalResponse, $uri);
    
            $status = $this->internalResponse->getStatus();
    
            if ($status >= 300 && $status < 400) {
                $this->redirect = $this->internalResponse->getHeader('Location');
            } else {
                $this->redirect = null;
            }
    
            if ($this->followRedirects && $this->redirect) {
                return $this->crawler = $this->followRedirect();
            }
    
            return $this->crawler = $this->createCrawlerFromContent($this->internalRequest->getUri(), $this->internalResponse->getContent(), $this->internalResponse->getHeader('Content-Type'));
        }
    

    这样做,我强制与传递给请求方法的 $server 参数和 $this->request->server 中包含的真实服务器参数进行合并。

    这样的合并已经在上面完成了 ($server = array_merge($this->server, $server);) 但由于某种原因我无法解释,filterRequest 调用有点“重置”请求,一扫我的自定义服务器参数。

    我没有清楚地看到这对子请求的深刻影响。 AFAIK,它只会在源自第一个请求或子请求的每个请求或子请求中合并我的自定义服务器参数。

    另一方面,有谁知道为什么 filterRequest(它只是一个绕过器)会重置所有服务器变量?

    PS : 当我在功能测试会话 vars 上遇到另一个(但相关的问题)时,我问了another question

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-24
      • 2013-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多