I'm trying to rewrite URLs as follows:
www.example.com/module-name(/) => handler.php?module=module-name
www.example.com/module-name/list/of/arguments(/) => handler.php?module=module-name&args=list/of/arguments (which I explode later in the script)
If module-name is missing or not allowed, it loads the home page of the website. No problems here.The problem is that mod_rewrite isn't working as it should. I wrote these rewrite rules...
RewriteEngine On
RewriteRule ^([^/]*)/?$ handler.php?module=$1
RewriteRule ^([^/]+)/(.+)/?$ handler.php?module=$1&args=$2
...but instead of passing module-name as module to the handler, the rewrite engine passes the name of the script itself, handler.php. I tried with different regex in the last two days, but the result is always the same. I don't know what to do anymore!
The rewrite rules are inside an .htaccess, placed in the document root (together with handler.php), and I'm running xampp on an Ubuntu 11.10 64-bit machine.
Thanks in advance!
Yep, after rewrite occurs, it goes to next cycle instead of existing immediately as you would expect.
You need to alter your rule (or add separate condition) to ignore requests to handler.php file. For example:
RewriteRule ^(?!handler\.php)([^/]*)/?$ handler.php?module=$1 [L]
RewriteRule ^(?!handler\.php)([^/]+)/(.+)/?$ handler.php?module=$1&args=$2 [L]
or with extra separate condition:
RewriteCond %{REQUEST_URI} !/handler\.php$
RewriteRule ^([^/]*)/?$ handler.php?module=$1 [L]
RewriteCond %{REQUEST_URI} !/handler\.php$
RewriteRule ^([^/]+)/(.+)/?$ handler.php?module=$1&args=$2 [L]
or even like that:
# do not touch requests to handler.php
RewriteRule ^handler\.php$ - [L]
# our rewrite rules
RewriteRule ^([^/]*)/?$ handler.php?module=$1 [L]
RewriteRule ^([^/]+)/(.+)/?$ handler.php?module=$1&args=$2 [L]
You can also go even this way (it really depends on your rewriting logic)
# do not do anything for requests to existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
# our rewrite rules
RewriteRule ^([^/]*)/?$ handler.php?module=$1 [L]
RewriteRule ^([^/]+)/(.+)/?$ handler.php?module=$1&args=$2 [L]
A problem could be that existing file-names get rewritten as well. To avoid that, you can add:
RewriteCond %{REQUEST_FILENAME} !-f # ignore existing files
RewriteCond %{REQUEST_FILENAME} !-d # ignore existing directories
So for you it would be:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f # ignore existing files
RewriteCond %{REQUEST_FILENAME} !-d # ignore existing directories
RewriteRule ^([^/]*)/?$ handler.php?module=$1
RewriteCond %{REQUEST_FILENAME} !-f # ignore existing files
RewriteCond %{REQUEST_FILENAME} !-d # ignore existing directories
RewriteRule ^([^/]+)/(.+)/?$ handler.php?module=$1&args=$2
Related
I have all of my customers sites in a directory on my subdomain:
customers.example.com/sites/customer_name
I want to rewrite the url so my customers only need to write
customers.example.com/customer_name
I have tried some different htacces scripts but none of them works. And one of them gives me a error 500 internal server error, so my mod_rewrite is active
Here is my current .htaccess file:
RewriteEngine On
RewriteRule ^sites/(css|js|img)/(.*)?$ /$1/$2 [L,QSA,R=301]
RewriteRule ^(.*)$ /sites/$1/ [QSA,L]
Since the rewrite engine loops, this pattern ^(.*)$ will blindly match everything, including your rule's target: /sites/something. It'll continue to append /sites/ to the front of the URI until you end up with something like /sites/sites/sites/sites/sites/sites/sites/ etc.
You need to add some conditions to prevent the looping, something like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /sites/$1/ [L]
or
RewriteCond %{REQUEST_URI} !^/sites/
RewriteRule ^(.*)$ /sites/$1/ [L]
or
RewriteCond %{DOCUMENT_ROOT}/sites%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}/sites%{REQUEST_URI} -d
RewriteRule ^(.*)$ /sites/$1/ [L]
This should work… If understand your end goal correctly. But unclear if you want the content accessible from customers.example.com/sites/customer_name and customers.example.com/customer_name at the same time:
RewriteEngine on
RewriteRule ^/sites/(.*)$ http://customers.example.com/$1 [L,R=301]
I have the following .htaccess file in a subdirectory of a site which allows me to route all URLs to index.php where I can parse them.
However, it's not allowing the standard files that I need for the website, e.g. css, javascript, pngs, etc.
What do I need to change (I assume in the fourth line) to allow these files so they don't get routed to index.php?
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|public|css|js|png|jpg|gif|robots\.txt)
RewriteRule ^(.*)$ index.php/params=$1 [L,QSA]
ErrorDocument 404 /index.php
Something I noticed. You're using the forward slash instead of a question mark... the params redirect would normally look like this:
RewriteRule ^(.*)$ index.php?params=$1 [L,QSA]
This should work by itself since any of those files *should* be real files.
ErrorDocument 404 /index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?params=$1 [L,QSA]
To have the site ignore specific extensions you can add a condition to ignore case and only check the end of the filenames in the request:
RewriteEngine On
RewriteCond %{REQUEST_URI} !(\.css|\.js|\.png|\.jpg|\.gif|robots\.txt)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?params=$1 [L,QSA]
If you're trying to ignore a folder then you could add:
RewriteEngine On
RewriteCond %{REQUEST_URI} !(public|css)
RewriteCond %{REQUEST_URI} !(\.css|\.js|\.png|\.jpg|\.gif|robots\.txt)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?params=$1 [L,QSA]
The easiest is to ignore them explicitly early in your rules:
RewriteRule \.(css|js|png|jpg|gif)$ - [L]
RewriteRule ^(index\.php|robots\.txt)$ - [L]
This avoid carrying them around all over the place with RewriteCond.
At your option, check that the file exists prior to doing so:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule \.(css|js|png|jpg|gif)$ - [L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(index\.php|robots\.txt)$ - [L]
(Note that the file check generates an extra disk access.)
You have the right idea, tweaking the fourth line.
The ^ is saying the various matching strings must be at the beginning of the line. If you don't care where any of these appear in the file, you can just remove the ^. That will avoid rewriting *.css, *.js, etc.; but will also not rewrite publicideas.html.
If you want to limit to just the suffixes, try this:
RewriteCond $1 !^(index\.php|public|.*\.css|.*\.js|.*\.png|.*\.jpg|.*\.gif|robots\.txt)$
This says to match anything at the beginning, then a ., then the suffix. The $ says match these at the end (nothing following).
I'm not sure about the public, so I left it (which means exactly public, with nothing else - probably not what you meant, but you can add a * before or after, or both).
RewriteCond %{REQUEST_FILENAME} !-f alone should be enough.
Another option is t exclude specific files from the rewrite.
From the TYPO3 packages:
# Stop rewrite processing, if we are in the typo3/ directory.
# For httpd.conf, use this line instead of the next one:
# RewriteRule ^/TYPO3root/(typo3/|t3lib/|fileadmin/|typo3conf/|typo3temp/|uploads/|favicon\.ico) - [L]
RewriteRule ^(typo3/|t3lib/|fileadmin/|typo3conf/|typo3temp/|uploads/|favicon\.ico) - [L]
This rule should appear before your actual rewrite. It should be
RewriteRule ^(public/|*\.css|*\.js|*\.png|*\.jpg|*\.gif|robots\.txt) - [L]
in your case.
I'm running in to a mod_rewrite issue where the second rule in my .htaccess file is overriding the first. The .htaccess file in question looks like the one below:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /path/appname
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule /api/v1/(.*)$ api/v1/index.php?rquest=$1 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
</IfModule>
The issue that I'm seeing is this:
If I go directly to http://example.com/path/appname/api/v1/valid/endpoint the first RewriteRule triggers correctly and I get the result back from the API.
However, say I visit http://example.com/path/appname/app - a page which has been rewritten according to the second RewriteRule. This page makes AJAX requests to the api/v1 page. Those requests are instead directed through the second RewriteRule and send to my base index.php page.
I'm confused on how this could be, as my understanding is that the [L] flag prevents any further rules from being run once it matches and thus once any request that has 'api/v1' in it should catch that and stop checking for any further matches. What do I need to change in order for this to work correctly?
Thanks!
You should exclude the segment path for the previous rule-set, so it is not processed again. Like this:
# Don't redirect/map when folders or files exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Exclude the previous path
RewriteCond %{REQUEST_URI} !api/v1/? [NC]
# Prevent loops
RewriteCond %{REQUEST_URI} !index\.php [NC]
RewriteRule . index.php [L]
</IfModule>
Replace the last 4 lines in you question with the above lines.
This is driving me mad. I'm trying to use .htaccess to redirect a subfolder (that doesn't exist) to the index page, using the subfolder name as the variable. ie:
http://www.website.com/john/
redirects to:
http://www.website.com/index.php?name=john
I've tried this (and various others) with no luck:
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^(.*)$ index.php?name=$1
Here is an example, how you can do this:
# turn mod_rewrite engine on
RewriteEngine On
# rewrite a physical existing file or folder
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
# allow things that are certainly necessary
RewriteCond %{REQUEST_URI} "/layout/" [OR]
RewriteCond %{REQUEST_URI} "/javascript/"
# rewrite rules
RewriteRule .* - [L]
RewriteRule (.*) index.php?_route=$1 [QSA]
This one also denies access to folders you don't want to have public.
Try this one:
RewriteRule ^([^/]*)/$ /?name=$1 [L]
RewriteRule ^([^.]*)$ /index.php?name=$1 [L,QSA]
2 days of struggling and about a pound less of hair, I figure it's about time I ask for some help. I've recently migrated my project to a main sub-directory so that the structure is as follows:
-application/
-index.php
-signup/
-index.php
-signup_set.php
-css/
-js/
I've been trying to get mod_rewrite to do my work for me to exclude "application/" from all the urls. Here is where I got in my root .htaccess:
RewriteEngine On
#first round through, prepend 'application/' to request
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !^application
RewriteRule ^(.*)$ application/$1 [L]
#second round through, if the new url is not directory or file, append .php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ $1.php [L]
I may have a terrible understanding of regex/mod_rewrite, but this actually seems to partly work. Partly. The weird part about this is that when I route to a "pretty url" (e.g. www/signup) the url in the top bar is physically rewritten to include the "application/" (e.g. www/application/signup). So somehow this "silent" rewriting process is getting pretty loud...Any suggestions? I realize I could change my root directory but that would require rewriting of code referencing css/js files. I'm more curious than anything, just trying my hand at some htaccess. Any help would be appreciated! Thanks StackOverflow, you rock.
P.S. I'm running Apache on Windows 7 and using a virtual host (in case any of that is relevant)
The rules below work for me running Apache on Windows 7 using a virtual host. All I changed was the second RewriteCond.
RewriteEngine On
# Append trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(?:\.\w+|/)$
RewriteRule ^(.*)$ /$1/ [L]
# First round through, prepend 'application/' to request
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/application
RewriteRule ^(.*)$ application/$1 [L]
# Second round through, if the new url is not directory or file, append .php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.\w+$
RewriteRule ^(.*)/$ $1.php [L]