You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:05:07