Rewrite URL regex: different filenames to same URL structure - regex

e.g. from
A: www.example.com/food.php
B: www.example.com/food2.php?type=bacon
C: www.example.com/food2.php?type=tomato
It's easy to get:
A: www.example.com/food
B: www.example.com/food2/bacon
C: www.example.com/food2/tomato
But how about getting the following from my original URL structure?
B: www.example.com/food/bacon
C: www.example.com/food/tomato
Do I need to keep the same filename to get the desired URLs or is there some regex to do it without causing problems?
I don't have much experience with regex, just simple rewrites from templates.

Use this:
RewriteEngine On
RewriteRule ^food/([^/]*)$ /food2.php?type=$1 [L]
This will leave you with the URLS:
www.example.com/food/bacon
www.example.com/food/tomato
Make sure you clear your cache before testing this.

The rewrite config should look like:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.example.com)$
RewriteCond "%{QUERY_STRING}" "\/food"
RewriteRule "(food)\/([a-z]+)$" "$12\.php\?type=$2"
Please refer to mod_rewrite documentation for more details
Please don't be confused with "$12" backreference -- mod_rewrite only offers one-digit references from $1 to $9 (and $0 for a whole matched string), hence it is reference to first (group) followed with "2".

Do you want this? I used vim's substitution command.

Related

How to write expression to grab all after an expression and then rewrite in htaccess

I'm new to the rewriting of urls and regex in general. I'm trying to rewrite a URL to make it a 'pretty url'
The original URL was
/localhost/house/category.php?cat=lounge&page=1
I want the new url to look like this:
/localhost/house/category?lounge&page=1
(like I say, I'm new so not trying to take it too far at the moment)
the closest I've managed to get it to is this:
RewriteRule ^category/(.*)$ ./category.php?cat=$1 [NC,L]
but that copies the whole URL and creates:
/localhost/house/category/house/category/lounge&page=1
I'm sure, there must be an easy way to say copy all after that expression, but I haven't managed to get there yet.
I will try to help you:
You probably have already, but try a mod rewrite generator and htaccess tester.
From this answer: The query (everything after the ?) is not part of the URL path and cannot be passed through or processed by RewriteRule directive without using [QSA].
I propose using RewriteCond and using %1 instead of $1 for query string matches as opposed to doing it all in RewriteRule.
For your solution, try:
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^house/category$ house/category.php?cat=%1 [NC,L]
This will insert the .php and cat= while retaining the &page=
Anticipating your next step, the below mod rewrite may help get started in converting
http://localhost/house/category/lounge/1
to
http://localhost/house/category.php?cat=lounge&page=1
Only RewriteRule necessary here, no query string:
RewriteRule ^house/category/([^/]*)/([0-9]*)/?$ house/category.php?cat=$1&page=$2 [NC,L]
Use regex101 for more help and detailed description on what these regexes do.
If it still not working, continue to make the regex more lenient until it matches correctly:
Try to remove the ^ in RewriteRule so it becomes
RewriteRule category$ category.php?cat=%1 [NC,L]
Then it will match that page at any directory level. Then add back in house/ and add /? wherever an optional leading/trailing slash may cause a problem, etc.
Thanks for all your suggestions, I took it back to this
RewriteRule category/([^/])/([0-9])/?$ category.php?cat=$1&page=$2 [NC,L]
which has done the trick, and I'll leave it at this for now.

.htaccess: param url to clean url

I am trying to turn an ugly url with parameters into a nice url. At the moment I have:
http://myasite.com/index.php?reg=uk&area=london&id=16
Which I would like to have like so:
http://myasite.com/uk/london/16
I have tried using this .htaccess:
RewriteEngine On
RewriteRule ^/?$/?$ index.php?reg=$1&area=london&id=$2 [L,QSA]
Which I got from an online generator however when I run the page with /uk/16 in the url it just crashes.
What am I doing wrong?
In reply to Chris's reply below. All of these are optional.
Structure of url is like so:
myasite.com
myasite.com/uk (if set, This will always be text and always 2 chars long)
myasite.com/uk/london (if set, This will always be text, this will be any char length )
myasite.com/uk/london/16 (if set, This will always be integer and any char length)
Your regex is incorrect. Your ^/?$/?$ says the request can have 2 /s only, each is optional. You also aren't using any capture groups so $1 and $2 have no context. Here's a regex that would work for your provided example:
^/(uk)/(\d+)$
If uk can be any 2 lowercase letters you could use:
^/([a-z]{2})/(\d+)$
You can use regex101 to see how your regexs will function.
https://regex101.com/r/VyJE9d/1 (your rule)
https://regex101.com/r/VyJE9d/2
The right side of the page gives explanations.
As a rewrite rule:
RewriteEngine On
RewriteRule ^/([a-z]{2})/(\d+)$ index.php?reg=$1&id=$2 [L,QSA]
All you need to use is this in your .htaccess file:
RewriteEngine On
RewriteRule ^([^/]*)/([^/]*)/([^/]*)$ /index.php?reg=$1&area=$2&id=$3 [L]
This will leave you with your desired URL of: http://myasite.com/uk/london/16. Just make sure you clear your cache before testing this.
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)/([0-9]+)/?$ index.php?reg=$1&id=$2 [L,QSA]
We are rewriting $1/$2/ and $1/$2 to index.php?reg=$1&id=$2

