.htaccess RewriteRule error in a CGI script - apache

I have following files:
website-folder
- .htaccess
- user.php
the .htaccess looks like:
RewriteRule ^user/([0-9]{1,11})$user.php?user_id=$1
Now I want to give in localhost/website-folder/user/1234 which should take the data from localhost/website-folder/user.php?user_id=1234.
But I am getting following error:
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there was an error in a CGI script.
If you think this is a server error, please contact the webmaster.

Your /website-folder/.htaccess file should look like this:
RewriteEngine on
# Set the base from which to rewrite as the site runs from a subfolder.
# This can be safely removed if you ever move to the root of the domain
RewriteBase /website-folder/
# Rewrite user/{id} to user.php (skip existing files)
RewriteRule %{REQUEST_FILENAME} !-f
RewriteRule %{REQUEST_FILENAME} !-d
RewriteRule ^user/([0-9]{1,11})$ user.php?user_id=$1 [QSA,L]
The error was thrown as you had a code formatting issue (assuming you copy-pasted the code into your question): there was no space between $ and user.php....
I've also added a RewriteBase in your file as you are running from a sub-folder.
Lastly, I've added the Query String Append (QSA) flag, which allows you to add more query parameters to the rewritten URI. You also left out the Last flag (L), which would have introduced potential issues for other rules below it.

Related

Changing file name in htaccess gives error 500

I have set
mydomain.com/page
to point to
mydomain.com/script.cgi
using htaccess and mod_rewrite, which works perfectly. BUT, when I change the file name and the associated rewrite rule I get error 500. Initially I thought it was a browser caching issue, but clearing the cache doesn't help. Here's the htaccess file:
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^page(.*)?$ /script.cgi$1 [NE,NC,L]
As I said this works perfectly - until I change the file name and the rule. If I change my script file name to script2.cgi and modify the rule to point to script2.cgi, it throws an error. Is it some kind of server caching issue?
I found the answer. It won't be obvious here because I used placeholder names. The problem was my alias folder and destination script began with the same letters.
/page -> /page.cgi
Because I used ^page(.*)?$ in the rule, it was also matching page.cgi thus creating an infinite loop. The answer is to either change the rule to ^page$ to match the entire alias name only, or change the name of the script to something else. Thanks everyone. Hope this helps someone else.

Explain .htaccess rules. Doesn't work for me

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

.htaccess - redirect to page/dir, while all pages/dir are internally parsed as query string parameters

Scenario:
I have a .htaccess file that is handling a lot of rewrites (I am aware it would be possbile/easier in PHP)
Everything worked fine
/some/fake/dir/foobar was internally rewritten to
/index.php?some=fake&dir=foobar
and any url containing a query string was stripped
so I wanted to make a "coming soon page" or a "under maintenance page" for any IP not matching the declared condition
Example of what I've tried:
I tried something like this, and some other variations.
# IF not from DEV address
RewriteCond %{REMOTE_ADDR} !^123\.123\.123\.123$
# AND not for comingsoon page or other assets
RewriteCond %{THE_REQUEST} !\?comingsoon [OR]
RewriteCond %{REQUEST_URI} !^/comingsoon
# THEN send them to comingsoon page
RewriteRule ^ /comingsoon [R,L]
I've tried it in all potential areas of the .htaccess file to meet the conditions.
It seems to be the problem is getting redirect loops. the apache logs show it requesting the /comingsoon page then redirecting to the root directory /. I'm assuming because of the internal conversion of /foo/bar to /?foo=bar. But I can't seem how to figure this out where / is redirected to the "ghost" page /comingsoon
below is the layout of the .htaccess file: (code omitted to save time understanding problem)
Options -Indexes
RewriteEngine on
RewriteBase /
# Forced https (should not effect the problem)
[...]
# To externally redirect /dir/index.php to /dir/
[...]
# To externally redirect /dir/foo.php to /dir/foo
[...]
# To internally redirect /dir/foo to /dir/foo.php
[...]
# Prevent Rewrite on existing directories, files, and links
[...]
# Remove query string
[...]
# To internally rewrite directories as query string
[...]
# Custom error documents
Comment if full .htaccess is required to solve. Thanks!
/EDIT:
Please note, I have gotten it working fine with "real" files as my script prevents rewrites on existing files being requested. This is not the solution I'm looking for. My main index file is serving the dynamic content dependent on what the request_uri is rewritten to via query strings
Well, I guess I solved it. had to check the %{THE_REQUEST} HEADERS for the hidden query string with ?comingsoon
You can see the whitelist of files or directories I added if anyone runs into this problem as well :)
# IF not from DEV address
RewriteCond %{REMOTE_ADDR} !^127\.0\.5\.1$
# AND not for comingsoon page or other assets
RewriteCond %{THE_REQUEST} !^GET\s(?:/\?comingsoon|/comingsoon|/assets/|/favicon\.ico|/google[A-Za-z0-9]+\.html) [NC]
# THEN send them to comingsoon page
RewriteRule ^ /comingsoon [R,L]

Apache does not rewrite request if file on path exists

