I'm trying to do a mod_rewrite. The given URLS should look like this:
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
The problem with that is, that it also rewrites things like javascript files matching the pattern, because they are in some subdirectories.
So how do I achieve, that mod-rewrite only accepts URLs like "foo/bar" and no URL like "fizz/buzz/jq.js"?
if you want
test/foo/dir/test44.j4s
to
dir test44.j4s
RewriteRule ^foo/(.*)/(.*) index.php?dir=$1&file=$2 [L]
You may ensure to not match existing files or directories by using the following rewrite conditions:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
See http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond for the full power of RewriteCond.
I often use
RewriteCond $1 !^favicon.ico|^css|^js
to exclude favicon, and the css and js directories from beeing rewritten.
The following should exclude Javascript and CSS files:
RewriteCond $1 !\.css$|\.js$
Just do this thing: if the request doesn't end with a known extension, then apply the rewrite rule:
RewriteCond %{REQUEST_URI} (.*)(\.(css|js|pdf|jpg|jpeg|gif|png|ico))
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
Or do it the opposite side: if the request starts with a known extension, then stops, otherwise keep on applying the rest:
RewriteRule (.*)(\.(css|js|htc|pdf|jpg|jpeg|gif|png|ico)){1}$ $1$2 [QSA,L]
RewriteRule ^([a-zA-Z0-9\-)/([a-zA-Z0-9\-)$ index.php?anum=$1&aname=$2
Both solutions should work.
Tell me which one did ;)
Olivier
Related
I would like to use RewriteRules in .htaccess to achieve particular url rewriting, but can't get it right, can somoene help?
I'm trying to rewrite the path (everything between the first and last /) into one query string, and the filename into another
e.g:
http://domain.com/users/admins/testuser.html
rewrites to
http://domain.com/index.php?path=users/admins&file=testuser
and
http://domain.com/home.html
rewrites to
http://domain.com/index.php?path=&file=home
and
http://domain.com/settings/account.html
rewrites to
http://domain.com/index.php?path=settings&file=account
EDIT:
Many thanks to the first two answerers, they are both good answers however I can't figure which one to use!
Is there any benefit to parsing the path from php itself, or vice-versa?
Try this rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((.+)/)?([^/]+)\.[^/.]+$ index.php?path=$2&file=$3
But it may be easier to use PHP’s parse_url and pathinfo for that:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$pathinfo = pathinfo(substr($_SERVER['REQUEST_URI_PATH'], 1));
var_dump($pathinfo);
Now you just need this rule to rewrite the request to the index.php:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^index.php$ index.php
Try this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((\w+/)*)(\w+)\.html$ index.php?path=$1&file=$3
Using a .htaccess rewrite rule, I need to add "?q=" before the path on any URL's containing the word "imagecache"
Therefore, if the URL is:
http://mysite.com/sites/default/files/imagecache/myimage.jpg
...then it will really try:
http://mysite.com/?q=sites/default/files/imagecache/myimage.jpg
But that will ONLY happen if the URL contains "imagecache." Otherwise, it does no rewriting.
Also, this will only happen if /sites/default/files/imagecache/myimage.jpg isn't already an existing image file. I believe I can do that using:
RewriteCond %{REQUEST_FILENAME} !-f
...right? It's just the first part that I can't figure out.
Something like this?:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*imagecache.*)$ /?q=$1 [L,QSA]
RewriteRule ^mysite.com/(.*)/imagecache/(.*)$ mysite.com/?q=$1/imagecache/$2
I just setup a subdomain with the following RewriteCond:
RewriteCond $1 !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?([^/]+)$ search.php?q=$1 [L,NS]
I'm using the same rewrite condition on my main domain and it works perfectly. However, when I set it up on the subdomain, it simply outputs "index.php" when going to http://sub.domain.com
Every page on the subdomain outputs the page name in the body instead of processing the code, except for the search page, which appears to be working correctly.
What can I do to correct this issue?
I haven't played with your exact regex with mod_rewrite, but if I was looking at writing that regex in another engine, I would have to escape the slash. Also, given that $ is used to indicate a back reference, would that need escaping too (would your $ symbols in the regex be necessary as there is likely to be more text in the URI and it is not matched at the end of a string)?
I would try
RewriteCond $1 !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?([^\/]+)$ search.php?q=$1 [L,NS]
One other thing. Normally $ at the end of a regex means "only match if this is the end of the string". So from that, if RewriteCond is matching on ^search.php$ but the URL is search.php?q=... then I would think that this wouldn't match because search.php is not the end of the string. So that would look like the following (assuming you don't need to change anything else from your original).
RewriteCond $1 !^search.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?([^/]+)$ search.php?q=$1 [L,NS]
In the main config the path always begins with / and you need an absolute path:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/([^/]+)$ %{DOCUMENT_ROOT}/search.php?q=$1 [L]
In an .htaccess you need a RewriteBase which is stripped from the url (no / in the Rule now) and the path is relative.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !^search.php$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)$ search.php?q=$1 [L]
Several things come to mind here:
I have a few suggestions/comments/gotchas. Hopefully one of them is useful to you:
Make sure search.php isn't just echoing out its $_GET parameters. While this sounds obvious in retrospect, it's one of the more overlooked solutions.
RewriteRule works slightly differently when you specify it in a server configuration file than if you specify it in an .htaccess. Specifically, ^/ is wrong in a server config version as the entire URL is used (http://sub.domain.com/blah).
Make sure no other rewrite rules are being processed for this subdomain first, either in the main httpd.conf / apache2.conf or .htaccess.
Make sure RewriteEngine On appears in your configuration, as it is activated per-VirtualHost.
The NS flag will ignore redirects done using a relative Redirect or relative RewriteRule.
It sounds like the pattern '^/?([^/]+)$' may not be matching at all.
I'd activate RewriteLog, crank RewriteLogLevel to level 3 or above, and see if your pattern is matching at all. If not, start with a simpler pattern, and then work your way to a more complex pattern.
Or, something else is matching the pattern, so the request never gets to 'RewriteRule ^/?([^/]+)$' at all. You will see this in the RewriteLog.
I believe I recently had a problem where '^/' didn't match in certain cases on a Virtual Host. But '/' worked. The folks in the #httpd on Freenode.org helped me. If I can find this in my notes, I'll post it here.
How would I rewrite script.php?id=3295 to script/3295??
and Im also wondering if someone could explain what these 3 RewriteConds does:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
Thank you very much
As I rather think that you want to rewrite requests of /script/3295 to /script.php?id=3295 and not the other way round, try this:
RewriteRule ^/script/([0-9]+)$ /script.php?id=$1
But if you really want to rewrite script.php?id=3295 to script/3295, try this:
RewriteCond %{QUERY_STRING} ^(([^&]*&)*)id=([0-9]+)&?([^&].*)?$
RewriteRule ^/script\.php$ /script/%3?%1%4
And if you want to use that rule in a .htaccess file, remove the leading slash from the pattern.
To your second question: The RewriteCond directives test if the requested URI cannot be mapped to an existing regular file (!-f), not to an existing directory (!-d) and not to an existing symbolic link (!-l).
RewriteRule ^/sctipt/(.*) /script.php?id=$1
For your first question, try:
RewriteRule ^script.php?id=(.*)$ /script/$1
For your second question, RewriteCond are conditions applied to the next RewriteRule. So if you see three RewriteCond like that all in a row, they all apply to only the next rule. The rule is only checked if all of those conditions match. In this particular case, it is checking the requested filename to make sure that it is not a file (!-f), not a directory (!-d) and not a symbolic link (!-l). If all of these conditions are true, mod_rewrite will process the next RewriteRule.
How can you use ModRewrite to check if a cache file exists, and if it does, rewrite to the cache file and otherwise rewrite to a dynamic file.
For example I have the following folder structure:
pages.php
cache/
pages/
1.html
2.html
textToo.html
etc.
How would you setup the RewriteRules for this so request can be send like this:
example.com/pages/1
And if the cache file exists rewrite tot the cache file, and if the cache file does not exists, rewrite to pages.php?p=1
It should be something like this: (note that this does not work, otherwise I would not have asked this)
RewriteRule ^pages/([^/\.]+) cache/pages/$1.html [NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule cache/pages/([^/\.]+).html pages.php?p=$1 [NC,QSA,L]
I can off coarse do this using PHP but I thought it had to be possible using mod_rewrite.
RewriteRule ^pages/([^/\.]+) cache/pages/$1.html [NC,QSA]
# At this point, we would have already re-written pages/4 to cache/pages/4.html
RewriteCond %{REQUEST_FILENAME} !-f
# If the above RewriteCond succeeded, we don't have a cache, so rewrite to
# the pages.php URI, otherwise we fall off the end and go with the
# cache/pages/4.html
RewriteRule ^cache/pages/([^/\.]+).html pages.php?p=$1 [NC,QSA,L]
Turning off MultiViews is crucial (if you have them enabled) as well.
Options -MultiViews
Otherwise the initial request (/pages/...) will get automatically converted to /pages.php before mod_rewrite kicks in. You can also just rename pages.php to something else (and update the last rewrite rule as well) to avoid the MultiViews conflict.
Edit: I initially included RewriteCond ... !-d but it is extraneous.
Another approach would be to first look if there is a chached representation available:
RewriteCond %{DOCUMENT_ROOT}/cache/$0 -f
RewriteRule ^pages/[^/\.]+$ cache/$0.html [L,QSA]
RewriteRule ^pages/([^/\.]+)$ pages.php?p=$1 [L,QSA]
To generalize the question: insert this above the rule that should not be matched if the file exists.
RewriteCond %{REQUEST_FILENAME} !-f
Sean Bright's answer provides a nice worked example for the caching question, but this line works more broadly. In my case, I have a link shortener where people can choose custom URLs and I didn't want it to be able to override existing files such as favicon.ico. Adding this line before the rewriterule fixed that issue.