RewriteRule negate (NOT) not working - mod-rewrite

I am trying to do the following redirect:
any url such as:
/about/apple/1
/about/green
/about/apples
/about/pears/1
to:
/about/apple
using the following, which does not work:
RewriteRule ^about/(!apple) /about/apple [R=301,L]
The following test line works fine:
RewriteRule ^about/apples /about/apple [R=301,L]
I have tried:
RewriteRule ^about/!(apple) /about/apple [R=301,L]
RewriteRule ^about/(?!apple) /about/apple [R=301,L]
RewriteCond %{REQUEST_FILENAME} !(about/apple)
RewriteCond %{REQUEST_FILENAME} about(.*)
RewriteRule . /about/apple [R=301,L]
And also tried putting it into a rewritecond before hand, but nothing works.
Thanks.

Your regular expression pattern ^about/(?!apples) matches none of the uris you want to redirect. It matches /about/foobar but does not match /about/apples or /about/apples/foobar as you have negated the apples substring in the pattern.
You can use
RewriteRule ^about/apples/(.*)$ /about/$1 [L,R]
This will redirect /about/apples/ or /about/apples/foobar to /about/foobar .
Make sure to clear your browser cache before testing this.

Related

Basic rewrite of url

I need a rule that rewrites
http://example.com/page.html?page=2
to
http://example.com/page.html/page/2
I already tried this rule:
RewriteRule ^(.*)page=(.*)$ http://example.com/$1/page/$2/
but this does not work! :( Where I'm wrong?
You can try this one:
RewriteCond %{QUERY_STRING} page=(\d+) [NC]
RewriteRule (.*) /$1/page/%1/? [R=301,L]
It should works.

Rewriting URLs with one query string to another URL with a different query string

I'm trying to accomplish some redirects as follows:
#Basic Rule Set
RewriteRule ^/path$ http://newhost.com/Page?pagename=form1000 [R=301]
RewriteRule ^/path/index.html$ http://newhost.com/Page?pagename=form1000 [R=301]
which work fine.
However, redirects with query strings in source and destination return me to the above destination url. For e.g.,
# Advanced Rule Set
RewriteRule ^/path/index.html?var=foo$ http://newhost.com/Page?pagename=form1000?id=hello [R=301]
RewriteRule ^/path/index.html?var=bar$ http://newhost.com/Page?pagename=form1000?id=byebye [R=301]
RewriteRule ^/path/index.html?var=xyz$ http://newhost.com/Page?pagename=form1000?id=world [R=301]
all redirect to http://newhost.com/Page?pagename=form1000.
I've tried a RewriteCond %{QUERY_STRING} ^var=(.*)$ [NC] and RewriteCond %{REQUEST_URI} ^/path/index.html [NC] preceding the above three rules, and still I'm redirected to http://newhost.com/Page?pagename=form1000. I've swaped the order of the Basic and Advanced rule sets, and all redirect to http://newhost.com/Page?pagename=form1000.
Any ideas on how I might get these rule sets to work? CentOS 6.x, Apache 2.2.
You may try this instead:
# Advanced Rule Set
RewriteCond %{QUERY_STRING} var=foo [NC]
RewriteRule ^path/index.html/? http://newhost.com/Page?pagename=form1000?id=hello [R=301,L,NC]
RewriteCond %{QUERY_STRING} var=bar [NC]
RewriteRule ^path/index.html/? http://newhost.com/Page?pagename=form1000?id=byebye [R=301,L,NC]
RewriteCond %{QUERY_STRING} var=xyz [NC]
RewriteRule ^path/index.html/? http://newhost.com/Page?pagename=form1000?id=world [R=301,L,NC]

mod_rewrite to redirect URL with query string

I have a lot of working mod_rewrite rules already in my httpd.conf file. I just recently found that Google had indexed one of my non-rewritten URLs with a query string in it:
http://example.com/?state=arizona
I would like to use mod_rewrite to do a 301 redirect to this URL:
http://example.com/arizona
The issue is that later on in my rewrite rules, that 2nd URL is being rewritten to pass query variables on to WordPress. It ends up getting rewritten to:
http://example.com/index.php?state=arizona
Which is the proper functionality. Everything I have tried so far has either not worked at all or put me in an endless rewrite loop. This is what I have right now, which is getting stuck in a loop:
RewriteCond %{QUERY_STRING} state=arizona [NC]
RewriteRule .* http://example.com/arizona [R=301,L]
#older rewrite rule that passes query string based on URL:
RewriteRule ^([A-Za-z-]+)$ index.php?state=$1 [L]
which gives me an endless rewrite loop and takes me to this URL:
http://example.com/arizona?state=arizona
I then tried this:
RewriteRule .* http://example.com/arizona? [R=301,L]
which got rid of the query string in the URL, but still creates a loop.
Ok, adding the 2nd RewriteCond finally fixed it - now rewriting correctly and no loop:
# redirect dynamic URL: ?state=arizona
RewriteCond %{QUERY_STRING} state=arizona [NC]
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteRule .* http://domain.com/arizona? [R=301,L]
# older rewrite rule that passes query string based on URL:
RewriteRule ^([A-Za-z-]+)$ index.php?state=$1 [L]
And here's the code to make it work for any state value, not just arizona:
RewriteCond %{REQUEST_URI} ^/$ [NC]
RewriteCond %{QUERY_STRING} ^state=([A-Za-z-]+)$ [NC]
RewriteRule .* http://domain.com/%1? [R=301,L]
RewriteCond %{REQUEST_URI} ^/\?state=arizona$ [NC]
should be
RewriteCond %{QUERY_STRING} state=arizona [NC]
The request_uri ends at the ? token.

removing the forward slash from this re-written url

I know this may sound silly little bit, but there is no other way to resolve it. I have an issue with the forward slash /. I want to remove it from the url because it is kind of making some confusion to the browsers giving trusted or un-trusted urls.
This is the code for the main domain:
RewriteCond %{SERVER_PORT} !^443$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^ /user [R=301,L]
and this is the output of the above code: https://www.mydomain.com/user/
but I want the url redirect to this:
https://www.mydomain.com/user
I also want to remove the forward slash from this url :
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(?:\.\w+|/)$
RewriteRule (.*) /$1/ [R,L]
RewriteCond %{REQUEST_URI} ^(/end)
RewriteRule ^(.*)$ /top/right/left/bottom/$1 [L]
RewriteCond %{REQUEST_URI} ^/top/right/left/bottom
RewriteRule top/right/left/bottom/(end)(/(./*))?$ $1$2 [R,L]
and this is the output of the above code: https://www.mydomain.com/end/
but I want the url redirect to this:
https://www.mydomain.com/end
Last question: why do I have to write www. in my own in some browser like FF or chrome so the redirect make itself to the required url?
All comments are appreciated
Looks like the above rewrites rules are written by me. So optimizing it for URL to not end with a / (https://www.mydomain.com/end)
Replace the whole(from RewriteCond %{ENV:REDIRECT_STATUS} 200 to RewriteRule top/right/left/bottom/(end)(/(./*))?$ $1$2 [R,L]) thing by this:
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteRule ^(end)(?:/(.*))? /top/right/left/bottom/$1/$2 [L]
RewriteRule ^top/right/left/bottom/(end)(/.*)?$ $1$2 [R,L]
Remember though if you access with a forward slash like this: https://www.mydomain.com/end/ the forward slash will not be removed.
If you want the / to be removed: Replace the last 2 rules by these:
RewriteRule ^(end)(?:/(.+))? /top/right/left/bottom/$1/$2 [L]
RewriteRule ^(end)/$ $1 [R,L]
RewriteRule ^top/right/left/bottom/(end)(/.*)?$ $1$2 [R,L]
Store the url in a variable and perform rtrim to remove trailing slash
$redirectURL = rtrim($redirectURL, "/");

How do I write a custom mod_rewrite .htaccess file for CakePHP routing?

I've rewritten my web app using CakePHP, but now I need to have my old formatted urls redirect to my new url format. I can't seem to add my own custom mod rewrite rule. I've added it above the main cakephp rewrite rule, but I'm getting an infinite redirect loop. I just want http://mysite.com/index.php?action=showstream&nickname=user to redirect to http://mysite.com/user before the cakephp rewrite happens.
EDIT: Ok, so now when the condition is met it's redirecting but it's appending the original query string to the end. I'm assuming that's due to the QSA flag in CakePHP rewrite rules, but I was under the impression the "L" in my rule would stop that from executing...
RewriteEngine On
RewriteCond %{QUERY_STRING} ^action\=showstream&nickname\=(.*)$
RewriteRule ^.*$ http://mysite.com/%1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
When you do a capture inside the RewriteCond line instead of the RewriteRule, you have to reference the capture with %N instead of $N. That is, your RewriteRule line should be:
RewriteRule ^index.php$ /%1 [R=301,L]
Try to test the request line (THE_REQUEST) to see what URI originally has been requested:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /index\.php
RewriteCond %{QUERY_STRING} ^action=showstream&nickname=([^&]*)$
RewriteRule ^index\.php$ /%1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php?url=$0 [QSA,L]
But maybe it would be easier to do this with PHP.

Resources