mod_rewrite change a variable content

I am having a little trouble with apache mod_rewrite, I need to be able to modify (append) a variable name to something else depending the regex in another variable in the URL:
https://localhost:85/fight?shoes=baby.firstlove&type=textype&awesome=23481234
By this i mean that if "awesome=" is 234[8,7]1234, shoes=baby.firstlove should become shoes=baby.firstlovefirsttry, OR if awesome=234[1,2]1234, then shoes=baby.firstlove, should become shoes=baby.firstlovesecondtry .
My rewrites rule are something like this (trying to capture awesome=23411234 or awesome=23425678):
RewriteCond %{QUERY_STRING} shoes=(.+)\&awesome=(\b234(1|2)\d{4}\b)
RewriteRule ^(.*)$ http://localhost:85/fight?shoes=baby.firstloveactual&subscriber=%2 [P]
But they are not changing the "shoes=" variable content as expected.
The URL remains the same:
http://localhost:85/fight?shoes=baby.firstlove&type=textype&awesome=23481234
Please what am I doing wrong?
RewriteCond %{QUERY_STRING} shoes=(.*)\&awesome=(\b234(1|2)\d{4}\b)
Your regex does not match your example URL:
https://localhost:85/fight?shoes=baby.firstlove&type=textype&awesome=23481234
You have an 8 where your regex is expecting a 1 or 2. However, if you need to match one of a series of characters then you should use a character class (eg. [12]) rather than a parenthesised/capturing group. Also, I'm not sure what you are trying to do with the word boundaries (ie. \b)? What is the intention of using the P flag? Presumably you need to externally redirect?
But also, your code sample does not seem to match your textual description of the problem?
if "awesome=" is 234[8,7]1234, shoes=baby.firstlove should become shoes=baby.firstlovefirsttry
Try the following (assuming "1234" is the literal string, rather than any 4 digits):
RewriteCond %{QUERY_STRING} shoes=.+&awesome=(234[87]1234)
RewriteRule ^/?fight http://localhost:85/fight?shoes=baby.firstloveactual&subscriber=%1 [R,L]
You've used https in your example URLs, but http in your rewrite?

Rewrite rule regexp

I would like to ask you guys because I have a problem with one my rewrite rules and I can't figure it out how to write the good one.
I have this rule:
RewriteRule ^wp-content/uploads/(.*[^(.js|.swf)])$ authenticate.php?file=$1
What I would like to do is redirect the user to the authenticate.php every time when someone tries to open something in the wp-content uploads dir and I would like to send the filename to the php
For example:
http://domain.tld/wp-content/uploads/2015/11/something.pdf
redirect to authenticate.php?file=something.pdf
But unfortunately my regexp is broken. Could someone help me?
Really thanks for it!
Try with that in your .htaccess:
RewriteCond %{REQUEST_URI} !(?:js|swf)$ [NC]
RewriteRule ^wp-content/uploads/(.+)$ authenticate.php?file=$1 [NC,L]
For http://domain.tld/wp-content/uploads/2015/11/something.pdf the result: http://domain.tld/authenticate.php?file=2015/11/something.pdf
Try using this regex with negative lookaheads:
^.*?wp-content\/uploads\/.*?\.(?!js$|swf$)[^.]+$
The following URL will match the regex:
http://cpsma.ie/wp-content/uploads/2015/09/CPSMA-Newsletter-No-35-Sept-2015-2.pdf
However, a similar URL which ends in .js or .swf will not match. Hence, the following two URLs do not match the regex:
http://domain.tld/wp-content/uploads/2015/10/javascript.js
http://domain.tld/wp-content/uploads/2015/02/shockwavefile.swf
You can test this regex out here:
Regex101

mod_rewrite: match string within URL, which regex to chose?

I would like to use mod_rewrite to capture a string within brackets in my URL and do a redirect.
My URL:
something?var_a=A&var_b=(B)&var_c=C
my .httaccess file with the regex:
RewriteEngine on
RewriteRule ^/?.+var_b=\((.*)\)$ somedir/$1 [R]
I just would like to capture what's in between the round brackets, so my redirect should look something like this: somedir/B
I test my regex at http://htaccess.madewithlove.be/ but I get no match.
I don't know what I am missing here, even if I try much simpler regexes, e.g. .+var_b(.*)$ I get no match. Only if my regex was looking for a pattern at the beginning, I get a match, so for example the regex something(.*)$ works.
What am I missing here?
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)var_b=\((.*?)\)(&|$) [NC]
RewriteRule ^.*$ somedir/%2? [R]
The reason is that RewriteRule does not receive the ?x=y part of the query. The %2 variable refers to the pattern from the last RewriteCond, while $2 would refer to the pattern from this RewriteRule. The ? at the end prevents the query part ?x=y from being automatically appended at the end of the result.
The (^|&) and (&|$) in the pattern guarantee that var_b=(B) is the complete parameter and not a part of it. Without these, the pattern would also match ?xyzvar_b=(B) or ?var_b=(B)xyz. With these, it will only match ?var_b=(B) or ?a=b&var_b=(B)&x=z etc.