Redirect with RewriteRule - regex

How to redirect with RewriteRule?
from:
www.example.com/ca/blog/something
To:
www.example.com/ca/test.php?url=something
Of course "something" could change. The other parts of the url will always be the same.
In the end, I want to use test.php with a parameter set:
$url = $_GET['url'];
echo $url;
I have deleted all other rules in the .htaccess to be sure there is no conflict. Please explain the solution. I am very new to regex.

RewriteEngine On
RewriteRule ca/blog/(.*)$ /ca/test.php?url=$1 [L,R=301]
It captures everything after /blog/ and gives it as an parameter to test.php. The period (.) means "every character", the asterisk (*) means "as many as I can possibly find (or none)", the brackets will capture the result. If you want to make sure that the url parameter in test.php is not empty, you might want to use a plus (+) like so:
RewriteRule ca/blog/(.+)$ /ca/test.php?url=$1 [L,R=301]
This means "as many characters but there has to be at least one". Additionally, there is a nice online tester for this.

Try:
RewriteEngine On
RewriteBase /
# at the entrance of RewriteRule: ca/blog/something
RewriteRule ^ca/blog/(.*)$ ca/test.php?url=$1 [QSA]
# after transformation: "ca/blog/something" -> "ca/test.php?url=something"

Related

.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

.htaccess replace "/" with "_"

This is my current htaccess
<IfModule mod_rewrite.c>
# turn on rewrite engine
RewriteEngine on
# if request is a directory, make sure it ends with a slash
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*/[^/]+)$ $1/
# if not rewritten before, AND requested file is wikka.php
# turn request into a query for a default (unspecified) page
RewriteCond %{QUERY_STRING} !wakka=
RewriteCond %{REQUEST_FILENAME} wikka.php
RewriteRule ^(.*)$ wikka.php?wakka= [QSA,L]
# if not rewritten before, AND requested file is a page name
# turn request into a query for that page name for wikka.php
RewriteRule ^(.*)$ wikka.php?wakka=$1 [QSA,L]
</IfModule>
My current url structure is
www.domain.com/site/pool/Page_Example_Test
www.domain.com/site/pool/Page_Example_Test/edit
www.domain.com/site/pool/Page_Example_Test/edit?id=1
www.domain.com/site/pool/Page_Example_Test/history
www.domain.com/site/pool/Page_Number_Room
www.domain.com/site/pool/Page_Number_Room/edit
How Is it possible to access them like this
www.domain.com/site/pool/Page/Example/Test
www.domain.com/site/pool/Page/Example/Test/edit
www.domain.com/site/pool/Page/Example/Test/edit?id=1
www.domain.com/site/pool/Page/Example/Test/history
www.domain.com/site/pool/Page/Number/Room
www.domain.com/site/pool/Page/Number/Room/edit
having the htaccess change only those "/" for "_"
There is only /history and /edit finishing the url name nothing more, the normal is without /edit or /history.
If there are between one and five pieces in the page name, such as
Page
Page/Page
Page/Page/Page
Page/Page/Page/Page
Page/Page/Page/Page/Page
and every element starts with a capital letter and every other part of the url is only lowercase, then you can accomplish this with four replacements (the one-piece-only one needs no replacement). For example, for three pieces:
Find what: ([A-Z][a-z]+)\/([A-Z][a-z]+)\/([A-Z][a-z]+)(\/)?
Replace with: $1_$2_$3$4
You can try it here (although I don't understand why it's only replacing with spaces in every line but the last).
Notes:
Each part (...) is captured
The final slash \/? is optional, and is the slash before the potential "edit" or "history".
In some regex flavors, you don't need to escape the slash /, but it's safer to do so: \/.
Each $[number] is a capture group reference
WARNING! These replacements must be done from longest to shortest: five pieces, then four, then three, then two. Otherwise, you'll seriously mess things up.
All the links in this answer come from the Stack Overflow Regular Expressions FAQ. Please consider bookmarking it for future reference. In particular, see the list of online regex testers in the bottom section, so you can try things out yourself.
Place this code in /site/pool/.htaccess:
RewriteEngine On
RewriteBase /site/pool/
RewriteRule "^(Page)/([^/]+)/([^/]+/.*)$" /$1/$2_$3 [L]
RewriteRule "^(Page)/([^/]+)/([^/]+)$" /$1/$2_$3 [L]

Understanding RegEx - SEO Duplication on last term

