What does this Mod Rewrite do? - mod-rewrite

Can anybody tell me what this does?
RewriteRule .* .main.php [QSA,L]
From what I understand it will rewrite ANYTHING to main.php correct? But not so sure what the QSA,L does.
This is the whole .htaccess file, when I hit the main directory I get a 400 Bad Request error. Edit: Bad request went away when I added an ending slash in the browser to the root directory of this script.
RewriteEngine On
# Transfering to the main tranfer file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !\.css$
RewriteCond %{REQUEST_FILENAME} !\.js$
RewriteRule .* .main.php [QSA,L]
# nobody is allowed to access the access the INI file
<FilesMatch "\.inc.php$">
Order allow,deny
Deny from all
</FilesMatch>

QSA = Query String Append: append the existing query string to the re-written rule
L = Last Rule: last rule of the set, don't process any following RewriteRule
Check out the documentation for more.
Do you have a file that is named .main.php? The dot prefix worries me. Your rules read that unless the request is an exists, symbolic link, or it has a CSS or JS extension it goes to .main.php

Related

Apache rewrite rule for existing files doesn't work

I need to protect all pdf files on server through a password. Typical path to a pdf is /images/a/a2/some.pdf
My rewriting code in httpd.conf is :
RewriteEngine On
Options FollowSymLinks
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^images/([^/]*)/([^/]*)/([^/]*)^.pdf$ /download.php?file=$3& [L]
RewriteRule images/a/a2/VB-VB-41-445%29_Small.pdf$ /download.php?file=ok [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /index.php/$1 [L,QSA]
The 5th line is added to check whether there is some problem in regular expression.
Unfortunately, the redirect doesn't work. If pdf exists it starts to load immediately.
But if path doesn't exist, it works! I need the opposite result. What is wrong with code or maybe there are some config settings with mod_rewrite?
P.S. I noticed one clue to a possible answer: if i replace "images" with "asdf" in rewrite rule and try non-existing path, it redirects to download.php. But if i try non-existing path with "images", it returns 404 error. Asdf doesn't exist on the server, but images - is a true folder.
RewriteRule /images/asd.pdf /download.php?file=ok [L,QSA] - doesn't work, folder exists, file asd.pdf doesn't exist
RewriteRule /asdf/asd.pdf /download.php?file=ok [L,QSA] - works, redirects correctly to download.pdf, path doesn't exists (neither folder nor file)
RewriteRule images/a/a2/VB.pdf$ /download.php?file=ok [L] - doesn't work, redirect doesn't happen, instead an existing pdf file starts to download.
P.P.S. After some time I found that inside /images/ folder there is .htaccess file with this text:
# Protect against bug 28235
<IfModule rewrite_module>
RewriteEngine On
RewriteCond %{QUERY_STRING} \.[^\\/:*?\x22<>|%]+(#|\?|$) [nocase]
RewriteRule . - [forbidden]
</IfModule>
<IfModule expires_module>
ExpiresActive On
ExpiresDefault "access plus 1 month"
</IfModule>
Probably, it is the cause of rewriting issue.
P.P.P.S.
The problem has been solved with writing the rewrite rule in a file .htaccess inside folder /images/:
# Protect against bug 28235
<IfModule rewrite_module>
RewriteEngine On
RewriteCond %{QUERY_STRING} \.[^\\/:*?\x22<>|%]+(#|\?|$) [nocase]
RewriteRule . - [forbidden]
RewriteRule ^[^\/]+/[^\/]+/(.*)\.pdf$ ../download.php?file=$1& [L]
</IfModule>
<IfModule expires_module>
ExpiresActive On
ExpiresDefault "access plus 1 month"
</IfModule>
The PDF starts to download if exists in path because of RewriteCond %{REQUEST_FILENAME} -f directive. This tells apache that the file exists and to not proceed with the following rules. If you remove this line, the mod_rewrite will always follow rules no matter if file exists or not.

.htaccess works in local but not on server (but no 404 error)

I have a .htaccess that is supposed to rewrite my URL. My host has told me that it supports URL rewriting, and I verified that by using phpinfo() and checking.
Anyways, this is my .htaccess:
RewriteEngine On
RewriteRule ^([_a-zA-Z0-9]+)$ index.php?page=$1 [R]
It works like a charm in local, but on my server, it doesn't do anything.
I checked this before on the internet and some people had it, but they all had a 404 error, while I don't have a 404 error. It simply doesn't redirect, it doesn't do anything, so I get all kind of error messages.
RewriteRule ^([_a-zA-Z0-9]+)$ index.php?page=$1 [R]
The regex in your rule doesn't match strings with slashes at any position. I am not sure that's acceptable and you don't give any request examples, but I don't think it is.
You may try this rule-set in one .htaccess file at root directory:
Options +FollowSymlinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !index\.php [NC]
RewriteRule ^([^/]+)/?$ index.php?page=$1 [L]
For permanent redirection replace [L] with [R=301,L].
You can make sure that the file (!-f) or directory (!-d) that you're matching doesn't exist before the rewrite. That way you don't end up with a 500 loop with something like /index.php?page=index. Additionally the ^ character is matching the beginning of the string, so if your original test was in a subdirectory it would not rewrite since you weren't allowing slashes.
This should work for any instance, however it will ONLY make the page variable the last string in the URI.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ([_a-zA-Z0-9]+)$ /index.php?page=$1 [R,L]

Mod-rewrite problems with REQUEST_FILENAME

I have a problem with server interpreting domain.com/index as domain.com/index.php. This screws with my URL structure.
I have created a .htaccess file with the following:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
</IfModule>
So if I type in the URL domain.com/index/about I want to get index/about from $_GET['url']. But instead it is blank. If I type any other URL not starting with index, like domain.com/foo/bar I get the expected results.
I understand that this is due to RewriteCond %{REQUEST_FILENAME} !-f which ignores any Rewrite if a file with same filename exist.
So my RewriteRules gives me the results I want as long as URL doesn't involve the word index or other dir- or filename. And that is all fine, since I have no other dirs or files in the current dir.
So question is; Can I make it more specific, as to say ignore filename.php instead of just filename? Meaning that domain.com/index/about should work but not domain.com/index.php/about.
Side question: And why does domain.com/index/about not work anyways? I have no dir called index/about and no file called index/about. Why does it interpret index/something as index.php/something which makes no sense, as I cannot have a dir inside a file.

mod_rewrite - trouble with combination of rules

I've got the following rules to work which:
only act on files that exist
exclude any files that contain images|js|css in their uri
add trailing slash to request uri
Rewrite rules:
RewriteEngine on
DirectorySlash Off
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/(images|js|css)$
RewriteRule ^(.*[^/.])$ /$1/ [R=301,L]
I now need to correctly redirect my home uri's like so:
http://www.example.com/sitemap/ -> http://www.example.com/index.php?page=sitemap
I've tried the following approach:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/.])$ index.php?page=$1 [R=301,L,NC]
But I get a page not found, presumably because $1 is being fed something with a slash in it. I thought [^/] would remove it but apparently not.
Could someone explain where I am going wrong here please?
Use this rule -- it will rewrite /sitemap/ into /index.php?page=sitemap:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ /index.php?page=$1 [QSA,L]
Put it into .htaccess into website root folder. If placed elsewhere it need to be tweaked a bit.
URL will stay the same. Existing query string will be preserved.
The trailing slash / must be present (i.e. /sitemap will not trigger this rule).
It will only rewrite if there is no such folder or file (i.e. if you have a folder named sitemap in your website root folder then no rewrite will occur).
It will only work for 1-folder deep URLs (e.g. /sitemap/, /help/, /user-account/ etc). It will not work for 2 or more folders in path (e.g. /account/history/).
RE: this line: RewriteCond %{REQUEST_URI} !/(images|js|css)$.
You said you want "exclude any files that contain images|js|css in their uri". Unfortunately the above pattern work differently -- it will match /something/css but will not match /css/something or /something/file.css.
If you want to match images|js|css ANYWHERE in URL straight after a slash, then remove $.

Rewrite rules confused

I am struggling to achieve this simple thing...
I have some static pages which should be like
www.domain.com/profile etc..
The problem is how to write the rewrite rules in order to ..
There would be some fixed rewrites
like /home
I want every file that exists not to be rewritten
www.domain.com/test.php should go to
test.php
Lastly if it is not found i want it to be redirected to static.php?_.....
RewriteRule ^/home/?$ /index.php?__i18n_language=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/([^/]+)/?$ /static.php?__i18n_language=$1
This works ok but if i type index.php or test.php or even the mach from other redirection it gets me in static.php...
Please help!
According to your description you can use these rules:
# stop rewriting process if request can be mapped onto existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteRule ^ - [L]
# rewrite known paths /home, /foo, /bar, etc.
RewriteRule ^/(home|foo|bar|…)$ /index.php [L]
# rewrite any other path
RewriteRule ^ /static.php [L]
I haven't used this in a long time, but it's something I found, that should help. It is part of an old script that generates .httaccess files for redirecting from /usr/share/doc only when the doc isn't found:
The rule is "Check, and if the target url exists, then leave":
RewriteEngine On
RewriteBase /doc/User_Documents
### If the directory already exists, then leave
### We're just redirecting request when the directory exists but has been renamed.
RewriteCond %{REQUEST_FILENAME} User_Documents/([^/]+-[0-9][^/]*)
RewriteCond $PWD/%1 -d
RewriteRule .* - [L]
It's the [L] that means leave if one of the conditions is matched. In the old script, there are hundreds of generated rules (after [L]) that are skipped, because one of the conditions matched. In your case you would skip the rest of the rules when the target %{REQUEST_FILENAME} is found.
So, I suggest, before the redirection rule:
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]

Resources