skip to Main Content

I am trying to get a simple redirection to work with GuzzleHttp and am using phpunit to test my code. The expected behavior is that if the requested URL ends with a "/" then the response should be a redirection to the same URL stripped with the trailing "/".

This is how my App.php looks like :

<?php
namespace Framework;
use GuzzleHttpPsr7Response;
use PsrHttpMessageResponseInterface;
use PsrHttpMessageServerRequestInterface;

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;
    }
}

And I run the test in AppTest.php like this :

<?php
namespace TestsFramework;

use FrameworkApp;
use GuzzleHttpPsr7ServerRequest;
use PHPUnitFrameworkTestCase;

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());
    }
}

When I run this test, both assertions fail and it’s due to the fact that the response’s status code is 200 and the headers list is empty and I confirmed that by doing a var_dump().

The weirdest thing is that, I wrote this code a few months ago and it worked and as far as I remember, the only thing I did between then and now was a composer install so I don’t know if it’s due to a recent updates of the dependencies.

Can someone help me with this?

2

Answers


  1. The issue seems to stem from the fact that you are always creating a new response object right after setting the redirection headers. This overwrites the previous response that had the redirection.

    To fix this, remove the second instance where you create a new response object after setting the redirection. Try the below code in your App.php:

    <?php
    namespace Framework;
    use GuzzleHttpPsr7Response;
    use PsrHttpMessageResponseInterface;
    use PsrHttpMessageServerRequestInterface;
    
    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));
                return $response; 
            }
    
            $response = new Response();
            $response->getBody()->write('Hello.');
            return $response;
        }
    }
    
    Login or Signup to reply.
  2. You are overriding the response instance from the if statement. Do something like the following to avoid overriding the response instance:

    $response = new Response();
    if (!empty($uri) && $uri[-1] === "/") {
        $response = $response->withStatus(301);
        $response = $response->withHeader('Location', substr($uri, 0, -1));
    } else {
        $response->getBody()->write('Hello.');
    }
    return $response;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search