Convert Dynamic URLs with query parameters to static URLs - .htaccess

For dynamic content on my website, I use urls with query variables
e.g. http://www.example.com/directory/?state=NJ&city=Wayne&zip=07474 or
http://www.example.com/directory/index.php?state=NJ&city=Wayne&zip=07474
I would like to convert them to seo-friendly static urls instead
e.g. http://www.example.com/directory/Wayne-NJ-07474/
I researched on SO and found it seems like a htaccess rewrite rule is the way to go.
I am a noob when it comes to htaccess constructs and what I fail to understand is will I still get the data associated with the individual query parameters i.e. state, city, and zip. Meaning will I still be able to access them via _REQUEST()?
I would also appreciate if someone would help me with the rewrite rule for my specific case.

You can use this code in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteBase /
# external redirect from actual URL to pretty one
RewriteCond %{THE_REQUEST} \s/+directory/(?:index\.php)\?state=([^\s&]+)&city=([^\s&]+)&zip=([^\s&]+)\s [NC]
RewriteRule ^ /directory/%2-%1-%3? [R=302,L,NE]
# internal forward from pretty URL to actual one
RewriteRule ^directory/([^-/]+)-([^-/]+)-([^-/]+)/?$ directory/?state=$2&city=$1&zip=$3 [L,QSA,NC]

Related

310 Redirect a URL Containing a ? (question mark)

I am currently in the final stages of redeveloping a website however having some trouble redirecting the old blog links to the new format.
We have inbound links to the old blog in the form of:
Index Page
http://www.domain_name.co.uk/blog-page/
Needs to become
http://www.domain_name.co.uk/news/
This is easy enough and has been done by using
RewriteRule ^blog-page$ /news/ [R=301,L]
Profile page
http://www.domain_name.co.uk/blog-page/index.php?/archives/1541-title-of-the-blog.html
The above needs to link to
http://www.domain_name.co.uk/news/1541-title-of-the-blog
However the '?' in the middle of the URL structure appears to break my rewriterule. I have read online about QUERYSTRING however I do not believe this solves my issue as there are no actual parameters passed through in the URL
The below code works but passes through the '/?/archives/' info also.
RewriteRule ^blog-page/index.php(.*)$ /news/$1 [R=301,L]
Any help would be massively appreciated. There are several other sections of the previous site build which for some reason use the same URL structure.
You will need an additional rule for matching query string. Have your DOCUMENT_ROOT/.htaccess like this:
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^/archives/(.+?)\.html$ [NC]
RewriteRule ^blog-page/index\.php$ /news/%1? [R=301,NC,L]
RewriteRule ^blog-page$ /news/ [R=301,L,NC]

Using mod_rewrite to mask a directory/file name in a URL

I've taken my site down for some prolonged maintenance and am using mod_rewrite to send all requests to a single page: www.mysite.com/temp/503.php
This is my .htaccess file which works fine.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/temp/503.php [NC]
RewriteRule .* /temp/503.php [R,L]
However, what I'd also like to be able to do is to hide /temp/503.php in the resulting URL from the visitor.
I know this is perhaps trivial and I'm sure fairly simple to achieve, but with my limited mod_rewrite skills I can't seem to get it to work.
Any help would be much appreciated.
Thanks.
Just get rid of the R flag in the rewrite rule, which tells the rule to redirect the request, thus changing the URL in the browser's location bar. So the rule would look like:
RewriteRule .* /temp/503.php [L]
which internally rewrites the requested URI instead of externally telling the browser that it's been moved to a new URL.

I changed the structure of my site to reach index cards

Excuse me for my english.
I make a brands directory web site.
Before to acces to the brands pages I use requests like this :
mydomain.com/fiche.php?id=115
where id is the id of the brand in my directory
I change the structure of the brands pages and now use this request:
mydomain.com/annuaire.php?type=fiche&id_marq=115
where id has become id_marq
I try to use a rewritebrule like this:
RewriteRule ^fiche.php$ http://www.annuaire-sites-officiels.com/annuaire.php?detail=fiche&id_marq=$1 [L,QSA,R=301]
to redirect the old links to the new pages but result dont pass the id_marq value and the url is:
http://www.annuaire-sites-officiels.com/annuaire.php?detail=fiche&id_marq=&id=115
&id= is too.
What am I doing wrong?
Your rule is not evaluating query string and that's why its not capturing id query parameter.
Change your code to:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^id=([^&]+) [NC]
RewriteRule ^fiche\.php$ /annuaire.php?detail=fiche&id_marq=%1 [R=302,L,QSA,NC]
Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.
Check out Regex Back Reference Availability:
You have to capture the query string. [QSA] passes it forward unaltered, so unless you're using id for anything you don't need that bit of code. Your 301 redirect is correct since this is a permanent redirect. Remember if you add a failed redirect your browser may cache that redirect so it might not look like it's working.
In this string match I'm only catching numbers to prevent someone from passing something like an asterisk * and XSS exploiting your site.
I've not included and [NC] matches in my code because when you allow multiple cases they can seem like different URLs to search engines (bad for SEO).
RewriteCond %{QUERY_STRING} id=([0-9]+)
RewriteRule ^fiche.php$ http://%{HTTP_HOST}/annuaire.php?detail=fiche&id_marq=%1 [R=301,L]

