Laravel 5 redirect () - & gt; back () does not work as expected


I've got a problem with redirect()->back() when there is no HTTP_REFERER set.

Normally when I open my URL with an ID as parameter to show a specific datarow: http://my-domain/module/ID

If the specified ID is not existent or the current loggedin user has no permission to open it, I make

if (!$this->checkPermission($id)) {
    return redirect()->back()->withError('message');
// do my stuff to show the datarow

But when I change the browsers address field and load an non-permitted ID then there is no HTTP_REFERER set and redirect()->back() redirects me to my last loaded JavaScript for_this_view.js (and shows it) added in the view as following:


<!DOCTYPE html>
<html lang="de">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    {!! HTML::style('assets/jquery-ui/jquery-ui.min.css?ver=1.11.4') !!}
    <!-- some more scripts -->




    {!! HTML::script('for_this_view.js') !!}

    <!-- display datarow -->

What is redirect()->back() doing here? If there is no URL to redirect back laravel is guessing one? And why? Maybe to ever have a way to redirect.

That make me not able to use this function.


Ah, maybe I found my problem...

I've tried to dynamically load JavaScript's if they exist in a specific folder. I do that, because I want my JavaScript's be parsed like a view to get Blade Syntax in it. I added a specific folder to the /config/view.php and made files like for_this_view_js.blade.php. They are dynamically added as for_this_view.js in the routes.php.

And therefore I made something like:

/* load view javascripts */
/** @var \SplFileInfo $path */
foreach (new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator(public_path())
    ) as $path)
    if ($path->isFile()
        && ends_with($path->getFilename(), 'js.blade.php'))
        Route::get('url_to_javascript.js', function() {
            $contents = View::make('for_this_view_js(.blade.php)');
            $response = Response::make($contents);
            $response->header('Content-Type', 'application/javascript');
            return $response;

If no HTTP_REFERER is set, Laravel tries to get the last request from the session. This URL is stored in Illuminate\Session\Middleware\StartSession:

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

As you can see there are a few conditions, which unfortunately your JS requests fulfill:

  1. GET method
  2. Handled by a route
  3. Not an ajax request


As I see it, you have two options.

Disable the middleware

Warning: I haven't tested this and there could be side-effects

Go to app/Http/Kernel.php and remove 'Illuminate\Session\Middleware\StartSession', from the $middleware. Now if no HTTP_REFERER is set, Laravel will simply redirect to the root of your application (/)

Extend the middleware and add additional constraints

You could extend the middleware and add some additional checking:

class CustomStartSession extends \Illuminate\Session\Middleware\StartSession {
    public function storeCurrentUrl(Request $request, $session){
        if(!ends_with($request->url(), '.js')){
            parent::storeCurrentUrl($request, $session);

Then enable it by replacing the original StartSession in app/Http/Kernel.php with yours and any request with an URL ending in .js will not be saved as "previous url"


Apparently the middleware needs to be registered as a singleton to be fully functional. You can do that by adding this in the register method of one of your service providers (e.g. AppServiceProvider)