skip to Main Content

When I open this page of my website it gives a 500 error:

single-portfolio/3/bizdb-business-directory-data-scraping-uk-

My .htaccess file:

RewriteEngine on
RewriteCond %{THE_REQUEST} /([^.]+).php [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]
RewriteRule ^single-portfolio/([0-9]+)/([0-9a-zA-Z_-]+)$ single-portfolio.php?id=$1&title=$2 [NC,L]

Error shown in browser is:

Internal Server Error
The server encountered an internal error or
misconfiguration and was unable to complete your request. Please
contact the server administrator at postmaster@localhost to inform
them of the time this error occurred, and the actions you performed
just before this error. More information about this error may be
available in the server error log.

error log reports:

Request exceeded the limit of 10 internal redirects due to probable
configuration error. Use ‘LimitInternalRecursion’ to increase the
limit if necessary. Use ‘LogLevel debug’ to get a backtrace

2

Answers


  1. Personnally, I think that it would be good to leave an empty line between your rewrite rules and add a comment to explain what each of them do.

    Step 1 : If I understand the first rewrite rule is to redirect /something.php to /something:

    RewriteCond %{THE_REQUEST} /([^.]+).php [NC]
    RewriteRule ^ /%1 [NC,L,R]
    

    This will force the browser to come back and visit /something due to the R flag.

    Step 2 : The second rewrite rule:

    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^ %{REQUEST_URI}.php [NC,L]
    

    It is an internal redirect to serve the PHP file if it exists, so typically /something would serve internally /something.php if it exists. The L flag tells Apache to stop here and not execute the next rewrite rules. But, the problem is that we all think that Apache will stop now and it’s not the case! Apache will take the resulting URL and pass it again through all the rewrite rules until the URL doesn’t change anymore. This is what they call a "round". So what is hapenning is that you are comming back to the first rewrite rule which will trigger the redirection, which is creating your "to many redirects" error.

    To stop that, in latest versions of Apache you can use the END flag instead of the L flag:

    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^ %{REQUEST_URI}.php [NC,END]
    
    Login or Signup to reply.
  2. RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^ %{REQUEST_URI}.php [NC,L]
    

    It’s this rule (that appends the .php extension via an internal rewrite) that is incorrect.

    This results in a rewrite-loop when requesting /single-portfolio/<anything> because /single-portfolio.php exists (satisfying the condition) but this rule will incorrectly rewrite the request to /single-portfolio/<anything>.php, which would ordinarily result in an erroneous 404 (since you are expecting the last rule to catch this request), but due to the L flag the rewriting engine starts over and repeatedly rewrites the request to /single-portfolio/<anything>.php.php to /single-portfolio/<anything>.php.php.php etc. etc. until the server "breaks" and a 500 response is returned.

    See my answer to the following question on ServerFault with a more detailed explanation of this behaviour: https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error

    Simply changing L to END will fix the rewrite-loop, but won’t resolve the overall problem because you’ll just get the erroneous 404 as mentioned above (the request won’t be correctly rewritten).

    Changing the order of your directives so the last rule that rewrites ^single-portfolio/ is before your second rule that appends the .php extension (via an internal rewrite) would solve your immediate problem, however, you need to fix the above rule so you are testing the same file you are ultimately rewriting to (otherwise, any URL of the form /php-file-that-exists/<anything> would result in a rewrite-loop / 500 Internal Server Error response, instead of the expected 404).

    For example:

    RewriteEngine on
    
    RewriteCond %{THE_REQUEST} /([^.]+).php [NC]
    RewriteRule ^ /%1 [L,R]
    
    RewriteRule ^single-portfolio/(d+)/([w-]+)$ single-portfolio.php?id=$1&title=$2 [NC,L]
    
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
    RewriteRule ^ %{REQUEST_URI}.php [L]
    

    NB: The shorthand character class w is the same as [0-9a-zA-Z_]. And dis the same as[0-9]`.

    The NC flag on the first and last rules are entirely superfluous. I would be wary of using the NC flag on the ^single-portfolio/ rewrite (it shouldn’t be necessary), as this potentially enables duplicate content (eg. /single-portfolio/... and /SiNgLe-PoRtFoLiO/... are both valid and resolve to the same resource.)

    The first rule that removes the .php extension via an external redirect should ultimately be a 301 (permanent) redirect once you have confirmed everything is working OK.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search