livewire / livewire

A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
MIT License
22.43k stars 1.56k forks source link

Getting 404 response on all request on v2.3.11 #2445

Closed tarikhagustia closed 3 years ago

tarikhagustia commented 3 years ago

Description

After upgrading from 2.3.8 to 2.3.11, all livewire component getting 404 response

Context

joshhanley commented 3 years ago

@tarikhagustia is that happening when you go to any endpoint that has a Livewire component, or is it happening on subsequent requests, when you interact with any Livewire components?

Butochnikov commented 3 years ago

@joshhanley same problem. this happens after on subsequent requests.

upd: maybe it will help, the package mcamara/laravel-localization is installed and middleware:

'localize'                => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRoutes::class,
        'localizationRedirect'    => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationRedirectFilter::class,
        'localeSessionRedirect'   => \Mcamara\LaravelLocalization\Middleware\LocaleSessionRedirect::class,
        'localeCookieRedirect'    => \Mcamara\LaravelLocalization\Middleware\LocaleCookieRedirect::class,
        'localeViewPath'          => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class
Butochnikov commented 3 years ago

404 only if prefix is set prefix' => LaravelLocalization::setLocale(),

on 2.3.8 version works fine

usernotnull commented 3 years ago

+1

joshhanley commented 3 years ago

@Butochnikov thanks for the info!

Setup

To replicate this issue, setup a Livewire app with a basic component with a button that triggers a request to the server.

