.htaccess rule for setting directory rewrite if extension match - .htaccess

At the moment I have
RewriteRule ^olddir/(.*).xls newdir/one/$1.xls
RewriteRule ^olddir/(.*).jpg newdir/one/$1.jpg
At the moment all the file extensions I want to rewrite I put on a separate line.
I'm sure there is a shorter way to do (.xls|.jpg)? this but I lack htaccess skills.

maybe
RewriteRule ^olddir/(.+)\.(jpg|xls)$ newdir/one/$1.$2
or
RewriteRule ^olddir/(.+\.(jpg|xls))$ newdir/one/$1
not sure about the second one as I haven't tried it, but should work... and changed * to + because there probably should be at least one char there and added a \ to the . or else it will match any char
Also, if you need help with the regex that mod_rewrite uses, check out http://httpd.apache.org/docs/current/rewrite/intro.html

Related

htaccess to add ?query=string to specific url

I'm pulling my hair out trying to get a .htaccess rewrite rule to work. I'm sure this should be easy but I just can't get it right!
I need to add ?query=string to a specific URL pattern so:
www.example.com/downloads/file
Becomes:
www.example.com/downloads/file?query=string
The best I can come up with is:
RewriteRule ^downloads/(.*) downloads/$1?query=string
But it's not working. Where am I going wrong?
What you have looks OK, except you might need to include the L flag to prevent further rewritting:
RewriteRule ^downloads/(.*) downloads/$1?query=string [L]
And if this is intended to be an external redirect then you'll need to make the substitution absolute or root-relative and include the R flag:
RewriteRule ^downloads/(.*) /downloads/$1?query=string [R=302,L]

mod_rewrite .htaccess with %20 translate to -

I have been reading about .htaccess files for a couple of hours now and I think I'm starting to get the idea but I still need some help. I found various answers around SO but still unsure how to do this.
As far as I understand you write a rule for each page extension you want to 'prettify', so if you have something.php , anotherpage.php, thispage.php etc and they are expecting(will receive??) arguments, each needs its own rule. Is this correct?
The site I want to change has urls like this,
maindomain.com/sue.php?r=word1%20word2
and at least one page with two arguments
maindomain.com/kevin.php?r=place%20name&c=person%20name
So what I would like to make is
maindomain.com/sue/word1-word2/
maindomain.com/kevin/place-name/person-name/
Keeping this .php page and making it look like the directory. Most of the tutorials I have read deal with how to remove the .php page to which the argument is passed. But I want to keep it.
the problem I am forseeing is that all of the .php?r=parts of the url are the same ie sue.php?r=, kevin.php?r= and the .htaccess decides which URL to change based on the filename and then omits it. If I want to keep the file name will I have to change the ?r=
so that it is individual? I hope this make sense. So far I have this, but I'm sure it won't work.
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([a-zA-Z0-9]+)/$1.php?r=$1
RewriteRule ^([a-zA-Z0-9]+)/$1.php?r=$1&c=$1
And I think I have to add ([^-]*) this in some part or some way so that it detects the %20 part of the URL, but then how do I convert it to -. Also, how are my $_GET functions going to work??
I hope my question makes sense
You're missing a space somewhere in those rules, but I think you've got the right idea in making 2 separate rules. The harder problem is converting all the - to spaces. Let's start with the conversion to GET variables:
# check that the "sue.php" actually exists:
RewriteCond %{REQUEST_URI} ^/([a-zA-Z0-9]+)/([^/]+)/?$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/?$ /$1.php?r=$2 [L,QSA]
RewriteCond %{REQUEST_URI} ^/([a-zA-Z0-9]+)/([^/]+)/([^/]+)/?$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^([a-zA-Z0-9]+)/([^/]+)/([^/]+)/?$ /$1.php?r=$2&c=$3 [L,QSA]
Those will take a URI that looks like /sue/blah/ and:
Extract the sue part
Check that /document_root/sue.php actually exists
rewrite /sue/blah/ to /sue.php?r=blah
Same thing applies to 2 word URI's
Something like /kevin/foo/bar/:
Extract the kevin part
Check that /document_root/kevin.php actually exists
3 rewrite /kevin/foo/bar/ to /kevin.php?r=foo&c=bar
Now, to get rid of the "-" and change them to spaces:
RewriteCond %{QUERY_STRING} ^(.*)(c|r)=([^&]+)-(.*)$
RewriteRule ^(.*)$ /$1?%1%2=%3\ %4 [L]
This looks a little messy but the condition matches the query string, looks for a c= or r= in the query string, matches against a - in the value of a c= or r=, then rewrites the query string to replace the - with a (note that the space gets encoded as a %20). This will remove all the - instances in the values of the GET parameters c and r and replace them with a space.

How to write this .htaccess rewrite rule

