inertia-laravel
inertia-laravel copied to clipboard
[1.x] Make inertia response more extension friendly
This PR simply aims to make Inertia\Response more friendly to extension/customization by:
This unlocks, for example, customizing how the page.url get's resolved by Inertia.
In a particular case, it was necessary for me to ensure redirections keept the url fragment (/abc#123).
Previously I had to:
- create a custom middleware
- render the Inertia response
- get it's orginal content
- modify it
- finally reset the page with the modified content
- return the response.
Example implementation
<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
final class EnsureCorrectInertiaRedirectionWhenPossible
{
/**
* Handle an incoming request.
* Ensure URL fragments on redirections are set whenever possible.
*
* @param Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse) $next
*/
public function handle(Request $request, Closure $next): Response|RedirectResponse|JsonResponse
{
if (!$request->inertia()) {
return $next($request);
}
$requestedFrom = $request->headers->get('x-requested-from');
if (!$requestedFrom) {
return $next($request);
}
$response = $next($request);
if (!($response instanceof JsonResponse)) {
return $response;
}
$parsedRequestedFrom = parse_url($requestedFrom);
if (!is_array($parsedRequestedFrom)) {
return $response;
}
if (!isset($parsedRequestedFrom['path'])) {
return $response;
}
if (!isset($parsedRequestedFrom['fragment'])) {
return $response;
}
$requestedFromUri = $parsedRequestedFrom['path'] . (
isset($parsedRequestedFrom['query']) ? "?{$parsedRequestedFrom['query']}" : ''
);
$page = $response->getOriginalContent();
if ($requestedFromUri !== $page['url']) {
return $response;
}
$page['url'] = "{$page['url']}#{$parsedRequestedFrom['fragment']}";
$response->setData($page);
return $response;
}
}
Now, a custom Response class overwritting the resolveUrl method could be resolved from the container whenever an Inertia response is returned.
Example implementation
use Illuminate\Http\Request;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
use Inertia\Response as InertiaResponse;
final class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
$this->app->bind(InertiaResponse::class, CustomInertiaResponse::class);
}
}
final class CustomInertiaResponse extends InertiaResponse
{
public function resolveUrl(Request $request, array $props): string
{
$url = '...';
return $url;
}
}
Resolved any conflicts that arose after https://github.com/inertiajs/inertia-laravel/pull/641. This PR is now up to date with the 1.x branch.
Closing this as we're not adding any new features or non-emergency fixes for 1.x. If This is still an issue in 2.x please submit a new PR.