Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Chop's avatar
Level 1

Wrong _previous url in Session, redirect back goes to an asset

Hi everyone.

I have a really weird problem. When I try to do a simple

Redirect::back()

the page loaded is in fact an asset from my project... An image or a javascript for example.

I created a PictureController that helps me getting pictures from users in any size from my storage folder and that creates a Response with the picture resized. So I first thought I messed up somewhere in this controller but even if this controller return no response, Redirect::back() still redirects me to one of my DebugBar javascript...

I'm really confused and would really appreciate some help! :)

0 likes
26 replies
Francismori7's avatar

If you are using a request to get the image on the page, of course, now the session will use the new URL because the request for the image is newer.. you pass it through the whole Laravel process so it stores it as the current URL and when you submit a page or whatever, that URL will still be the previous one because it was called last by your client.

Quick workaround is to override the previous page in the session with the real one (go back two, if you want) when resizing the image.

Chop's avatar
Level 1

Hi Francismori7 and thanks for your very quick answer! :)

Ok I didn't know that was a normal behavior since I just passed a Response with a content-type 'image/jpeg' without any "code" in the page. Weird thing is the problem only appears on 1 page.

Also I tried to use

Session::setPreviousUrl('/test') 

before and after (we never know... :p) I return my response and it doesn't change anything...

Chop's avatar
Level 1

Also I doubt the problem comes from my Response since when I comment my

return \Response::make(...)

the _previous.url is still a link to an image from my page...

EDIT: Also... DebugBar show a different result for the content of _previous.url in Session than a direct Session::previousUrl() inside the page... I'm really lost...

Francismori7's avatar

@Chop As soon as a request goes through the Laravel middlewares and stuff, it is stored in the session as the "current URL", hence being the previous on your session.

You get /photos, now it's the previous URL (/photos), it that page, you call /photo/152 and return a response (you call it with the src="" attribute of the image, browser does it automatically. Laravel stores that as current URL, because it doesn't know if it's a page or anything else, for Laravel, it's just a response, whatever it is. Previous URL is now /photo/152 in the session. It's actually normal.

The request goes through the Illuminate\Session\Middleware\StartSession middleware. This in turns initializes the session interface and stores the current URL: $this->storeCurrentUrl($request, $session); This method in turns does this:

    protected function storeCurrentUrl(Request $request, $session)
    {
        if ($request->method() === 'GET' && $request->route() && !$request->ajax()) {
            $session->setPreviousUrl($request->fullUrl());
        }
    }

setPreviousUrl in \Session just puts the key _previous.url in the session.

I'm NOT sure, but you can try in your /photo/152 controller method to do this: Session::setPreviousUrl(Session::previousUrl());

(Of course I'm using fake routes etc)

EDIT: DebugBar updates itself with every request, you get a dropdown in the top right of it, showing every request. Session::previousUrl() is echo'ed in the page directly and not updated when you call the image, so that's why.

1 like
Chop's avatar
Level 1

@Francismori7 Thanks a lot for pointing out the function responsible for this behavior! I already tried to change the previousUrl in my controller without success.

What I did is I added a condition to stroreCurrentUrl() like this:

function storeCurrentUrl(Request $request, $session)
    {
        if ($request->method() === 'GET' && $request->route() && !$request->ajax() && !preg_match("/(.jpg)|(.png)|(.gif)|(.jpeg)|(javascript\?[0-9]{1,})$/", $request->url()))) {
            $session->setPreviousUrl($request->fullUrl());
        }
    }

Probably not the best workaround for this problem, but at least it's solved it! If you know a better way to integrate this change, I'm all ears! :)

Thanks again for your precious help!!

EDIT: If anyone has an idea why when I try to get $request->header('Content-Type'), it always returns nothing, I would appreciate it! It would probably be a lot smoother to create a condition with the header and not the url! :)

Francismori7's avatar

I think your fix might have broken the whole previous URL thingy to be honest, unless your route does end with an extension?

As for $request->header, request is what is sent to your server by a web browser/client, not what your server generates.

Chop's avatar
Level 1

My routes for the pictures end with ".jpg" yes, so for this part it works and it doesn't seems to be broken yet.

Ok I understand now why I can't get this header... Is there any other way for me to check what kind of content the request is to filter it? Right now, I don't see any other way to do it without using the url...

Francismori7's avatar

@Chop You can use named routes. No matter the passed params (in your route), it'll have the same name in Request::route().

1 like
Chop's avatar
Level 1

@Francismori7 Thanks!! Ok so my new fix looks like this:

if (
    $request->method() === 'GET' && 
    $request->route() && !$request->ajax() && 
    $request->route()->getName() != "pictures.get" && 
    !str_contains($request->route()->getName(), 'debugbar') 
    ){
    $session->setPreviousUrl($request->fullUrl());
}

I hope it's a less crappy fix!

Thanks again for your help, you saved me! ;)

Francismori7's avatar
Level 52

@Chop The only problem I see with your fix is that you are overriding changes in a vendor file - meaning it will be replaced every time you run composer install or composer update.

