Remove part of the query string with mod_rewrite - apache

I am not very good with .htaccess at all, so I want to achieve something very simple, but I can't. What I want to do is to redirect certain files to test.php, and if test is ok, PHP redirects back to original page. It works fine, I add the "test=ok" part to the original URL, that way I don't get a redirect loop. However, I want to remove the test=ok query part from the original URL on redirection. How can I achieve that???
TL/DR
I have several URLs I want rewritten through mod_rewrite.
examples:
http://example.com/?time=1&test=ok
http://example.com/?test=ok
How can I remove the &test=ok and the ?test=ok parts using .htaccess?
Right now I have:
RewriteCond %{QUERY_STRING} ^test=ok$ [NC]
RewriteRule (.*) /$1? [L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} (/[^.]*|\.(php|html?|js))$ [NC]
RewriteCond %{QUERY_STRING} !test=ok [NC]
RewriteRule .* test.php [L]
But that doesn't remove the test=ok part... :(

Related

.htaccess - mod-rewrite and redirecting profile URLs with parameters to clean ones

I have links to user profiles like:
https://example.com/chat/index.php?action=user&member=547
https://example.com/chat/index.php?action=user&member=11540
etc.
My goal is to mod-rewrite such URLs so that they look nicer, ie. they should look like:
https://example.com/chat/member-547/
https://example.com/chat/member-11540/
etc.
And URLs without a trailing slash, ie.
https://example.com/chat/member-547
should be 301-forwarded to one with slash, ie.
https://example.com/chat/member-547/
So in .htaccess I tried this, but only the first line seems to work and it's not complete:
RewriteRule ^chat/member-([0-9]+)/$ ./index.php?action=user&member=$1
RewriteRule ^chat/member-([0-9]+)$ /member-$1/ [R=301,L]
TO SUMMARIZE:
When someone enters URL like:
https://example.com/chat/index.php?action=user&member=547
it should be 301-redirected to:
https://example.com/chat/member-547/
When someone enters:
https://example.com/chat/member-547
it should also be 301-redirected to:
https://example.com/chat/member-547/
I hope there's an efficient way to do it right.
Starkeen's answer is correct, and will work. I'll just suggest an alternative, which acts on the raw request variable itself:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^GET\ /chat/index\.php\?action=user&(member)=(\d+) [NC]
RewriteRule ^chat/index\.php$ /chat/%1-%2/? [R=301,L]
RewriteRule ^chat/member-([0-9]+)$ /member-$1/ [R=301,L]
RewriteRule ^chat/(member)-(\d+)/$ /chat/index.php?action=user&$1=$2 [L]
You can use the following rule :
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteCond %{QUERY_STRING} ^action=([^&]+)&member=(.+)$
RewriteRule /chat/index\.php$ /chat/member-%2/? [L,R=301]
RewriteRule ^chat/member-(.+)/?$ /chat/index.php?action=user&member=$1 [L]

redirect url with query string to path, and url without query string must be internally rewritten

I've been trying and trying.
If one goes to:
www.domain.nl/vereniging
internally a page is requested from:
www.domain.nl/?p=vereniging
For that I use this:
RewriteCond %{QUERY_STRING} !(p=.*)$
RewriteRule ^(.+)$ ?p=$1 [NC]
If a users visits:
www.domain.nl/?p=vereniging
I want the users to be redirected to:
www.domain.nl/vereniging
For that I use:
RewriteCond %{QUERY_STRING} ^p=(.*)$ [NC]
RewriteRule ^$ http://www.domain.nl/%1? [NC,R=301]
(If I put RewriteCond %{REQUEST_FILENAME} !-d before this, it doesn't redirect anymore. That's strange because a query is not a directory right?)
Separately, these 2 chunks of code work.
However, if I put them together in 1 .htaccess it bitches about looping.I don't understand this, because the conditions should prevent looping.
Try applying the END flag to either the first or second RewriteRule.
Look at the END flag here: http://httpd.apache.org/docs/current/rewrite/flags.html
You need to check against the actual request:
RewriteCond %{THE_REQUEST} \?p=([^&\ ]+)
RewriteRule ^ /%1? [L,R=301]

How to avoid chain redirections using mod_rewrite?