i have a problem with duplicate pages for SEO on a website i'm trying to fix. www.example.com/category/c1234 loads just the same as www.example.com/category/c1234garbage
I've been reading online and testing the code and so far I narrowed it down to a possible regex problem. I have the following lines
# url rewrites
RewriteCond %{REQUEST_URI} ^/index\.cfm/.+ [NC]
RewriteRule ^/index.cfm/(([^/]+)/?([^/]+)?)/?(.*)? /index.cfm/$4?$2=$3 [NS,NC,QSA,N,E=SESDONE:true]
I added an R in the rule so I could see if it was passing through there and it is and after it passes that the garbage at the end disappears.
Can someone help me understand this and figure out a way to fix it so when you go to www.example.com/category/c1234garbage it redirects to www.example.com/category/c1234
I've been searching online for quite a while now and thought it might be time to post here since I can't seem to find a solution. I'm reading "Mastering Regular Expressions" but it might take take a while for me to find the answers I'm looking for.
I appreciate any help you can give me. Thank you.
EDIT: This is what i have before that
RewriteEngine On
Rewritebase /
# remove trailing index.cfm
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^index.cfm(\?)?$ / [R=301,L]
# remove trailing slash
RewriteCond %{QUERY_STRING} ^$
RewriteRule (.*)/$ /$1 [R=301,L]
# Remove trailing ?
RewriteCond %{THE_REQUEST} \?\ HTTP [NC]
RewriteRule ^/?(index\.cfm)? /? [R=301,L]
# SEF URLs
SetEnv SEF_REQUEST false
RewriteRule ^[a-z\d\-]+/[a-z]\d+/? /index.cfm/$0 [NC,PT,QSA,E=SEF_REQUEST:true]
RequestHeader add SEF-Request %{SEF_REQUEST}e
RewriteCond %{HTTP:SEF_REQUES} ^true$ [NC]
RewriteRule . - [L]
EDIT: I was reading the htaccess again and found this that I don't understand but it might have some connection. It's located at the bottom of the file.
# lowercase the hostname, and set the TLD name to an enviroment variable
RewriteCond ${lowercase:%{SERVER_NAME}|NONE} ^(.+)$
RewriteCond %1 ^[a-z0-9.-]*?[.]{0,1}([a-z0-9-]*?\.[a-z.]{2,6})$
RewriteRule .? - [E=TLDName:%1]
From your description and your code, it sounds like this is the transformation that's happening here:
www.example.com/category/c1234garbage
↓
www.example.com/index.cfm?category=c1234garbage
So the problem, I think, is not your rewriting rules. The problem is how you're handling querystring parameters on the server side. If you have an actual page called index.cfm that's interpreting those parameters, you should tweak the code behind that page to validate them and redirect to /category/c1234 where appropriate.
I think the code in index.cfm is looking at the parameter, checking to see if it starts with something recognizable, and going from there. You need to make it more strict.
Alternatively, you could add another .htaccess rule to parse the c1234garbage part and decide which part is valid, and which part (if any) is garbage. I can't give you a regex for that, though, since I don't know the rules for a valid input in your application.
Edit:
I think I found the problem. This part here:
RewriteRule ^[a-z\d\-]+/[a-z]\d+/? /index.cfm/$0 [NC,PT,QSA,E=SEF_REQUEST:true]
You specify the beginning of the relative URL with ^, but you don't specify that you want it to match all the way to the end. So I think what's happening is that it's taking the part of the string that matches, throwing out everything else, and appending it to /index.cfm/. So it takes only the /category/c1234 part from /category/c1234garbage, because that's the part that matches ^[a-z\d\-]+/[a-z]\d+/?.
You can probably fix this with just a word break:
RewriteRule ^[a-z\d\-]+/[a-z]\d+\b/? /index.cfm/$0 [NC,PT,QSA,E=SEF_REQUEST:true]
If that doesn't work, I'm afraid we've reached the end of my htaccess knowledge. I'm more of a regex guy.
Just BTW, this still seems a little awkward. If I understand this right, part of the URL will still get thrown out if it doeesn't fit your exact pattern. E.g. /category/c1234?abc=123 will lose its querystring parameters. You might want to redesign how your rules are set up.
I partially solved the problem. I added
# Remove garbage from after category
RewriteCond %{REQUEST_URI} [a-z\d\-]+/[a-z]\d+(.+)
RewriteRule ^([a-z\d\-]+/[a-z]\d+)/? $1 [R=301]
on top of the SEF rules. It's doing what i want which is to remove the garbage from the url but it gives me an infinite loop because its redirecting even when the url is clean. Any hints?
EDIT: So i realized that the .+ at the end is matching the numbers as well... How do i change it to match anything other than numbers after the numbers? basically where I have the .+ i need to have a "match any character except for numbers"
EDIT: I finally got it to work with the following code:
# Remove garbage from after category
RewriteCond %{REQUEST_URI} [a-z\d\-]+/[a-z]\d+[A-Za-z-.]+
RewriteRule ^([a-z\d\-]+/[a-z]\d+)/? $1 [R=301]
The (.+) i was using previously was reading the 2nd number (c1234)as being part of the . so it would always pass the the condition as true unless it was something like c1

