I'm trying to rewrite /user/username to /user-profile/?user=username without changing the URL in the address bar. I have the following code:
RewriteRule ^/?user/(.*?)/?$ /user-profile/?user=$1 [L]
RewriteCond %{THE_REQUEST} ^/user-profile/\?user=([^\&\ ]+)
RewriteRule ^/?user-profile/$ /user/%1? [L,R=301]
This changes /user/username to /user-profile/?user= in the address bar. The query string var "user" is left blank but it somehow loads the correct user profile. So I think the first rule is working but the second rule and it's condition must not be since the URL in the address bar is changing. What can I do to fix it?
Thanks!
A couple of things. You have 2 rules, one that internally rewrites and the other redirects the browser. You must have your redirect come before the rewrite, otherwise the internal rewrite gets reprocessed by the redirect rule. The other thing is the %{THE_REQUEST} variable is literally the first line of the HTTP request, and it starts with a method, not the request URI:
GET /user-profile/?user=qwerty HTTP/1.1
is what it will look something like. That means you need to alter your regex to account for those other parts of the request that's not the URI. Try:
RewriteCond %{THE_REQUEST} ^GET\ /user-profile/\?user=([^\&\ ]+) [NC]
RewriteRule ^ /user/%1? [L,R=301]
RewriteRule ^/?user/(.*?)/?$ /user-profile/?user=$1 [L]
Related
I want to make my website to have 'pretty-urls'. Also I want to make so users which input 'ugly' urls will be redirected to 'pretty-urls'.
Simplified example:
I have page data.php?id=123. I want so it shows to users as data/123 and for whose who typed in address bar data.php?id=123 it will be redirected to data/123.
I have tried following code in .htaccess:
# redirect to pretty url
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^/?data\.php data/%1? [R=301,L]
# convert pretty url to normal
RewriteRule ^/?data/([0-9]+)$ data.php?id=$1 [L]
However it doesn't work, it goes into infinite loop as I understood.
Is what I wanted possible and how if yes?
Using %{QUERY_STRING} for your case will produce a infinite loop because the internal destination also relies on it.
However using %{THE_REQUEST} does not:
# Redirect /data.php?id=123 to /data/123
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+data\.php\?id=([0-9]+) [NC]
RewriteRule ^ /data/%1? [R=302,L]
# Internally forward /data/123 to /data.php?id=123
RewriteRule ^data/([0-9]+)/?$ /data.php?id=$1 [NC,L]
I have problem when I try to redirect and rewrite together.
I have site example.com/show_table.php?table=12 (max 99 tables). I wanted nice links, so I got this .htacces rw rule:
RewriteRule ^table/([0-9]{1,2})$ show_table.php?table=$1 [L,NC]
Now are links something like example.com/table/12 - it's definitely OK. But I want all old links redirect to new format. So I use Redirect 301, I added to .htaccess this code:
RewriteCond %{REQUEST_URI} show_table.php
RewriteCond %{QUERY_STRING} ^table=([0-9]{1,2})$
RewriteRule ^show_table\.php$ http://example.com/table/%1? [L,R=301,NC]
But when I visit example.com/show_table.php?table=12, I receive just redir-loop. I don't understant - the first is rewrite, the second is redirection, there ain't no two redirections. Do You see any error?
Thanks!
Instead of checking REQUEST_URI in the condition, you need to be checking in THE_REQUEST (which contains the full original HTTP request, like GET /show_table.php HTTP/1.1). When Apache performs the rewrite, it changes REQUEST_URI, so to the rewritten value, and that sends you into a loop.
# Match show_table.php in the input request
RewriteCond %{THE_REQUEST} /show_table\.php
RewriteCond %{QUERY_STRING} ^table=([0-9]{1,2})$
# Do a full redirection to the new URL
RewriteRule ^show_table\.php$ http://example.com/table/%1? [L,R=301,NC]
# Then apply the internal rewrite as you already have working
RewriteRule ^table/([0-9]{1,2})$ show_table.php?table=$1 [L,NC]
You could get more specific in the %{THE_REQUEST} condition, but it should be sufficient and not harmful to use show_table\.php as the expression.
You'll want to read over the notes on THE_REQUEST over at Apache's RewriteCond documentation.
Note: Technically, you can capture the query string in the same RewriteCond and reduce it to just one condition. This is a little shorter:
# THE_REQUEST will include the query string so you can get it here.
RewriteCond %{THE_REQUEST} /show_table\.php\?table=([0-9]{1,2})
RewriteRule ^show_table\.php$ http://example.com/table/%1? [L,R=301,NC]
I have looked through stack overflow and can't find the exact answer I am looking for so here goes.
I have a URL
http://holtplantandmachinery.co.uk/cat/wheel-loaders which redirects to http://holtplantandmachinery.co.uk/category.php?name=wheel-loaders
However I need it to work the other way around when you enter the dynamic URL it rewrites to the static (folder looking) URL above and vice versa. Essentially whatever one is called it should rewrite to the static one. Now I know I need to setup a rewrite that works the opposite way to the one above and then have a condition to stop an infinite loop but I can't seem to get anything to work please help.
When someone types http://holtplantandmachinery.co.uk/category.php?name=wheel-loaders into the browser's URL address bar, the request sent to the holtplantandmachinery.co.uk server looks something like:
GET /category.php?name=wheel-loaders HTTP/1.1
Host: holtplantandmachinery
some other headers
etc
You can use the %{THE_REQUEST} var to match against the first line:
RewriteCond %{THE_REQUEST} ^(GET|POST|HEAD)\ category\.php\?name=([^&\ ]+)
RewriteRule ^ /cat/%2? [L,R=301]
This will redirect the request to http://holtplantandmachinery.co.uk/cat/wheel-loaders and that URL will show up in the browser's URL address bar. The reason why you use %{THE_REQUEST} instead of %{QUERY_STRING} is because when your other rule that rewrites the nicer looking URL to the one with the query string, it'll look and the %{QUERY_STRING} would match, the rule would get applied and cause a redirect loop. Alternatively, you could match against the query string and use a:
RewriteCond %{ENV:REDIRECT_STATUS} !200
To ensure the URI wasn't from a previously rewritten internal redirect.
Then you'd have your internal rewrite rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?cat/(.*)$ /category.php?name=$1 [L]
I have a site and need htaccess code to make this change in the address bar without making any physical changes in the server folders
example.com/data/65767.html
to be
example.com/65767
example.com/data/56-45.html
to be
example.com/56-45
Regards
Horribly inefficient, you need to make sure your links get changed to point to the one without .html, but...
RewriteEngine On
# externally redirect so that the browser shows the non-.html URL
RewriteCond %{THE_REQUEST} ^(GET|POST|HEAD)\ /data/([0-9-]+)\.html
RewriteRule ^ /%2 [L,R=301]
# internally rewrite the non-.html URI back to the .html URI
RewriteCond %{DOCUMENT_ROOT}/data%{REQUEST_URI}.html -f
RewriteRule ^/?([0-9-]+)$ /data/$1.html [L]
This works with /data/<any number of digits or "-"> URIs. If you want it to work with anything, replace the [0-9-] with .
EDIT:
can we also redirect example.com/65767.html to be example.com/65767 and the content from example.com/data/65767.html
Yeah, just change the first rule to:
RewriteCond %{THE_REQUEST} ^(GET|POST|HEAD)\ /(data/)?([0-9-]+)\.html
RewriteRule ^ /%3 [L,R=301]
I need to redirect
/search?keywords=somesearchterm
to
/search/somesearchterm
This seems incredibly basic but I've been pounding my head against it for an hour.
Thanks for taking the time to look at this.
You want to implement what is called a "301 Redirect" with mod_rewrite.
RewriteEngine ON
RewriteRule ^/search\?keywords=somesearchterm$ /search/somesearchterm
adding regular expressions:
RewriteEngine ON
RewriteRule ^/search\?keywords=(.+) /search/$1 [R=301,L]
R=301 means provide a 301 Header redirect so the user's URL changes in the browser, and L means don't process any more rewrite rules if this one matches.
If you want to do the reverse -- in other words, if someone goes to mysite.com/search/asearchterm and you want the URL to stay the same, but "behind the scenes" you want it to load a certain server script, do this:
RewriteEngine ON
RewriteRule ^/search/(.+) /search.php\?keywords=$1 [L]
You can not match aginst Query string in RewriteRule directive. Use %{THE_REQUEST} or %{QUERY_STRING} server variables to match the Query string :
The following rule works fine for this redirection
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/search\?kewords=([^&\s]+) [NC]
RewriteRule ^ /search/%1? [NE,NC,R,L]
RewriteRule ^search/([^/]+)/?$ /search?keyword=$1 [QSA,NC,L]