Basicly i'm working on my site to be SEO-friendly. I wanted to achieve following:
Rewrite urls to pretty ones
Remove multiple slashes (eg. example.com/////something/// to example.com/something/
Redirect www version to a non-www version.
Hide index.php file from all urls
Redirect from old (/?id=something/ to new urls /something/)
I came up with this .htaccess code:
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]
RewriteRule ^index.php(.*)$ /$1 [R=301]
RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L]
...and though it's working it has a side effect: chain redirects, eg. example.com/?id=something////// -> example.com/something////// -> example.com/something/
So is there a way to rewrite or modify this code so it'll be redirecting just once to the preferred version of the url?
Trying to interpret what you want, let's look at the rules in your question:
.1 Can't understand the purpose of this:
RewriteCond %{THE_REQUEST} //
RewriteRule .* $0 [R=301]
.2 This rule-set in your question removes www and converts the query string ?id=val to /val, but only when the incoming URI has www AND there is a query string as both conditions must be met:
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteCond %{QUERY_STRING} ^id=([a-z0-9\/-]+)
RewriteRule ^(.*)$ http://example.com/%1? [R=301]
.3 This rule
RewriteRule ^index.php(.*)$ /$1 [R=301]
Hides index.php, but only when it is in the root directory. Example:
http://www.example.com/index.php?id=val
Does not work when it is in a subdirectory. Example:
http://www.example.com/folder/index.php?id=val
.4 Can't understand the purpose of this:
RewriteRule ^([a-z0-9\/-]+)$ /?id=$1 [L]
I suggest this instead:
RewriteEngine On
RewriteBase /
#Redirects all www to non-www
RewriteCond %{HTTP_HOST} www\.example\.com$ [NC]
RewriteRule ^(.*)/?$ http://example.com/$1 [R=301,L]
#Hides "index.php" keeping the query if present
RewriteRule ^(.*)/index\.php$ $1/ [R=301,QSA,L]
#Converts query string `?id=val` to `/val`
RewriteCond %{QUERY_STRING} id=([^/]+)
RewriteRule .* /%1? [R=301,L]
Remember spiders will "adapt" to the correct new structure after a few months, and the problem may ultimately be a whole lot less severe than what it looks like initially. You can leave all the .htaccess code in place, knowing it always be there to correct any "old" references yet will in fact hardly ever actually be used.
I've never found an easy way to avoid multiple round trips back to the client when "fixing up" a URL to be in some sort of canonical form. mod_rewrite seems to be more focussed on the "local" redirect case where the client has no idea that the content it got back came out of a file structure that doesn't perfectly match that implied by the URL.
It is possible to save up all the URL mods locally, then provoke only one round trip to the client that delivers all the URL corrections all at once by setting everything in newly created "environment" variables then at the end asking basically "has anything changed?" However doing so is notably verbose and rather awkward and quite error-prone and has never become a "recommended technique".

Apache Redirect after a RewriteRule

I'm trying to redirect to a "mobile" version of the site, done by the following:
RewriteCond %{HTTP_USER_AGENT} "ipad|iphone|ipod" [NC]
RewriteCond %{HTTP_COOKIE} !^.*mobile.*$ [NC]
RewriteRule ^$ /?m=t [L,R=302,co=mobile:true:.domain.com]
RewriteCond %{HTTP_USER_AGENT} "ipad|iphone|ipod" [NC]
RewriteCond %{HTTP_COOKIE} ^.*mobile=true.*$ [NC]
RewriteCond %{QUERY_STRING} !(^|&)m=t(&|$) [NC]
RewriteRule ^$ /?m=t [L,R=302,co=mobile:true:.domain.com,QSA]
Now this works for the root.
But since the site depends heavily on rewrites, if I modify
RewriteRule ^$ /?m=t [L,R=302,co=mobile:true:.domain.com,QSA]
to
RewriteRule ^(.*)$ /$1?m=t [L,R=302,co=mobile:true:.domain.com,QSA]
It'll give me the correct redirect, but without any previous rewrites.
so if I have say a rewrite previously that was
RewriteRule ^product/shimano$ /index.php?product_cat=shimano [L]
The modified line will give me /index.php?m=t&product_cat=shimano instead of /product/shimano?m=t
What am I missing? I've been trying to figure this out for a while now.
Try redirecting first, then rewriting. That is, put these mobile check rules in front of the rewrites.
That way, if it's mobile, and m=t isn't there, it will do the 302 redirect with m=t added. That will then come through again, skip these rules (since m=t is there), and continue on wiht the normal rewrites.
I'm not entirely sure about the first set of rules above. They might also need that line from the second set, that does the querystring check for m=t, to avoid an infinite loop. Basically, if it already has m=t, then it doesn't do it again.

Redirect in combination with a rewrite condition in htaccess

I've got a cms-driven website, with no option to change the code. What I want to accomplish is creating friendly url's, using only apaches mod-rewrite engine.
The problem is I'm creating an infinite loop, because I first redirect the original url (index.php?id=21) to a friendly one (/friendly/) and then rewrite the '/friendly' part back to 'id=21'
I know there should be an extra condition or parameter to avoid looping in this case, but I can´t get one of the possible solutions to work.
Here´s the code:
RewriteCond %{query_string} ^id=21$ [NC]
RewriteRule /* /peuterspeelzaal? [R=301,L]
RewriteRule ^peuterspeelzaal$ index.php?id=21 [L]
You need to look at the request line in THE_REQUEST to see what originally has been requested:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /[^?\ ]*\?id=21\ [NC]
RewriteRule /* /peuterspeelzaal? [R=301,L]
RewriteRule ^peuterspeelzaal$ index.php?id=21 [L]
I'm guessing you are rewriting in both directions to ensure that old links are redirected to the new friendly urls?
You could just add a dummy parameter to all your "friendly" rewrites so that they don't match the other rule:
RewriteCond %{query_string} ^id=21$ [NC]
RewriteRule /* /peuterspeelzaal? [R=301,L]
RewriteRule ^peuterspeelzaal$ index.php?id=21&dummy=1 [L]