DEV Community

Tyler Smith
Tyler Smith

Posted on

Handling url-encoded forwarded slashes in Laravel URLs

Today I was building a Laravel app where I needed to query the back-
end for vehicles. The URL included the "make" of the vehicle as an encoded URL segment, and Laravel in turn would provide the models.

// routes/web.php
Route::get('/vehicles/{make}', function ($make) {
    $models = VehicleModels::select()
        ->where('make', $make)
        ->get();
    return view('models', ['models' => $models]);
});
Enter fullscreen mode Exit fullscreen mode

I wanted to see what models "Toyota/Scion" had, but this didn't work when I navigated to /vehicles/Toyota%2FScion. I instead got a 404 error because Laravel was interpreting this path as /vehicles/Toyota/Scion. According to Laravel team members in the GitHub issue tracker, this is the intended behavior and there are no plans to change it. Bummer.

Fortunately, Andrew Finnell proposed a relatively painless solution: double-encode the URL segment, then decode it on the server. Here's what that looks like:

// Original code for generating link:
$link = '/vehicles/' . urlencode('Toyota/Scion');

// New code that encodes url twice:
$link = '/vehicles/' . urlencode(urlencode('Toyota/Scion'));

// Now, we'll decode the route segment in the Laravel back-end:
Route::get('/vehicles/{make}', function ($make) {
    $models = VehicleModels::select()
        ->where('make', urldecode($make))
        ->get();
    return view('models', ['models' => $models]);
});
Enter fullscreen mode Exit fullscreen mode

With this code, Laravel does not interpret the encoded forward slashes as new URL segments, which means I can successfully query the back-end for "Toyota/Scion" using the generated url /vehicles/Toyota%252FScion.

Alternatively, if you wanted to encode the link using JavaScript on the front-end, you'd use the following code:

const link = `/vehicles/${encodeURIComponent(encodeURIComponent("Toyota/Scion"))}
Enter fullscreen mode Exit fullscreen mode

Hopefully this post makes the solution more discoverable and saves you some frustration. I also saw recommendations for Base64 encoding and an older Laravel package that seems to solve the same problem, but I haven't tested these solutions personally.

Discussion (0)