How redirect from /file.php to /file on nginx?

后端 未结 1 1810
时光取名叫无心
时光取名叫无心 2021-01-27 21:54

I\'m currently hiding the .php extension from the urls on my nginx server with this configuration:

location / {
    try_files $uri $uri/ @extensionless-php;
    i         


        
相关标签:
1条回答
  • 2021-01-27 22:50

    To redirect those requests permanently with HTTP 301 code try

    rewrite ^(.*)\.php$ $1 permanent;
    

    Put this directive before your location blocks.

    Update

    After this being answered, OP asked another question (now being deleted) - what if you have the following webroot structure:

    webroot
    |
    +-- index.php (PHP file)
    |
    +-- somename.php (PHP file)
    |
    +-- somename (folder)
    |   |
    |   +-- index.php (PHP file)
    |
    +-- someothername (folder)
        |
        +-- index.php (PHP file)
    

    Previous solution makes it impossible to serve somename.php file, because the request to http://example.com/somename would be redirected by try_files directive to http://example.com/somename/ and in next turn would be served with somename/index.php file.

    This can be solved, but you'll have to stop using index and try_files directives and emulate their behavior with your own request processing logic. This is what I've ended up with:

    map $original_uri $maybe_slash {
        ~/$      '';
        default  '/';
    }
    
    server {
    
        ...
    
        if ($original_uri = '') {
            set $original_uri $uri;
        }
    
        # redirect requests of '/somepath/somefile.php' to '/somepath/somefile'
        rewrite ^(.*)\.php$ $1 pemanent;
    
        location / {
    
            # this emulates 'try_files $uri $uri/ ...' directive behavior and redirects '/some/path'
            # to '/some/path/' if 'some/path.php' file does not exists, but 'some/path' folder exists
            # and there are 'some/path/index.html' file in that folder
            set $check_redirect $rewrited$maybe_slash;
            if ( $check_redirect = '1/' ) {
               return 301 $original_uri/$is_args$args;
            }
    
            if ( -f $document_root$uri.php ) { rewrite ^ $uri.php last; }
    
            # this emulates 'index index.php index.html' directive behavior
            if ( -f $document_root$uri${maybe_slash}index.php ) {
                set $rewrited 1;
                rewrite ^ $uri${maybe_slash}index.php last;
            }
            if ( -f $document_root$uri${maybe_slash}index.html ) {
                set $rewrited 1;
                rewrite ^ $uri${maybe_slash}index.html last;
            }
    
            # if a request for an absent resource should be served with some backend
            # controller, it is ok to use some 'try_files' directive here like
            # try_files $uri /index.php?path=$original_uri;
    
        }
    
        location ~ \.php$ {
    
            # this emulates 'try_files $uri $uri/ ...' directive behavior and redirects '/some/path'
            # to '/some/path/' if 'some/path.php' file does not exists, but 'some/path' folder exists
            # and there are 'some/path/index.php' file in that folder
            set $check_redirect $rewrited$maybe_slash;
            if ( $check_redirect = '1/' ) {
               return 301 $original_uri/$is_args$args;
            }
    
            # no 'try_files $uri =404'  or 'include snippets/fastcgi-php.conf' here, this location
            # can be reached only if requested PHP file is really exists in webroot folder
            include fastcgi.conf;
            fastcgi_param SCRIPT_FILENAME $document_root$uri;
            fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
    
        }
    
    }
    

    With this configuration and webroot structure given above

    • request to http://example.com/ would be served with webroot/index.php file;
    • request to http://example.com/somename would be served with webroot/somename.php file;
    • request to http://example.com/somename.php would be redirected to http://example.com/somename and served with webroot/somename.php file;
    • request to http://example.com/somename/ would be served with webroot/somename/index.php file;
    • request to http://example.com/someothername would be redirected to http://example.com/someothername/ (since no webroot/someothername.php file exists) and served with webroot/someothername/index.php file.

    Important note about custom HTTP error pages

    If you have some custom error page, for example webroot/error/404.php for HTTP 404 error, instead of usual way to define it like

    error_page 404 /error/404.php;
    

    you'd need to skip .php extension of that file:

    error_page 404 /error/404;
    
    0 讨论(0)
提交回复
热议问题