htacess url rewrites for .php?=n

I'm looking to rewrite old PHP pages to new locations, however the previous system used URLs structured as follows:
/old-page.php?page=Our%20Services
I've tried the following:
Redirect 301 /old-page.php?page=Our%20Services http://www.newdomain.co.uk/our-services/
Can someone help explain to me why the rewrite rule ignores everything after the question mark please?
You can use Redirect for simple cases only. If you want to check the query string, you must use mod_rewrite and RewriteCond
RewriteEngine on
RewriteCond %{QUERY_STRING} page=Our%20Services
RewriteRule ^old-page.php$ http://www.newdomain.co.uk/our-services/ [R,L]
This checks, if the query string contains page=Our%20Services and the URL path is old-page.php. It then redirects the client to the new URL http://www.newdomain.co.uk/our-services/.

301 Redirecting URLs based on GET variables in .htaccess

I have a few messy old URLs like...
http://www.example.com/bunch.of/unneeded/crap?opendocument&part=1
http://www.example.com/bunch.of/unneeded/crap?opendocument&part=2
...that I want to redirect to the newer, cleaner form...
http://www.example.com/page.php/welcome
http://www.example.com/page.php/prices
I understand I can redirect one page to another with a simple redirect i.e.
Redirect 301 /bunch.of/unneeded/crap http://www.example.com/page.php
But the source page doesn't change, only it's GET vars. I can't figure out how to base the redirect on the value of these GET variables. Can anybody help pls!? I'm fairly handy with the old regexes so I can have a pop at using mod-rewrite if I have to but I'm not clear on the syntax for rewriting GET vars and I'd prefer to avoid the performance hit and use the cleaner Redirect directive. Is there a way? and if not can anyone clue me in as to the right mod-rewrite syntax pls?
Cheers,
Roger.
As the parameters in the URL query may have an arbitrary order, you need to use a either one RewriteCond directive for every parameter to check or for every possible permutiation.
Here’s an example with a RewriteCond directive for each parameter:
RewriteCond %{QUERY_STRING} ^([^&]&)*opendocument(&|$)
RewriteCond %{QUERY_STRING} ^([^&]&)*part=1(&|$)
RewriteRule ^bunch\.of/unneeded/crap$ /page.php/welcome? [L,R=301]
RewriteCond %{QUERY_STRING} ^([^&]&)*opendocument(&|$)
RewriteCond %{QUERY_STRING} ^([^&]&)*part=2(&|$)
RewriteRule ^bunch\.of/unneeded/crap$ /page.php/prices? [L,R=301]
But as you can see, this may get a mess.
So a better approach might be to use a RewriteMap. The easiest would be a plain text file with key and value pairs:
1 welcome
2 prices
To define your map, write the following directive in your server or virual host configuration (this directive is not allowed in per-directory context):
RewriteMap examplemap txt:/path/to/file/map.txt
Then you would just need one rule:
RewriteCond %{QUERY_STRING} ^([^&]&)*opendocument(&|$)
RewriteCond %{QUERY_STRING} ^([^&]&)*part=([0-9]+)(&|$)
RewriteRule ^bunch\.of/unneeded/crap$ /page.php/%{examplemap:%2}? [L,R=301]
RewriteCond %{QUERY_STRING} option=com_content&task=view&id=70&Itemid=82
RewriteRule ^index.php http://www.example.com/business/banks/? [R=301,L]
The ? will prevent the url the user is sent to from having the same query string as the origin page.
In summary, you could use RedirectMatch with a regex that will match the full URL, including query string. That will let you rearrange parts of the URL, but if you have to do conversions like "opendocument&part=1" to "welcome" (where the new URL is completely different from the original one), you might need a RewriteMap - or perhaps better, just send all URLs to page.php and parse the query string in PHP.
EDIT: If it's just a few URLs you want to redirect, you could probably write out individual rules like
RedirectPermanent http://www.example.com/bunch.of/unneeded/crap?opendocument&part=1 http://www.example.com/page.php/welcome
RedirectPermanent http://www.example.com/bunch.of/unneeded/crap?opendocument&part=2 http://www.example.com/page.php/prices

Resources