Reputation: 1140
I'm using Laravel 5.1. I have this in my .htaccess
file (these are only changes in the file, compared to the default):
Options -Indexes
ErrorDocument 403 /error-403
I also have a js/
directory in my public/
directory.
When I try to access the /js/
directory in the browser, I don't get the /error-403
route opened, as I'd expect. Instead I get Laravel's 404 HTTP error handler triggered (I get a 404 page from Laravel) and I don't understand why.
When I open /error-403
directly in the browser, the corresponding view opens fine. Here are some interesting server variables which I see in PHP for both of these requests.
/error-403
:
"REDIRECT_STATUS" => "200"
"REDIRECT_URL" => "/error-403"
"REQUEST_METHOD" => "GET"
"REQUEST_URI" => "/error-403"
/js/
:
"REDIRECT_REDIRECT_REQUEST_METHOD" => "GET"
"REDIRECT_REDIRECT_STATUS" => "403"
"REDIRECT_STATUS" => "403"
"REDIRECT_URL" => "/error-403"
"REQUEST_METHOD" => "GET"
"REQUEST_URI" => "/js/"
To me it seems like Apache's redirecting the request to Laravel, but Laravel, instead of picking up the URL /error-403
, picks up the URL /js/
for which no route exists and then throws a 404.
Has anyone else encountered similar problems? What am I missing here? How can I set up Laravel so that Apache (and its ErrorDocument
statement) redirects to a route defined in Laravel? And by "how", I mean how can I do it in a proper way, so it's not a hack. I guess I could create a custom middleware which would examine these server variables and correct the route, but this seems dirty and I don't know if I'm missing something here.
Upvotes: 0
Views: 979
Reputation: 1140
I managed to overcome this problem, if anyone is interested.
I noticed the problem was in Symfony\Component\HttpFoundation\Request::prepareRequestUri()
. In this method only REQUEST_URI
is taken into account, REDIRECT_URL
isn't ever looked at.
Laravel uses Illuminate\Http\Request
which is a child class of the previously mentioned one. If you look at the service container, you will see an instance of this class. So what I needed to do was to extend this class and override this method. So I did this:
<?php
namespace App\Http;
use Illuminate\Http\Request as LaravelRequest;
class Request extends LaravelRequest
{
protected function prepareRequestUri()
{
if ((int) $this->server->get('REDIRECT_STATUS', '200') >= 400 && $this->server->has('REDIRECT_URL')) {
$requestUri = $this->server->get('REDIRECT_URL');
$this->server->set('REQUEST_URI', $requestUri);
return $requestUri;
}
return parent::prepareRequestUri();
}
}
So, if the REDIRECT_STATUS
is over 400 and REDIRECT_URI
exists, it will be used, otherwise it will fallback to framework default logic.
Finally, I had to instruct the framework to use my implementation and not its own. I did this by editing public/index.php
and replacing Illuminate\Http\Request::capture()
with App\Http\Request::capture()
.
And now everything works as it should, at least from what I can tell. Apache error documents are being properly rendered by Laravel.
Upvotes: 1