I'm setting up a 404 page on a project on my localhost (MAMP) and in my .htaccess file I’ve included the following code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) $1.php [NC,L]
</IfModule>
ErrorDocument 404 http://localhost:8888/project/public/404.php
The 404.php page sits at the same level as .htaccess file in a public folder below the project root:
project
— publicFolder
— privateFolder
The Issue
When I include the code within the <IfModule mod_rewrite.c> it throws an error when I type in a 404 page URL (i.e. a page that doesn't exist). When I remove this <IfModule mod_rewrite.c> code block the problem goes away. The error message 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 you#example.com 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.
When I check the apache error log, as recommended in the above message I get the following:
[core:error] [pid 2575] [client ::1:51038] AH00124: 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.
I suspect the issue may be to do with the line that removes the .php file extension on all of the pages, i.e.RewriteRule (.+) $1.php [NC,L]
My Question
How do I get the clean URL code inside the <IfModule mod_rewrite.c> block to stop throwing an internal server error when a user goes to what should be a 404 page?
Any help great appreciated.
Your issue simply is that you indeed implement an endless rewriting loop.
Have a try using that variant with an additional condition:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L]
You need to understand that the L flag you are using indeed terminates the rewriting, but only for the current cycle . Whenever a rewriting cycle alters (rewrites) the processed request a new cycle is started. Until the request is stable, so is not rewritten again. Since the rewritten target again matches your conditions and the rule's matching pattern you again rewrite the request in your implementation. Which ultimately results in a request to something like /foo.php.php.php.php.php, appending one ".php" for every rewriting cycle.
An alternative would be to use the younger [END]¸ flag here instead of the older [L] flag. The END flag completely terminates the rewriting process, ignoring any other rules. So you need to be sure that rule really is the last that should get applied. Using that flag you won't need the additional condition, since the complete termination obviously prevents an endless rewriting loop.
In general I would advise to not use distributed configuration files for this (".htaccess"). But to implement such rules in the actual http server's central host configuration. And use absolute paths there.
That typically prevents a lot of confusing and side effects.
Certainly there may be other issues here that do not get immediately clear from the question you asked. But above is an obvious issue.
Always test using a fresh anonymous browser window, always make deep reloads in the browser to prevent client side caching effects while testing.
Related
I've got a Drupal site running under the main domain. With the following rewrite rules in the .htaccess file (rootlevel):
# Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
This works fine for the Drupal installation which uses PHP, but it somehow interferes with a newly created subdomain that just uses plain HTML. Upon loading the sub-domain site the browser produces an error message:
500 Internal Server Error
In the logs I find the following error messages:
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.
How can I adjust the .htaccess file so that requests for the subdomain are not affected by the rewrite code that is needed for Drupal to function? (While keeping that code functional for requests aimed at the site under the main domain, of course.)
I stumbled across a solution provided by the Drupal community and decided to implement that one first. That works like a charm.
Here's the link to the page in question:
https://www.drupal.org/node/30334
Look under the section called:
"Restore support for other Directory Index Files (index.htm)".
It reads:
"Drupals .htaccess file also includes a line (DirectoryIndex) that
gives instructions "If asked for a directory path, return the
index.php file found in that directory". This replaces the normal
webserver behaviour that usually says "return the index.htm file found
there"..."
I have hierarchy structure of file as below:
/public_html/directory/
/public_html/directory/index.php
/public_html/directory/file.php
I want to forward the request to the most appropriate link. For example,
mydomain.com/directory/ to mydomain.com/directory/index.php
mydomain.com/directory/file to mydomain.com/directory/file.php
If 404 or 500 error occurs then forward it to /public_html/error.php
For this I have written following code in .htaccess
Options +SymLinksIfOwnerMatch -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# don't touch /forum URIs
RewriteRule ^forums/ - [L,NC]
# hide .php extension snippet
#To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+).php [NC]
RewriteRule ^ %1 [R,L]
# To internally forward /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
ErrorDocument 404 /error.php
ErrorDocument 500 /error.php
It works properly if I make requests as mentioned above. But if I request for page mydomain.com/directory/file/scrap then it generates Internal Server Error
I think its because file is not a directory. But I don't know how to solve this problem here. Please suggest.
Also one more line is mentioned in the error output by server regarding ErrorDocument for 500 in the end. The complete output is as follows:
Internal Server Error
The server encountered an internal error or misconfiguration and was
unable to complete your request.
Please contact the server administrator, root#localhost and inform
them of the time the error occurred, and anything you might have done
that may have caused the error.
More information about this error may be available in the server error
log.
Additionally, a 500 Internal Server Error error was encountered while
trying to use an ErrorDocument to handle the request.
This is happening because the %{REQUEST_FILENAME} -f condition also checks for "path info" style requests. So when you request:
mydomain.com/directory/file/scrap
The rewrite engine will see the file /directory/file.php and assume that you're making a path info style request, e.g. /directory/file.php/scrap
This causes the rewrite engine to loop.
You need to change that condition to:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
Oh, also, as for the ErrorDocument thing, I'm pretty sure that what's happening is the rewrite module is completely ending the URL processing in the pipeline. That means, directives that get applied at the end of the pipeline will never get applied if mod_rewrite flips out and ends all the processing. That's why your ErrorDocument directives aren't being applied. If you fix the rewrite issue, you'll notice that the 500 error document will work again.
Based on the configuration above, I would say there is a problem with /error.php.
Assuming there is no scrap.php, mydomain.com/directory/file/scrap will not get rewritten.
The 500 error also mentions that the error was encountered while trying to use an ErrorDocument.
Try a static error.html instead of a dynamic error.php to narrow the problem down.
You could also log the rewrites to verify that they are working correctly:
RewriteLogLevel 9
RewriteLog /var/log/httpd/rewrite_log
I want to be able to rewrite this
http://localhost/.../identicon/f528764d624db129b32c21fbca0cb8d6.png
to
http://localhost/.../identicon.php?hash=f528764d624db129b32c21fbca0cb8d6
so I add to the /.../.htaccess so this is it:
RewriteEngine On
RewriteRule ^resource/ - [L]
RewriteRule ^identicon/(.+)\.png$ identicon.php?hash=$1 [QSA,L]
RewriteRule ^(.*)$ index.php?t=$1 [QSA,L]
Which doesn't work for some reason because it redirects it to index.php?t=identicon.php; even though the L flag is set! Why?
Add a condition to the last rule to exclude requests that can be mapped to existing files:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?t=$1 [QSA,L]
That is necessary because the L flag generates an internal redirect with the new URL as the request URL:
Remember, however, that if the RewriteRule generates an internal redirect (which frequently occurs when rewriting in a per-directory context), this will reinject the request and will cause processing to be repeated starting from the first RewriteRule.
(Not correct answer; left for reference)
I just figured out what may be the issue - it's something that thwarted me for a long time.
Depending on your server settings, it very well may be interpreting identicon/xxx.png as a request to identicon.php/xxx.png, assuming that the PHP extension is what you wanted. Try going to /index instead of /index.php - if it loads the PHP file, this is the issue affecting you.
This is the MultiViews Apache option, and it's stupid, but it has to be enabled specifically. Go into your site configuration file and see where it is enabled, and remove it.
If you don't have total control over your server configuration, the following may work in .htaccess (depending, ironically, on your server configuration).
Options -Multiviews
A friend of mine has inherited an old Joomla 1.0.x site, that amongst other things has a big problem with IE visitors.
The site is viewable here: http://intellepark.co.za
If you browse the site with Firefox, the GETs / responses bounce around as follows:
1. GET /
2. 302 to /site
3. GET /site
4. 301 to /site/
5. GET /site/
6. 200 (or 304)
Problems in IE
In IE7, the same sequence occurs, but at step 6, IE fails to load the page appropriately and displays the "Internet Explorer cannot display the webpage" error page.
If I load the same page with IE6 (Standalone version) I get intermittent and malformed responses from the server. The document fails to download properly but still displays up until the last byte it received.
Solution?
At first I thought there was something wrong with the output, so:
I checked the HTML: There's a double slash in all asset URLs (e.g. /site//templates/intellepark/js/mootools.js). The doctype is XHTML1, valid, but the charset is Latin.
I disabled JavaScript in IE, but that results in the same behaviour.
So now I suspect it's a configuration issue.
The server is running the following:
Apache 2.2.9
Joomla 1.0.12 Stable
PHP 5.2
What would be causing this bad behaviour in IE? Is it the double slash in the URLs?
What can I recommend to my friend to have this problem fixed?
Thanks for your help - Please let me know if you require any further info!
--nd
edit
Inline paste of the .htacces file
## Can be commented out if causes errors, see notes above.
Options +FollowSymLinks
#
# mod_rewrite in use
RewriteEngine On
# Uncomment following line if your webserver's URL
# is not directly related to physical file paths.
# Update Your Joomla!/MamboDirectory (just / for root)
# RewriteBase /
########## Begin - Joomla! core SEF Section
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (/|\.htm|\.php|\.html|/[^.]*)$ [NC]
RewriteRule ^(content/|component/) index.php
#
########## End - Joomla! core SEF Section
# Block out any script trying to set a mosConfig value through the URL
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
# Block out any script trying to base64_encode crap to send via URL
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
# Block out any script that includes a <script> tag in URL
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Send all blocked request to homepage with 403 Forbidden error!
RewriteRule ^(.*)$ index.php [F,L]
I notice 2 things, but I'm not sure if either is the problem.
1) The site flushes the output early. This is fine (actually good). Other resources can start downloading before the index.php is fully loaded. However, depending on how this is configured it might be causing some problems for IE (and may be related to 2 below).
To diagnose, turn off any early output flushing, and see what happens.
2) The second thing that I notice is that the calculated checksum is different than the stored checksum, and since the content is gzip compressed, IE6 may not decompress after a failed checksum (I don't know what IE's default behavior is in that scenario).
Anyway, turn off compression, and see what happens.
Hope that helps, and let us know when what happens when you disable each of those (individually and both together).
I'm about to do some server maintenance and would like to rewrite requests to Apache's standard 503 temporarily unavailable message.
I've Googled and found a few mod_rewrite snippets, but they all involve doing an [R=503] to a PHP script which then sends its own 503 headers and a hand-written message... which just seems ugly to me, when Apache's default is there for me to use.
So, how can I rewrite all request to Apache's standard 503 error message?
Thanks for your help
(Long time Coding Horror RSS subscriber here... Just in a bit of a rush!)
To add a little bit more, I often have the following:
RewriteEngine on
RewriteCond -f path/to/my-custom-error-document
RewriteRule !^path/to/my-custom-error-document$ - [L,R=503]
What this does is check to see if the error document exists. If it does, it serves up the error page. What this allows me to do is throw up the custom error without having to restart apache. To put it back in place, I just remove (or rename) the error page.
I don’t know exactly since when mod_rewrite allows other status codes than 3xx for the R flag. But this should do it:
RewriteEngine on
RewriteRule ^ - [L,R=503]
And if you’ve set a custom error document, use this to prevent additional internal errors:
RewriteEngine on
RewriteRule !^path/to/my-custom-error-document$ - [L,R=503]
Edit Found a better solution using the REDIRECT_STATUS environment variable:
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} !=503
RewriteRule ^ - [L,R=503]
Thanks guys - worked perfectly.
Here's the exact .htaccess configuration I used (sans my IP address) during maintenance:
RewriteEngine on
RewriteCond %{REMOTE_HOST} !^123\.456\.789\.012$
RewriteCond %{ENV:REDIRECT_STATUS} !=503
RewriteRule ^ - [L,R=503]