Skip to content

Commit 551660e

Browse files
authored
Merge pull request #5 from aiglesiasn/master
Add ability for External Redirects
2 parents 292af3a + f3eaa1c commit 551660e

File tree

4 files changed

+182
-1
lines changed

4 files changed

+182
-1
lines changed

src/Middleware/InertiaMiddleware.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ private function changeRedirectCode(Request $request, Response $response): Respo
103103
return $response->withStatus(303);
104104
}
105105

106+
// For External redirects
107+
// https://inertiajs.com/redirects#external-redirects
108+
if (
109+
409 === $response->getStatusCode()
110+
&& $response->hasHeader('X-Inertia-Location')
111+
) {
112+
return $response->withoutHeader('X-Inertia');
113+
}
114+
106115
return $response;
107116
}
108117
}

src/Service/Inertia.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,30 @@ public static function lazy(callable $callable): LazyProp
9595
{
9696
return new LazyProp($callable);
9797
}
98+
99+
/**
100+
* @param string|ResponseInterface $destination
101+
* @param int $status
102+
* @return ResponseInterface
103+
*/
104+
public function location($destination, int $status = 302): ResponseInterface
105+
{
106+
$response = $this->createResponse('', 'text/html; charset=UTF-8');
107+
108+
// We check if InertiaMiddleware has set up the 'X-Inertia-Location' header, so we handle the response accordingly
109+
if ($this->request->hasHeader('X-Inertia')) {
110+
$response = $response->withStatus(409);
111+
return $response->withHeader(
112+
'X-Inertia-Location',
113+
$destination instanceof ResponseInterface ? $destination->getHeaderLine('Location') : $destination
114+
);
115+
}
116+
117+
if ($destination instanceof ResponseInterface) {
118+
return $destination;
119+
}
120+
121+
$response = $response->withStatus($status);
122+
return $response->withHeader('Location', $destination);
123+
}
98124
}

test/Middleware/InertiaMiddlewareTest.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,35 @@ public function testItChangesResponseCodeTo303WhenRedirectHappensForPutPatchDele
131131

132132
$this->assertSame($response->reveal(), $middleware->process($request->reveal(), $handler->reveal()));
133133
}
134-
}
134+
135+
public function testItRemovesInertiaHeaderForExternalRedirects()
136+
{
137+
$factory = $this->prophesize(InertiaFactoryInterface::class);
138+
$inertia = $this->prophesize(InertiaInterface::class);
139+
$inertia->getVersion()->willReturn('12345');
140+
141+
$request = $this->prophesize(ServerRequestInterface::class);
142+
$request->withAttribute(InertiaMiddleware::INERTIA_ATTRIBUTE, $inertia->reveal())->willReturn($request);
143+
$request->hasHeader('X-Inertia')->willReturn(true);
144+
$request->getHeader('X-Inertia-Version')->willReturn('12345');
145+
$request->getMethod()->willReturn('POST');
146+
147+
$factory->fromRequest($request)->willReturn($inertia);
148+
149+
$response = $this->prophesize(ResponseInterface::class);
150+
151+
$response->withAddedHeader('Vary', 'Accept')->willReturn($response);
152+
$response->withAddedHeader('X-Inertia', 'true')->willReturn($response);
153+
$response->hasHeader('X-Inertia-Location')->willReturn(true);
154+
$response->getStatusCode()->willReturn(409);
155+
$response->withoutHeader('X-Inertia')->shouldBeCalled();
156+
$response->withoutHeader('X-Inertia')->willReturn($response);
157+
158+
$handler = $this->prophesize(RequestHandlerInterface::class);
159+
$handler->handle(Argument::that([$request, 'reveal']))->willReturn($response);
160+
161+
$middleware = new InertiaMiddleware($factory->reveal());
162+
163+
$this->assertSame($response->reveal(), $middleware->process($request->reveal(), $handler->reveal()));
164+
}
165+
}

test/Service/InertiaTest.php

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,4 +292,119 @@ public function testRenderReturnResponseWithLazyProps()
292292
$this->assertSame($validJson, $jsonResponse);
293293
}
294294

