使用GuzzleHttp实现URL重定向时响应头为空、状态码异常的问题
问题:GuzzleHttp重定向逻辑测试失败,状态码始终返回200
我正尝试使用GuzzleHttp实现一个简单的重定向功能,并通过PHPUnit测试代码。预期逻辑为:若请求URL末尾带有"/",则响应应重定向至去掉末尾"/"的同地址。但运行测试时两个断言均失败,通过var_dump确认响应状态码为200且响应头为空。这段代码几个月前能正常运行,期间仅执行过composer install,不确定是否因依赖更新导致问题。
现有代码
App.php
<?php namespace Framework; use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class App { public function run(ServerRequestInterface $request): ResponseInterface { $uri= $request->getUri()->getPath(); if (!empty($uri) && $uri[-1] === "/") { $response= new Response(); $response= $response->withStatus(301); $response= $response->withHeader('Location', substr($uri, 0, -1)); } $response= new Response(); $response->getBody()->write('Hello.'); return $response; } }
AppTest.php
<?php namespace Tests\Framework; use Framework\App; use GuzzleHttp\Psr7\ServerRequest; use PHPUnit\Framework\TestCase; class AppTest extends TestCase { public function testRedirectTrailingSlash() { $app= new App(); $request= new ServerRequest('GET', '/some-slug/'); $response= $app->run($request); $this->assertContains('/some-slug', $response->getHeader('Location')); $this->assertEquals('301', $response->getStatusCode()); } }
问题分析
核心问题是变量覆盖:当匹配到末尾带/的URL时,你确实创建了301重定向的response实例,但之后又重新初始化了一个全新的Response对象,直接覆盖了之前的重定向响应。最终返回的永远是状态码200、内容为Hello.的默认响应,和依赖更新无关,是代码逻辑的疏漏。
修复方案
方案1:提前返回重定向响应
直接在匹配到重定向条件时返回响应,避免后续代码覆盖:
<?php namespace Framework; use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class App { public function run(ServerRequestInterface $request): ResponseInterface { $uri = $request->getUri()->getPath(); if (!empty($uri) && $uri[-1] === "/") { return new Response(301, ['Location' => substr($uri, 0, -1)]); } $response = new Response(); $response->getBody()->write('Hello.'); return $response; } }
方案2:先初始化默认响应,按需替换
先创建默认响应,当需要重定向时再替换为对应实例:
<?php namespace Framework; use GuzzleHttp\Psr7\Response; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class App { public function run(ServerRequestInterface $request): ResponseInterface { $uri = $request->getUri()->getPath(); // 先初始化默认响应 $response = new Response(); $response->getBody()->write('Hello.'); if (!empty($uri) && $uri[-1] === "/") { // 替换为重定向响应 $response = new Response(301, ['Location' => substr($uri, 0, -1)]); } return $response; } }
测试验证
修复后重新运行PHPUnit测试,两个断言都会通过:状态码返回301,Location头包含去掉末尾/的地址。
内容的提问来源于stack exchange,提问作者mqbaka mqbaka
相关产品推荐
相关产品推荐