Maybe this belongs somewhere else, like your own Middleware extension:

Create a new middleware called StartSessionExtended:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Session\Middleware\StartSession;

class StartSessionExtended extends StartSession // Extend the base StartSession middleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return parent::handle($request, $next); // defer to the right stuff
    }

    /**
     * Store the current URL for the request if necessary.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Illuminate\Session\SessionInterface $session
     * @return void
     */
    protected function storeCurrentUrl(Request $request, $session)
    {
        if (
            $request->method() === 'GET' &&
            $request->route() && !$request->ajax() &&
            $request->route()->getName() != 'pictures.get' &&
            !str_contains($request->route()->getName(), 'debugbar')
        ) {
            $session->setPreviousUrl($request->fullUrl());
        }
    }
}

Then, in app/Http/Kernel.php, change 'Illuminate\Session\Middleware\StartSession' to 'App\Http\Middleware\StartSessionExtended'

Untested, but should be better.

Francismori7's avatar

@Chop Glad to help! Guess what, I also did some refactoring thanks to you! :P Lazy fixes are my favorite, however they shouldn't be left unattended too long (whoops)

Chop's avatar
Level 1

@Francismori7 Well, I shouldn't have declare victory too soon! :p When the fix is added as a middleware file, the sessions aren't working correctly anymore... Impossible to login/logout and I got TokenMismatchedExceptions everywhere (I guess because of the Session not working correctly)... :'(

Chop's avatar
Level 1

@Francismori7 Yes, copy paste... When I test it, I can't even logout my current user... :/

Chop's avatar
Level 1

@Francismori7 Already tried, it doesn't change anything... It's EXACTLY the same function that I have now in my StartSession and StartSessionExtended files...

I even tried to copy past the entire file to have exactly the same content in both (except the namespace ofc) and I still have the same problems with the sessions...

Francismori7's avatar

@Chop This is beyond my understanding... If you reverse the changes and go back to the original middleware? (In Kernel.php too)

Chop's avatar
Level 1

@Francismori7 If I put the fix on the original file, everything works perfectly. If I put the original file as default and put our middleware fix, the sessions aren't working anymore...

Clearly it's the fact that I add the middleware file in Kernel.php that broke something...

Chop's avatar
Level 1

@Francismori7 If I don't replace it and just add it, the first occurence of storeCurrentUrl is triggered before the fix' version, so the _previous.url is already changed into the asset url...

But at least, the sessions are working! Haha :)

EDIT: As implied, until now I replaced it!

Francismori7's avatar

@Chop That was the intended process, replacing the line. No idea why it doesn't work properly on your part though. Is your code on GitHub?

bericp1's avatar

Don't mean to resurrect a dead thread but if anyone else is facing a similar issue, I think I found a solid solution.

@Francismori7 Your solution (replacing the StartSession middleware with a patched one in Kernel.php) looks like it should work and I have no idea why it isn't. For some reason, even if you just extend and don't override any methods, it seems to completely break sessions.

I got it to work by creating App\Http\Middleware\StartSession with the following content (edited to be more general):

<?php


namespace App\Http\Middleware;

use Illuminate\Contracts\Routing\TerminableMiddleware;
use Illuminate\Http\Request;

class StartSession extends \Illuminate\Session\Middleware\StartSession implements TerminableMiddleware {

    /**
     * Store the current URL for the request if necessary.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Illuminate\Session\Store $session
     * @return void
     */
    protected function storeCurrentUrl(Request $request, $session) {
        if ($request->method() === 'GET' && $request->route() && !$request->ajax() && !str_contains($request->route()->getName(), 'debugbar')) {
            $session->setPreviousUrl($request->fullUrl());
        }
    }

}

But instead of making the replacement in the Kernel, I noticed that Laravel was binding \Illuminate\Session\Middleware\StartSession in the IoC container so I just rebound it to the patched StartSession in my AppServiceProvider::register function like so:

$this->app->bind('Illuminate\Session\Middleware\StartSession', 'App\Http\Middleware\StartSession', true);

And now it's working perfectly!

@Chop For me, I just needed LaravelDebugbar's assets not to end up in _previous so you'll have to edit the if statement in the patched StartSession class above to include $request->route()->getName() != 'pictures.get' for your case if this is at all still relevant to you.

2 likes
Francismori7's avatar

@bericp1 Makes sense, if Laravel is already binding the StartSession elsewhere then it obviously gets used instead of our own implementation.

Nice find.

jnbn's avatar

We had a similar problem on one of our projects and I realized that it was because of a broken image url.

Seems like as there's no file server was handling the request to laravel's index which causes SessionMiddleware to log _previous as the asset url.

fyi.

samuelhgf's avatar

Hi, guys! Sorry reopen this thread but I was suffering the same issue.

I was trying to make a router.post from Inertia and on my controller returning a back() but it was returning to a different Location header, to a style file that even't existed on the application.

Turns out that was an extension on my Google Chrome that was causing this mess.

So, for anyone that found this and have a similar issue, try making the test flow on a icognito window.

Please or to participate in this conversation.