295+
public function testLocationReturnResponseWithLocationAsStringWithNotExistingInertiaHeader()
296+
{
297+
$request = $this->prophesize(ServerRequestInterface::class);
298+
$htmlResponse = null;
299+
300+
$response = $this->prophesize(ResponseInterface::class);
301+
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
302+
$responseFactory->createResponse()->willReturn($response);
303+
304+
$stream = $this->prophesize(StreamInterface::class);
305+
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
306+
$streamFactory->createStream(Argument::type('string'))->will(function () use ($stream){
307+
return $stream;
308+
});
309+
310+
$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);
311+
312+
$response->withBody($stream->reveal())->willReturn($response);
313+
$response->withHeader('X-Inertia', true)->willReturn($response);
314+
$response->withHeader('Content-Type', 'text/html; charset=UTF-8')->willReturn($response);
315+
$response->withStatus(302)->willReturn($response);
316+
$response->withHeader('Location', 'new-location')->willReturn($response);
317+
318+
$inertia = new Inertia(
319+
$request->reveal(),
320+
$responseFactory->reveal(),
321+
$streamFactory->reveal(),
322+
$rootViewProvider->reveal()
323+
);
324+
325+
326+
$returnedResponse = $inertia->location('new-location');
327+
328+
$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
329+
$this->assertNotSame('', $htmlResponse);
330+
}
331+
332+
public function testLocationReturnResponseWithLocationAsStringWithExistingInertiaHeader()
333+
{
334+
$request = $this->prophesize(ServerRequestInterface::class);
335+
$request->hasHeader('X-Inertia')->willReturn(true);
336+
$htmlResponse = null;
337+
338+
$response = $this->prophesize(ResponseInterface::class);
339+
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
340+
$responseFactory->createResponse()->willReturn($response);
341+
342+
$stream = $this->prophesize(StreamInterface::class);
343+
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
344+
$streamFactory->createStream(Argument::type('string'))->will(function () use ($stream){
345+
return $stream;
346+
});
347+
348+
$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);
349+
350+
$response->withBody($stream->reveal())->willReturn($response);
351+
$response->withHeader('X-Inertia', true)->willReturn($response);
352+
$response->withHeader('Content-Type', 'text/html; charset=UTF-8')->willReturn($response);
353+
$response->withStatus(409)->willReturn($response);
354+
$response->withHeader('X-Inertia-Location', 'new-location')->willReturn($response);
355+
356+
$inertia = new Inertia(
357+
$request->reveal(),
358+
$responseFactory->reveal(),
359+
$streamFactory->reveal(),
360+
$rootViewProvider->reveal()
361+
);
362+
363+
$returnedResponse = $inertia->location('new-location');
364+
365+
$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
366+
$this->assertNotSame('', $htmlResponse);
367+
}
368+
369+
public function testLocationReturnResponseWithLocationAsResponseInterfaceWithExistingInertiaHeader()
370+
{
371+
$request = $this->prophesize(ServerRequestInterface::class);
372+
$request->hasHeader('X-Inertia')->willReturn(true);
373+
$htmlResponse = null;
374+
375+
$response = $this->prophesize(ResponseInterface::class);
376+
$responseFactory = $this->prophesize(ResponseFactoryInterface::class);
377+
$responseFactory->createResponse()->willReturn($response);
378+
379+
$stream = $this->prophesize(StreamInterface::class);
380+
$streamFactory = $this->prophesize(StreamFactoryInterface::class);
381+
$streamFactory->createStream(Argument::type('string'))->will(function () use ($stream){
382+
return $stream;
383+
});
384+
385+
$rootViewProvider = $this->prophesize(RootViewProviderInterface::class);
386+
387+
$response->withBody($stream->reveal())->willReturn($response);
388+
$response->withHeader('X-Inertia', true)->willReturn($response);
389+
$response->withHeader('Content-Type', 'text/html; charset=UTF-8')->willReturn($response);
390+
391+
$locationResponse = $this->prophesize(ResponseInterface::class);
392+
$locationResponse->getHeaderLine('Location')->willReturn('new-location');
393+
394+
$response->withStatus(409)->willReturn($response);
395+
$response->withHeader('X-Inertia-Location', $locationResponse instanceof ResponseInterface ? $locationResponse->getHeaderLine('Location') : $locationResponse)->willReturn($response);
396+
397+
$inertia = new Inertia(
398+
$request->reveal(),
399+
$responseFactory->reveal(),
400+
$streamFactory->reveal(),
401+
$rootViewProvider->reveal()
402+
);
403+
404+
$returnedResponse = $inertia->location($locationResponse);
405+
406+
$this->assertInstanceOf(ResponseInterface::class, $returnedResponse);
407+
$this->assertNotSame('', $htmlResponse);
408+
}
409+
295410
}

0 commit comments

Comments
 (0)