inertia-laravel icon indicating copy to clipboard operation
inertia-laravel copied to clipboard

Laravel Inertia apps doesn't support subdomain redirects

Open MooseSaeed opened this issue 2 years ago • 8 comments

I'm working on a Laravel 9, InertiaJS and vue project where a user can submit a new product through products/create route and this sends to ProductController@store which does all what it's supposed to do and then supposedly redirect the user to the newly created product on a subdomain route like this http://username.example.test/my-new-product

The issue I'm having is that I keep getting the below error and the redirect doesn't work:

Access to XMLHttpRequest at 'http://user.example.test/my-first-product' (redirected from 'http://example.test/products/create') from origin 'http://example.test' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The code works as follows:

1- The form:

const form = useForm("createProduct", {
    webshop_id: null,
    title: null,
    price: null,
    type: null,
    currency: null,
    description: null,
    thumbnail: null,
});
const submit = () => {
    form.post(route("products.create"), {
        onSuccess: () => form.reset(),
    });
};

2- Products create router:


Route::middleware([
    'auth:sanctum',
    config('jetstream.auth_session'),
    'verified',
])->group(function () {

    Route::post('products/create', [ProductController::class, 'store'])->name('products.create');

});

3- The controller - Storing the new product with user details and redirecting (which doesn't work) to show the product

public function store(StoreProductRequest $request)
    {
		
		// Code
		
        return redirect()->route('products.show', [$user, $product]);
    }

4- The show route and controller@show

Route::domain('{user:username}.' . env('APP_URL'))->group(function () {
    Route::get('{product:slug}', [ProductController::class, 'show'])->name('products.show');
});
    public function show(User $user, Product $product)
    {

        return Inertia::render('Products/Show', [
            'user' => $user,
            'product' => $product,
            'thumbnails' => $product->productimages
        ]);
    }

I saw @reinink explain in this Issue that we can use now Inertia::location

The only way I could get this to work is returning this is the ProductController@store:

 return Inertia::location('http://' . $user->username . '.example.test/' . $validated['slug']);

But It causes a full page refresh which defeats the whole concept of having a single page application and I will have to remember changing 'http' to 'https' and domain to the real domain when I'm going to put the app in production. I was hoping that I was doing something wrong but after hours of searching for a solution I began to think that Laravel Inertia apps doesn't support subdomain redirects

MooseSaeed avatar Jul 12 '22 18:07 MooseSaeed

Solved the issue by making the below changes to cors.php

    'paths' => ['api/*', '*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => ['x-inertia'],

    'max_age' => 0,

    'supports_credentials' => false,

No cors issues now but I'm having a different issue where the desired page rendered by Inertia on the incorrect route. Raised the Issue for Laravel Framework

MooseSaeed avatar Jul 14 '22 09:07 MooseSaeed

This is driving me crazy! Subdomains isn't working even if I hard set the redirect like this redirect()->to('http://username.example.test/productSlug') it gives me in the browser url example.test/productSlug only. I even used Inertia to redirect from the frontend to a url and did the same. The only thing that works is using Inertia::location() but this causes a full page refresh.

MooseSaeed avatar Jul 14 '22 17:07 MooseSaeed

Same behavior occurs with Inertia's Link.

If you are on a subdomain route like {subdomain}.example.test/profile and you have a link like this <Link href="http://example.test">Click</Link> It will redirect you to {subdomain}.example.test. The only workaround is having a normal HTML anchor tag like this <a href="http://example.test">Click</a>

MooseSaeed avatar Jul 15 '22 16:07 MooseSaeed

Javascript's pushState cannot change the domain

laserhybiz avatar Jul 21 '22 07:07 laserhybiz

@MooseSaeed Hey I honestly don't think this is possible to make Inertia requests across subdomains — sorry!

reinink avatar Jul 21 '22 23:07 reinink

@reinink I agree! After days of research I'm sure now that it is impossible to route redirect to a subdomain route from root domain without page refresh. Any change to the host will require the page to reload which is out of Laravel and JetStream scope and out of InertiaJS hands. As far as I understand that this is for security purposes.

Sorry for wasting your time and thanks a million for your efforts

MooseSaeed avatar Jul 21 '22 23:07 MooseSaeed

Yes inertia works with browser history, but it seems inertia is missing a check, so that redirects to a different domain are handled correctly and reload the page

Tofandel avatar Aug 22 '22 20:08 Tofandel

@MooseSaeed As a workaround you can add to your HandleInertiaRequests middleware

public function version(Request $request): string
{
    return md5($request->host) . parent::version($request);
}

And if you have CORS working, the request will be followed and inertia will reload the page but you'll have one more request than what is strictly necessary

Cross domains redirects are not very frequent so you'd be better doing it explicitely without inertia using a window.location and it would prevent all the CORS issues that goes with it

If you need the domain to be dynamic, instead of a redirect then send the url as an inertia prop and use that in the success handler for your window.location

Tofandel avatar Aug 22 '22 20:08 Tofandel

@reinink sorry to bother, but question, that is not covered in docs/thread and related to current issue.

Is using <a> tag to get to the subdomain route a viable/good practice for Inertia? E.g. little js component, that checks, if subdomain changes and renders <InertiaLink> or <a>.

It's the same app, same cookie name, subdomains due to SEO-stuff.

Cause I don't see any issues with that, but would like not to face any long-term.

riabiy-denis avatar Jan 04 '23 01:01 riabiy-denis

Just found this issue as i was having issues with the same thing, is there any chance sub domain redirects can be added to inertia? Would be a great help!

NinjaJake86 avatar Jan 31 '23 10:01 NinjaJake86

Hey there,

We're closing this issue because it's inactive, already solved, old or not relevant anymore. Feel to open up a new issue if you're still experiencing this problem.

jessarcher avatar Sep 08 '23 01:09 jessarcher

Just came across this issue and, like @riabiy-denis, I solved it via a small component that either outputs an a tag or an Inertia Link component by comparing the current host with the host of the link. Works really well and was easy to implement!

boris-glumpler avatar Feb 29 '24 07:02 boris-glumpler