I am setting up a MVC style routing system using mod rewrite within an .htaccess file (and some php parsing too.)
I need to be able to direct different URLs to different php files that will be used as controllers. (index.php, admin.php, etc...)
I have found and edited a rewrite rule that does this well by looking at the first word after the first slash:
RewriteCond %{REQUEST_URI} ^/stats(.*)
RewriteRule ^(.*)$ /hello.php/$1 [L]
However, my problem is I want it to rewrite based on the 2nd word, not the first. I want the first word to be a username. So I want this:
http://www.samplesite.com/username/admin to redirect to admin.php
instead of:
http://www.samplesite.com/admin
I think I just need to edit the rewrite rule slightly with a 'anything can be here' type variable, but I'm unsure how to do that.
I guess you can prefix [^/]+/ to match and ignore that username/
RewriteCond %{REQUEST_URI} ^/[^/]+/stats(.*)
RewriteRule ^[^/]+/(.*)$ /hello.php/$1 [L]
then http://www.samplesite.com/username/statsadmin will be redirecte to http://www.samplesite.com/hello.php/statsadmin (or so, I do not know the .htaccess file)
To answer your question, "an anything can be here type variable" would be something like a full-stop . - it means "any character". Also the asterisk * means "zero or more of the preceding character or parenthesized grouped characters".
But I don't think you need that...If your matching url will always end in "admin" then you can use the dollar sign $ to match the end of the string.
Rewrit­eRule admin$ admin.php [R,NC,L]
Rewrites www.anything.at/all/that/ends/in/admin to www.anything.at/admin.php

Mod_Rewrite to /subdirectory and /subdirectory/query

I'm having a difficult time getting into using mod_rewrite. I've been at this for about an hour googling stuff but nothing quite seems to work. What I want to do is change
example.com/species.php into example.com/species
and also
example.com/species.php?name=frog into example.com/species/frog.
Using
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^species/(.*)$ /species.php?name=$1
I can get example.com/species.php?name=frog to display as example.com/species/frog, and with
RewriteRule ^species/ /species.php
I can get example.com/species.php to display as example.com/species/, but I can't get both of them to work at the same time.
Also, example.com/species with no trailing slash always comes up as a 404.
I've considered just making a /species/ directory to catch any problems but I'd rather just have a few rules for one species.php file. Any help would gladly be appreciated!
Edit (because I can't answer my own question for 8 more hours):
I seem to have fixed both of my problems. I changed my .htaccess to:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^species/(.*)$ /species.php?name=$1
RewriteRule ^species/?$ /species.php
The second RewriteRule successfully redirects example.com/species to example.com/species.php while leaving the other RewriteRule working at the same time.
However, if I typed in example.com/species/ with a trailing slash, it was being read as example.com/species.php?name= and would throw an error because no name was submitted, so I just added
if(isset($_GET['name']) && empty($_GET['name'])) {header('location: http://example.com/species');}
so that if I used example.com/species/ it would redirect to /species and work as desired.
If you change the * (match zero or more) to a + (match one or more) in your first RewriteRule then you should stop seeing species.php?name= if a trailing slash is used.
This is because the + will require that something appears after the slash, otherwise the rule will not match. Then your second RewriteRule will match because it ends with an optional slash, but will not add the name= query string to the target URL.
You may also want to add the [L] flag (last) after the first rule, because you don't need the second rule to execute if the first rule matches. (Note that this will not stop the RewriteCond and RewriteRule tests being run on the resulting redirect URL, which will have to go through the .htaccess file just like any other request.)
See the Reference Documentation for mod_rewrite in Apache 2.4 (or see the docs for the version of Apache you're actually using).

.htaccess rewritecond rewrite case level 2 folder=info

I wanted to set .htaccess to rewrite:
example.com/bla/info/
to
example.com/info/index.php?q=bla
example.com/bla/info/txt/
to
example.com/info/index.php?q=bla&t=txt
I wanted the browser still to display:
example.com/bla/info/txt/
I didn't want rewrite in the level 2 rewrites, like:
example.com/bla/xxx/
or
example.com/ccc/zzz/aaa/
but
example.com/silly/info/
would work as well as
example.com/strange/info/mytxt/
Did this make sense?
Any help?
If you start your pattern with ^ and end it with $, the rule will only apply if the whole string matches.
RewriteRule ^/bla/info/$ /info/index.php?q=bla
RewriteRule ^/bla/info/txt/$ /info/index.php?q=bla&t=txt
If you use do not use the [R] option, the URL shown in the browser will be whatever the user entered.
Are you trying to make this general-purpose? If so, you can use regex-type matching and variable substitution. To make 'bla' match any string up to the next slash (/), use
([^/]+)
in your pattern and reference it with $1 in your substitution.
RewriteRule ^/([^/]+)/info/$ /info/index.php?q=$1
RewriteRule ^/([^/]+)/info/([^/]+)/$ /info/index.php?q=$1&t=$2
I recommend the Apache web pages about mod_rewrite for more information.
[Edit. Fixed the rules to not include the host name in the pattern, as the original poster figured out.]
--
bmb
you got me in the right track.
i ended up with something like this:
RewriteRule ^([^/\.]+)/info/?$ example/info/index.php?q=$1 [L]
thanks a lot

Resources