I'm doing a rewrite with mod_rewrite on every request that does not match an existing file or directory. This is my configuration:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [NC,L]
This is used to map URLs like /abc/foo or /abc/foo/10 to my app. And it works just fine.
To improve the performance, my app now stores the results of a call to /abc/foo in a file foo in the corresponding directory /abc - so that after the first call the rewrite conditions do no longer apply (file does not exist) and apache directly serves the data without first invoking the app. Works fine as well.
The problem is: Requesting /abc/foo/10 does now no longer cause the URL to get rewritten, instead I get an error "404 File Not Found". The log entries state that the rewrite condition !-f is no longer true, but actually the file /abc/foo/10 does not exist. /abc/foo exists, but is a file, not a directory.
How can I get this to work?
(MultiViews is disabled)
This is because foo exists as a file and apache serves foo with the additional /10 passed as a query string. So, your application should write some additional code to the foo file, that also checks if a request includes some additional url component and then handle creation of the directory "foo" and the file 10.
You must be in per-dir/htaccess context w/ AcceptPathInfo on.
Therefore REQUEST_FILENAME matched the part that existed, and is not the same as REQUEST_URI.
Use the REQUEST_URI var if you don't care where the request was previously mapped in your rewritecond.
In per-vh context, these vars are always the same.
Project design is a little bit wrong - others already pointed out that it's not scallable - how could You cache a request to /abc/foo/10 if there is already a /abc/foo file?
Answer to that and to Your problem is usage of subfolders instead of files.
So instead of cache structure of:
/abc/foo
/abc/bar
...?
use:
/abc/index.html
/abc/foo/index.html
/abc/bar/index.html
/abc/foo/10/index.html
and each time create new directory with index.html
This time Apache would find out that there is /abc/foo folder but no /abc/foo/10 file in it, so RewriteCond will apply.
edit
You could also try a different way - to modify url with mod_rewrite, changing urls:
/abc/foo
/abc/bar
/abc/foo/10
to something like:
/cache/abc~foo
/cache/abc~bar
/cache/abc~foo~10
htaccess rules (roughly):
# redirecting to cache folder and removing last '/'
RewriteCond %{REQUEST_URI} ^/(abc|cde)
RewriteRule ^(.*?)/?$ /cache/$1 [L]
# recursive replacing '/' with '~'
RewriteCond %{REQUEST_URI} ^/cache/.*/
RewriteRule cache/(.*)/(.*)$ /cache/$1~$2 [L]
Your standard htaccess rules should follow

Apache mod_rewrite usually works, but won't work in this folder -- what's wrong?

I have an Apache web server that usually handles mod_rewrite fine. I have a directory called /communications/q/ and I want to rewrite any URI to insert "index.php" before the rest of the entered URI.
For example, /communications/q/something/else should actually serve communications/q/index.php/something/else. It's the standard PHP CodeIgniter setup.
I placed a .htaccess file in the /q/ directory and put the following in it:
RewriteEngine On
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
When I even try to go to /communications/q/, I get a 404 Not Found error. Which makes no sense at all because if I comment the .htaccess stuff out, I get the index.php page if I go to /communications/q/, but with the code, I get 404 Not Found.
Anyone spot what I'm doing wrong?
FYI I have a controller called hello, so technically /communications/q/hello should work, but it's a 404, also. But with .htaccess commented out, /communications/q/index.php/hello works fine.
..
==== ADDED NOTE #1 ====
Using CodeIgniter, I should be able to call controllers and functions using the URI structure. So I have a controller called welcome, actually, and then a function called index() which is the default, and a function called hello().
The way CI works, I would write /communications/q/index.php/welcome and I would get the output of the index() function from the welcome controller. And in fact, this works perfectly right now.
Unfortunately, having that weird index.php in the URI is unwieldy and unnecessary, so CI suggests using .htaccess to allow the URI to omit that section of the URI and silently reenter it in the background, using mod_rewrite.
When I add the RewriteRule above, however, it doesn't work. So:
/controller/q/welcome returns a 404 error when it should return exactly the same thing as /controller/q/index.php/welcome. That's the problem. Shouldn't the RewriteRule above make that work?
..
The substitution in a RewriteRule is relative to the DocumentRoot. Based on this, I'd suggest you try:
RewriteEngine On
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /communications/q/index.php/$1 [L]
The answer was in the CodeIgniter wiki, in the end. I replaced my .htaccess code with the following:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /communications/q/
# Removes access to the system folder by users.
# Additionally this will allow you to create a System.php controller,
# previously this would not have been possible.
# 'system' can be replaced if you have renamed your system folder.
RewriteCond %{REQUEST_URI} ^system.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
# When your application folder isn't in the system folder
# This snippet prevents user access to the application folder
# Submitted by: Fabdrol
# Rename 'application' to your applications folder name.
RewriteCond %{REQUEST_URI} ^application.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
# Checks to see if the user is attempting to access a valid file,
# such as an image or css document, if this isn't true it sends the
# request to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>
<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin
ErrorDocument 404 /index.php
</IfModule>
And everything worked perfectly. The major relevant change, I think, was adding a ? to the RewriteRule after index.php -- does anyone understand why that's necessary?
Source: http://codeigniter.com/wiki/mod_rewrite/