laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.54k stars 11.02k forks source link

Ignored Subdomains on Redirection #43184

Closed MooseSaeed closed 2 years ago

MooseSaeed commented 2 years ago

Description:

I'm using Laravel with JetStream, InertiaJS --SSR and VueJS. I'm working with this form that submits a store request to products/create in order to create a new product, then I'm trying to return and redirect to view the product with subdomain as the username of the product owner like this {username}.example.test/{productSlug} but I was getting this error:

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.

I solved that by making the below changes in cors.php:

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

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

Now I'm being redirected to a working page with the intended product but incorrect url example.test/{productSlug} without the username as a subdomain. If I refresh the page of course I get a 404 because this is an incorrect route and if I manually visit the correct url {username}.example.test/{productSlug} I find it working. So mainly I'm redirected to a url that doesn't include the subdomain.

Checked the network tap on firefox and the request is passed correctly with subdomain and the host as well contains the correct url with subdomain.

Steps To Reproduce:

1- Start new laravel project and install Jetstream with InertiaJS SSR and Vue. 2- Make Product model and migration. 3- Create a form where a User can create a new Product and send the request to store the product and redirect to show the product.

public function store(StoreProductRequest $request)
    {

        // Code

        return redirect()->route('products.show', [$username, $slug]);
    }

4- Make a new route with subdomain to view the product:

Route::domain('{username}.' . env('SESSION_DOMAIN'))->group(function () {

    Route::get('{slug}', [ProductController::class, 'show'])->name('products.show');

});

5- Return the models in the show method:

    public function show($username, $slug)
    {

        $user = User::where('username', $username)->first();
        $product = Product::where('slug', $slug)->first();

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

6- You will get CORS errors, update cors.php as below:

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

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

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

    'max_age' => 0,

    'supports_credentials' => false,

7- Submit the form and the controller store action finishes what It's supposed to do and then redirects to a working page of the product without cors errors, the only problem is that it shows in the browser as example.test/productSlug while it's supposed to be username.example.test/productSlug. When refresh the page It gets 404 page not found error which make sense because that's an incorrect route, When manually visiting the desired route you can find it working as expected.

driesvints commented 2 years ago

Hey @MooseSaeed. I see you solved it here: https://github.com/inertiajs/inertia-laravel/issues/431. Glad you figured that out 👍

MooseSaeed commented 2 years ago

Hey @MooseSaeed. I see you solved it here: inertiajs/inertia-laravel#431. Glad you figured that out 👍

Hi @driesvints , Please reopen the issue as it's not yet solved

I solved cors errors issue upon redirect but the above mentioned issue is not solved yet unfortunately.

MooseSaeed commented 2 years ago

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.

driesvints commented 2 years ago

Heya, thanks for reporting.

We'll need more info and/or code to debug this further. Can you please create a repository with the command below, commit the code that reproduces the issue as separate commits on the main/master branch and share the repository here? Please make sure that you have the latest version of the Laravel installer in order to run this command. Please also make sure you have both Git & the GitHub CLI tool properly set up.

laravel new bug-report --github="--public"

Please do not amend and create a separate commit with your custom changes. After you've posted the repository, we'll try to reproduce the issue.

Thanks!

MooseSaeed commented 2 years ago

Hello @driesvints ,

Please find the requested repo.

Readme has the steps and current behavior gif

Laravel-bug

driesvints commented 2 years ago

@MooseSaeed can you consolidate all your custom changes into one commit please? Without the installation of jetstream.

MooseSaeed commented 2 years ago

@driesvints I hope I haven't messed the repo up :D , I think I merged all custom changes to one commit 'custom changes'. If You need the whole thing all over again, please let me know.

driesvints commented 2 years ago

I'm sorry @MooseSaeed but I'm going to close this one. I believe something is amis with configuration and this isn't a Laravel or Jetstream issue. Please continue to try a support channel and maybe the Inertia issue tracker.

MooseSaeed commented 2 years ago

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