dongzhuxun5136 2015-07-29 12:46
浏览 74

将Apache ErrorDocument路由到Laravel路由

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.

  • 写回答

1条回答 默认 最新

  • dongwen6743 2015-07-30 11:44
    关注

    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.

    评论

报告相同问题?

悬赏问题

  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 MATLAB中streamslice问题
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序