Install mcamara/laravel-localization (I'm sure any package with prefixes will do the same).

Setup mcamara/laravel-localization as per instructions, by registering route middleware in http kernel

Add prefix to route

image

Action

Browse to the route with a specific language specified like /en

Trigger Livewire action and you get the 404.

image

Troubleshooting

So it looks like in HttpConnectionHandler:64 Livewire is trying to do a match of the incoming route against the current listed routes.

So it's trying to match the original route /en with the list of routes, but it can't find it as it's a prefix. The route would actually be /.

Not sure how to match when prefixed are involved.

Hope this helps!

tarikhagustia commented 3 years ago

404 only if prefix is set prefix' => LaravelLocalization::setLocale(),

on 2.3.8 version works fine

yes, i'm working with this library, any trick to running latest livewire with this package?

marispro commented 3 years ago

Also getting this error, and can confirm that it happens even when you use prefix without any kind of packages.

calebporzio commented 3 years ago

Ok I've zeroed in on the problem.

From what I can tell, @marispro, standard prefixes work fine.

It's dynamic prefixes that are iffy.

In this case, when using the localization package, the prefix for the original request route is dynamically set like this: ['prefix' => LaravelLocalization::setLocale()]

This works great for the first request to that prefixed route, but on the subsequent request when Livewire tries to locate the orignal URL, let's say: /es/some-route, it can't find it because the localization wasn't carried over to the /livewire/message request for some reason.

Livewire already supports localization carry over so this is odd to me, however, I fixed this by also including the locale in the /livewire/message endpoint now like so: /es/livewire/message.

This has been fixed and tagged in: v2.3.12

squishythejellyfish commented 3 years ago

๐Ÿ‘‹ Oh Hi! I'm Squishy, the friendly jellyfish that manages Livewire issues.

I see this issue has been closed.

Here in the Livewire repo, we have an "issues can be closed guilt-free and without explanation" policy.

If for ANY reason you think this issue hasn't been resolved, PLEASE feel empowered to re-open it.

Re-opening actually helps us track which issues are a priority.

Reply "REOPEN" to this comment and we'll happily re-open it for you!

(More info on this philosophy here: https://twitter.com/calebporzio/status/1321864801295978497)

usernotnull commented 3 years ago

v2.3.12 resolved the issue if there was a prefix, such as xxx.com/ar/blog BUT if in the options of the LaravelLocalization, we set to hide the default locale (let's say en is the default), then the problem still exists, and a 404 is returned if we're on xxx.com/blog (auto redirected from xxx.com/en/blog)

Can anyone also confirm this?

The middleware responsible for dynamically changing the prefix again is called 'localizationRedirect', if set in middleware

renepardon commented 3 years ago

Just updated to 2.3.13. (was 2.3.6 before) All livewire Links return 404 for me now.

๐Ÿ‘‹ Oh Hi! I'm Squishy, the friendly jellyfish that manages Livewire issues.

I see this issue has been closed.

Here in the Livewire repo, we have an "issues can be closed guilt-free and without explanation" policy.

If for ANY reason you think this issue hasn't been resolved, PLEASE feel empowered to re-open it.

Re-opening actually helps us track which issues are a priority.

Reply "REOPEN" to this comment and we'll happily re-open it for you!

(More info on this philosophy here: https://twitter.com/calebporzio/status/1321864801295978497)

REOPEN

renepardon commented 3 years ago

Just updated to 2.3.13. (was 2.3.6 before) All livewire Links return 404 for me now. So this is even worse behaviour than I had before: https://github.com/mcamara/laravel-localization/issues/773

So I need to go back to 2.3.6 for now

marispro commented 3 years ago

Lol this becomes mind blowing, but latest update solved my all issues including prefixed named routes inside livewire (which didn't worked well before)

usernotnull commented 3 years ago

@marispro are you using 'localizationRedirect' middleware which hides the default locale?

marispro commented 3 years ago

@RJFares no, I don't use laravel-localization, but have something like that condition which hides default locale

Route::group([
       'prefix' => config('app.locale') == config('app.fallback_locale') ? '' : app()->getLocale()
], function(){
       // all routes here
})

PS: app.locale is set before this dynamically

joshhanley commented 3 years ago

Reopening due to @RJFares issue. I've run a test locally with the package and now going to /en is fine, but / is erroring out.

Investigating now.

calebporzio commented 3 years ago

Ok, this is dark.

Here's what's happening.

Let's say you have the following route in your app:

Route::group(['prefix' => LaravelLocalization::setLocale()], function () {
    Route::get('/foo', Foo::class);
});

If you visit "/foo" from the browser, this route is registered:/foo If you visit "/en/foo" from the browser, this route is registered:/en/foo

In a normal scenario, the endpoint you are requesting and the registered route match up so all is good.

The reason we are seeing issues with Livewire is:

My initial fix was to make the Livewire AJAX endpoint include the locale /livewire/message -> /en/livewire/message

Now we have the reverse problem like people are seeing.

If you visit /foo and, now update Livewire, Livewire is looking for /en/foo inside the routes that only contain /foo and the match isn't found.

This dynamic prefixing stuff based on the original URL seems really heavy handed to me.

However, I don't want to alienate users of this package, so we have to find a solution.

The only thing I can think of right now is something really dark like, when Livewire is looking for the "original" route, if it doesn't find it, try looking for the route prefixed with the locale (/en)

Does anyone else have ideas?

Thanks.

imagina commented 3 years ago

Same issue here!

calebporzio commented 3 years ago

Ok, I've just tagged v2.3.14 which should fix this in perpetuity. Please re-open if I'm totally wrong.

What I did:

If Livewire can't find the original route, it will remove the locale from the endpoint and look again.

This fixes it both ways for both cases mentioned above.

Thanks for helping out. Fingers crossed.

squishythejellyfish commented 3 years ago

๐Ÿ‘‹ Oh Hi! I'm Squishy, the friendly jellyfish that manages Livewire issues.

I see this issue has been closed.

Here in the Livewire repo, we have an "issues can be closed guilt-free and without explanation" policy.

If for ANY reason you think this issue hasn't been resolved, PLEASE feel empowered to re-open it.

Re-opening actually helps us track which issues are a priority.

Reply "REOPEN" to this comment and we'll happily re-open it for you!

(More info on this philosophy here: https://twitter.com/calebporzio/status/1321864801295978497)

marispro commented 3 years ago

Named routes (which I render in Livewire component) doesn't contain locale again, however, in my case I have another solution for that. So not a big problem.

calebporzio commented 3 years ago

Ok, thanks @marispro - if an issue crops up, feel free to submit a new issue.

cdo9 commented 3 years ago

I still have the issue on v2.3.17, here is my route file :

Route::group([
    'prefix' => LaravelLocalization::setLocale(),
    'middleware' => ['localize', 'localeSessionRedirect', 'localizationRedirect', 'localeViewPath']
], function() {
    Auth::routes();
    Route::get('', [HomeController::class, 'index'])->name('home');
    Route::group(['middleware' => ['construction.check']],function() { /* todo : remove this group for real production */
        Route::get(LaravelLocalization::transRoute('routes.blogs.index'), [BlogController::class, 'index'])->name('blogs.index');
        Route::get(LaravelLocalization::transRoute('routes.blogs.show'), [BlogController::class, 'show'])->name('blogs.show');
    });
});

Every action calls /livewire/message/like and returns a 404 not found

joshhanley commented 3 years ago

@cdo9 what is the original url that your Livewire component is on?

Also can you in your browser, open devtools, and go to network tab. Then trigger a Livewire request (that errors). If you click on that request, and go to headers tab at the bottom you should see request payload. Can you share everything that is in the fingerprint key? It will look something like below

image

usernotnull commented 3 years ago

@cdo9 try without localizationRedirect middleware. If it works, it means it's another issue I can help with, not livewire related.

cdo9 commented 3 years ago

@RJFares I have the same error without localizationRedirect

@joshhanley my urls looks like this : mysite.com/fr/blogs/translated-category-slug/translated-article-slug

and here is what my fingerprint looks like :

Capture dโ€™eฬcran 2021-02-13 aฬ€ 08 26 19

if i switch back to v2.3.8 all of my components are working again

joshhanley commented 3 years ago

@cdo9 great! Thanks for the info. I suspect it's the transRoute that's causing the issue. I'm thinking Livewire doesn't know that's a route model binding due to the translation.

Butochnikov commented 3 years ago

@calebporzio now livewire always go to /livewire/message/* hence the locale is set to en (or default locale) but in fingerprint: locale: ru

it turns out that you need to set the locale manually in the component:

$locale = session('locale'); \\ or get from fingerprint
LaravelLocalization::setLocale($locale);
epalmans commented 3 years ago

also applies to https://github.com/mcamara/laravel-localization/issues/773

Bit of a nasty workaround, but maybe it helps for some:

I've registered a second routes-file that does not have the LaravelLocalization group middleware and the locale prefix applied and then manually insert this Route into it:

Route::post('livewire/message/{name}', '\Livewire\Controllers\HttpConnectionHandler')->name('livewire.message');

That works, but it's not very pretty. Which makes me wonder.... @calebporzio might livewire's serviceprovider be somehow be able to register its route(s) in a similar same way; by bypassing any prefixes and middleware?

epalmans commented 3 years ago

also applies to mcamara/laravel-localization#773

Bit of a nasty workaround, but maybe it helps for some:

I've registered a second routes-file that does not have the LaravelLocalization group middleware and the locale prefix applied and then manually insert this Route into it:

Route::post('livewire/message/{name}', '\Livewire\Controllers\HttpConnectionHandler')->name('livewire.message');

That works, but it's not very pretty. Which makes me wonder.... @calebporzio might livewire's serviceprovider be somehow be able to register its route(s) in a similar same way; by bypassing any prefixes and middleware?

ohw wait, a better solution: publish the livewire config and manually set the middleware_group to a custom middleware. Then in your middleware config make sure to exclude the laravelocalization middlewares from that group!

Cosnavel commented 3 years ago

I think the problem is the base route that calls the livewire request. I fixed this problem for me with an addition to #2661. I removed the language prefix from the URL and used the base URL for making the request.

vendor/livewire/livewire/src/Controllers/HttpConnectionHandler.php

protected function makeRequestFromUrlAndMethod($url, $method = 'GET')
    {
        $url = LaravelLocalization::getNonLocalizedURL(str_replace(config('app.url'), '', $url));

Does anyone know how to pass down the non-localized URL to livewire outside of the Connection Handler?

cdo9 commented 3 years ago
Cosnavel commented 3 years ago

@cdo9 I just realized that my fix is not working when u got a livewire component on your / route. The code below fixes this too.

protected function makeRequestFromUrlAndMethod($url, $method = 'GET')
{
    $url = str_replace(config('app.url'), '', $url);

    if (empty($url)) {
        $url = '/';
    }

    $url = LaravelLocalization::getNonLocalizedURL($url);
alexchirolde commented 3 years ago

I added my custom middleware to add the lang prefix to the url. On my browser domain.com/en (I always have a lang prefix) and when I check the browser console I get domain.com/en/livewire/message/ but still 404. Does anyone was able to solve this??

alexchirolde commented 3 years ago

solved here, I`m using nwidart/laravel-modules so I have the livewire problem only on a specific module, which contains all the livewire logic. In case you need it mhmiton/laravel-modules-livewire helps me a lot. If is not required displaying the locale on the url, just register the routes without the lang prefix:

protected function mapWebRoutes()
    {
        Route::middleware(["web", "remove.locale"]) // the remove.locale middleware does add the language support to your blades templates
            ->prefix("en") // remove whatever logic in here
            ->namespace($this->moduleNamespace)
            ->group(module_path("Module", "/Routes/web.php"));
    }

The remove.locale middleware:


public function handle($request, Closure $next)
    {
        $locales = config("app.locales");

        if (Session::has("locale")) {
            $currentSessionLocale = Session::get("locale", config("app.locale"));
        } else {
            $currentSessionLocale = $request->getLocale();
        }
        if (in_array($currentSessionLocale, array_keys($locales))) {
            app()->setLocale($currentSessionLocale);
     } else
            app()->setLocale(config("app.fallback_locale"));

        return $next($request);
    }

and then in your blades the regular function @lang("key.value") will work.

Also the livewire calls will be working without the locale. Hope it helps to someone.

Best