301 redirect get pagination - .htaccess

I'm trying to 301 redirect a paginated blog list from an old site onto a new url.
I think I'm getting pretty close with the RewriteRule but I'm not quite there yet, this is what I have:
RewriteCond %{QUERY_STRING} ^page=
RewriteRule ^(blog)?$ http://www.newdomain.com/news/page/$1? [R=301,L]
Using this rule if I go to
http://www.olddomain.com/blog?page=1
I currently get redirected to
http://www.newdomain.com/news/page/blog
I would like to be sent to
http://www.newdomain.com/news/page/1
I'm sure its just something small and simple that I'm missing.
Edit
Expanding on the solution below, I've added tags/category support to the rewrite rule using $1.
RewriteCond %{QUERY_STRING} ^page=([^&]+) [NC]
RewriteRule ^blog/tag/([^/\.]+)?$ http://www.newdomain.com/news/tag/$1/page/%1? [R=301,L,NC]

Few minor mistakes in your code.
You need to capture page parameter's value from query string first
Then use that capture value using % instead of $1
No need to capture blog since you don't need it.
Change your code with:
RewriteCond %{QUERY_STRING} ^page=([^&]+) [NC]
RewriteRule ^blog/?$ http://www.newdomain.com/news/page/%1? [R=301,L,NC]

Related

Redirect to 'pretty-urls' doesn't work

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]

mod_rewrite and redirect causing loop

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]

mod rewrite in htaccess with paging system

I have the following code which works fine
RewriteRule ^articles/([^/\.]+)/?$ articles.php?pid=$1 [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+articles\.php\?pid=([^\s&]+) [NC]
RewriteRule ^ http://www.mydomain.com/articles/%1? [R=301,L]
The problem is that I have a paging systen and I send another variable to that page for my paging system which looks like this
&pageNum_getArticles=1#1
I've already tried to do the following but gets confused with the hash I think
RewriteRule ^articles/([^/\.]+)/?$ articles.php?pid=$1&pageNum_getArticles=$2 [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+articles\.php\?pid=([^\s&]+)&pageNum_getArticles=([^\s&]+) [NC]
RewriteRule ^ http://www.mydomain.com/articles/%1/%2? [R=301,L]
Thanks for the info. So is there a solution about this or I have to change the paging system?
Yes.
You have 2 sets of rewrite rules that sort of work together. The first rule takes a nice looking URL without any query strings and internally rewrites it to a php script. The second rule takes the ugly looking php script URI and redirects the browser to use the nicer looking one. The first set is correct. But the second set uses the same rule to route to the script. You need to create another grouping for your paging, as $2 doesn't backreference to any match.
Try:
# second match here---------------v
RewriteRule ^articles/([^/.]+)/([^/.]+)/?$ articles.php?pid=$1&pageNum_getArticles=$2 [L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+articles\.php\?pid=([^\s&]+)&pageNum_getArticles=([^\s&]+) [NC]
RewriteRule ^ http://www.mydomain.com/articles/%1/%2? [R=301,L]
Note that if you still want to use the rules that doesn't use paging, you need to have the non-paging rules after the ones with paging.
Additionally, if for some reason your paging doesn't work without the URL fragment, and if the fragment is always going to be the same as the paging number, you can just add it to the end of the redirect. But you'll need a NE like faa suggested:
RewriteRule ^ http://www.mydomain.com/articles/%1/%2#%2? [R=301,L,NE]

mod_rewrite so that first-level subdirectory is a GET variable

Alright, title is REALLY sloppy.
Here's my problem: I have a news site and when you go to the main page (domain.com) it redirects you to domain.com/news/top?geography=San_Francisco after it figures out your geography.
How do I use the .htaccess so that it goes from domain.com/news/top?geography=San_Francisco domain.com/San_Francisco/news/top ?
There are some similar questions, but I have not found one similar enough in that you're editing the URL as a furtherback subdirectory.
It should also be noted that I am using the Code Igniter framework for PHP and it normally has it as domain.com/index.php/news/top?geography=San_Francisco but I did a mod_rewrite already to get rid of the index.php. The code is as follows for that:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
Code I've tried:
RewriteRule ^([^/]+)/news/top$ /news/top?geography=$1 [L,QSA]
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
Before the index.php rule that you have, try adding this:
RewriteRule ^([^/]+)/news/top$ /news/top?geography=$1 [L,QSA]
You'll need to make sure the links you generate are in the form of domain.com/San_Francisco/news/top though.
But to take care of the links in the wild that still look like the old way, you have to match against the actual request:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /news/top\?geography=([^&]+)
RewriteRule ^news/top$ /%1/news/top? [L,R=301]
This will 301 redirect the browser if someone goes to the link domain.com/news/top?geography=San_Francisco and make it so the browser's address bar says this: domain.com/San_Francisco/news/top. At which point the browser will send another request for the second URL, and you use the rule above to change it back into the one with a query string.

.htaccess redirect from GET variable to url string

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]

Resources