ExpressionEngine RewriteRule RegEx Throws 500 Error

When using categories in ExpressionEngine, a Category URL Indicator trigger word can be set to load a category by its {category_url_title}.
I would like to remove the category "trigger word" from the URL.
Here is what I have so far, with the trigger word set to "category":
RewriteRule /products/(.+)$ /products/category/$1 [QSA,L]
I'm not an expert at writing regular expressions, but I do a little. I'm 99% sure my RegEx is fine, however when trying to use it as a RewriteRule in my .htaccess file, I'm getting a 500 error.
I'm sure it's something stupid, but for some reason I'm not seeing my mistake. What am I doing wrong?
Update: Adding a ^ to the beginning of the RewriteRule fixed the 500 error.
RewriteRule ^/products/(.+)$ /products/category/$1 [QSA,L]
This is not safe. Take:
/products/a
The regex group matches a.
It will be rewritten to:
/products/category/a
which the regex matches again (this time, the group matches category/a). Guess what will happen.
You want /products/ from the beginning of input if it is not followed by category/, which means you want a negative lookahead. Also, the QSA flag is of no use, you don't have a query string to rewrite (QSA stands for Query String Append):
RewriteRule ^/products/(?!category/)(.+) /products/category/$1 [L]
Another way to use it (and which I personally prefer) is to use a RewriteCond prior to the rule:
RewriteCond %{REQUEST_URI} ^/products/(?!category/)
RewriteRule ^/products/(.*) /products/category/$1 [L]
This Apache RewriteRule should do the job for you*:
RewriteCond %{REQUEST_URI} ^/products/(?!category/)
RewriteRule ^/products/(.*) /products/category/$1 [L]
With this in place, you'll need to hard code your category links manually:
{categories backspace="2"}
{category_name},
{/categories}
Which would output the new Category URLs you desire:
http://example.com/products/toys
Otherwise, if using the recommended path variable when building your category links:
{categories backspace="2"}
{category_name},
{/categories}
Would create links with the Category URL Indicator in the URI:
http://example.com/products/C1
http://example.com/products/category/toys
Which — while perfectly valid — would create canonicalization issues on your site since the different URLs would appear as duplicate content to search engines.
*Credit to fge for brilliant mod_write rule.

Can mod_rewrite preserve a double slash?

Im just learning mod_rewrite and regex stuff, and what I'm trying to do is pass variables of any name, with any number of variables and values, into a script and have them forwarded to a different script.
here is what I have so far:
RewriteEngine on
RewriteRule ^script\$(.*[\])? anotherscript?ip=%{REMOTE_ADDR}&$1 [L]
That all seems to work except that one of the parameters I'm passing is a URL and the // after http:// always gets stripped down to one slash.
for example, I do
script$url=http://www.stackoverflow.com
then it redirects to:
anotherscript?ip=127.0.0.1&url=http:/www.stackoverflow.com
and the second script chokes on the single-slash.
I realize that preserving a double-slash is the exact opposite of what people usually do with mod_rewrite. Is there a way I can preserve the double-slash?
EDIT: Solution found with Gumbo's help.
RewriteCond %{THE_REQUEST} ^GET\ (.*)/script\$([^\s]+)
RewriteRule ^script\$(.*) anotherscript?ip=%{REMOTE_ADDR}&%2 [L]
I had to add that (.*) in front of /script on the RewriteCond, once I did that it got rid of the 404 errors and then it was just a matter of passing the matches through.
Try this rule:
RewriteCond %{THE_REQUEST} ^GET\ /script\$([^\s]+)
RewriteRule ^script\$.+ anotherscript?ip=%{REMOTE_ADDR}&%1 [L]
See Diggbar modrewrite- How do they pass URLs through modrewrite? for the explanation.
I Think there may be something wrong with the first part of your RewriteRule regex
^script\$(.*[\])?
The backslash ( \ ) is used to escape a special character into a litteral one, thus you are actually trying to match a closing bracket ( ] ), is that intended ?
try this
RewriteRule ^script\$(.*)? anotherscript?ip=%{REMOTE_ADDR}&$1 [L]