Skip to content

Commit

Permalink
Merge pull request #5 from aiglesiasn/master
Browse files Browse the repository at this point in the history
Add ability for External Redirects
  • Loading branch information
cherifGsoul authored Jul 25, 2024
2 parents 292af3a + f3eaa1c commit 551660e
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/Middleware/InertiaMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ private function changeRedirectCode(Request $request, Response $response): Respo
return $response->withStatus(303);
}

// For External redirects
// https://inertiajs.com/redirects#external-redirects
if (
409 === $response->getStatusCode()
&& $response->hasHeader('X-Inertia-Location')
) {
return $response->withoutHeader('X-Inertia');
}

return $response;
}
}
26 changes: 26 additions & 0 deletions src/Service/Inertia.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,30 @@ public static function lazy(callable $callable): LazyProp
{
return new LazyProp($callable);
}

/**
* @param string|ResponseInterface $destination
* @param int $status
* @return ResponseInterface
*/
public function location($destination, int $status = 302): ResponseInterface
{
$response = $this->createResponse('', 'text/html; charset=UTF-8');

// We check if InertiaMiddleware has set up the 'X-Inertia-Location' header, so we handle the response accordingly
if ($this->request->hasHeader('X-Inertia')) {
$response = $response->withStatus(409);
return $response->withHeader(
'X-Inertia-Location',
$destination instanceof ResponseInterface ? $destination->getHeaderLine('Location') : $destination
);
}

if ($destination instanceof ResponseInterface) {
return $destination;
}

$response = $response->withStatus($status);
return $response->withHeader('Location', $destination);
}
}
33 changes: 32 additions & 1 deletion test/Middleware/InertiaMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,35 @@ public function testItChangesResponseCodeTo303WhenRedirectHappensForPutPatchDele

$this->assertSame($response->reveal(), $middleware->process($request->reveal(), $handler->reveal()));
}
}

public function testItRemovesInertiaHeaderForExternalRedirects()
{
$factory = $this->prophesize(InertiaFactoryInterface::class);
$inertia = $this->prophesize(InertiaInterface::class);
$inertia->getVersion()->willReturn('12345');

$request = $this->prophesize(ServerRequestInterface::class);
$request->withAttribute(InertiaMiddleware::INERTIA_ATTRIBUTE, $inertia->reveal())->willReturn($request);
$request->hasHeader('X-Inertia')->willReturn(true);
$request->getHeader('X-Inertia-Version')->willReturn('12345');
$request->getMethod()->willReturn('POST');

$factory->fromRequest($request)->willReturn($inertia);

$response = $this->prophesize(ResponseInterface::class);

$response->withAddedHeader('Vary', 'Accept')->willReturn($response);
$response->withAddedHeader('X-Inertia', 'true')->willReturn($response);
$response->hasHeader('X-Inertia-Location')->willReturn(true);
$response->getStatusCode()->willReturn(409);
$response->withoutHeader('X-Inertia')->shouldBeCalled();
$response->withoutHeader('X-Inertia')->willReturn($response);

$handler = $this->prophesize(RequestHandlerInterface::class);
$handler->handle(Argument::that([$request, 'reveal']))->willReturn($response);

$middleware = new InertiaMiddleware($factory->reveal());

$this->assertSame($response->reveal(), $middleware->process($request->reveal(), $handler->reveal()));
}
}
115 changes: 115 additions & 0 deletions test/Service/InertiaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,119 @@ public function testRenderReturnResponseWithLazyProps()
$this->assertSame($validJson, $jsonResponse);
}

public function testLocationReturnResponseWithLocationAsStringWithNotExistingInertiaHeader()
{
$request = $this->prophesize(ServerRequestInterface::class);
$htmlResponse = null;

$response = $this->prophesize(ResponseInterface::class);
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
$responseFactory->createResponse()->willReturn($response);

$stream = $this->prophesize(StreamInterface::class);
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
$streamFactory->createStream(Argument::type('string'))->will(function () use ($stream){
return $stream;
});

$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);

$response->withBody($stream->reveal())->willReturn($response);
$response->withHeader('X-Inertia', true)->willReturn($response);
$response->withHeader('Content-Type', 'text/html; charset=UTF-8')->willReturn($response);
$response->withStatus(302)->willReturn($response);
$response->withHeader('Location', 'new-location')->willReturn($response);

$inertia = new Inertia(
$request->reveal(),
$responseFactory->reveal(),
$streamFactory->reveal(),
$rootViewProvider->reveal()
);


$returnedResponse = $inertia->location('new-location');

$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
$this->assertNotSame('', $htmlResponse);
}

public function testLocationReturnResponseWithLocationAsStringWithExistingInertiaHeader()
{
$request = $this->prophesize(ServerRequestInterface::class);
$request->hasHeader('X-Inertia')->willReturn(true);
$htmlResponse = null;

$response = $this->prophesize(ResponseInterface::class);
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
$responseFactory->createResponse()->willReturn($response);

$stream = $this->prophesize(StreamInterface::class);
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
$streamFactory->createStream(Argument::type('string'))->will(function () use ($stream){
return $stream;
});

$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);

$response->withBody($stream->reveal())->willReturn($response);
$response->withHeader('X-Inertia', true)->willReturn($response);
$response->withHeader('Content-Type', 'text/html; charset=UTF-8')->willReturn($response);
$response->withStatus(409)->willReturn($response);
$response->withHeader('X-Inertia-Location', 'new-location')->willReturn($response);

$inertia = new Inertia(
$request->reveal(),
$responseFactory->reveal(),
$streamFactory->reveal(),
$rootViewProvider->reveal()
);

$returnedResponse = $inertia->location('new-location');

$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
$this->assertNotSame('', $htmlResponse);
}

public function testLocationReturnResponseWithLocationAsResponseInterfaceWithExistingInertiaHeader()
{
$request = $this->prophesize(ServerRequestInterface::class);
$request->hasHeader('X-Inertia')->willReturn(true);
$htmlResponse = null;

$response = $this->prophesize(ResponseInterface::class);
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
$responseFactory->createResponse()->willReturn($response);

$stream = $this->prophesize(StreamInterface::class);
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
$streamFactory->createStream(Argument::type('string'))->will(function () use ($stream){
return $stream;
});

$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);

$response->withBody($stream->reveal())->willReturn($response);
$response->withHeader('X-Inertia', true)->willReturn($response);
$response->withHeader('Content-Type', 'text/html; charset=UTF-8')->willReturn($response);

$locationResponse = $this->prophesize(ResponseInterface::class);
$locationResponse->getHeaderLine('Location')->willReturn('new-location');

$response->withStatus(409)->willReturn($response);
$response->withHeader('X-Inertia-Location', $locationResponse instanceof ResponseInterface ? $locationResponse->getHeaderLine('Location') : $locationResponse)->willReturn($response);

$inertia = new Inertia(
$request->reveal(),
$responseFactory->reveal(),
$streamFactory->reveal(),
$rootViewProvider->reveal()
);

$returnedResponse = $inertia->location($locationResponse);

$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
$this->assertNotSame('', $htmlResponse);
}

}

0 comments on commit 551660e

Please sign in to comment.