Rewriting old and new urls to same page with .htaccess - .htaccess

Have a page currently with the URL /results-details.php?mls_number=stringofnumbers.
I want it to re-write to: /results-details/stringofnumbers
However I want that to basically resolve back to the original page.
I'm also changing all the URLs on the site internally to point to the URL. So I have two re-write rules:
RewriteCond %{QUERY_STRING} mls_number=([0-9]+)$
RewriteRule (.*) /new-homes/results-details/%1? [R=301,C]
RewriteRule ^results-details/([0-9]+)$ results-details.php?mls_number=$1
The second rule works fine on it's own with internal links in the /results-details/stringofnumbers form, but the first one doesn't chain properly to the second one and not sure what I'm doing wrong.
Basically trying to retain any links to the old URLs that might be out there but start using the new URS internally.
Suggestions?

YOu need to match against the actual request and not the URI, because the rewrite engine loops:
RewriteCond %{THE_REQUEST} \ /new-homes/results-details\.php?mls_number=([0-9]+)
RewriteRule ^ /new-homes/results-details/%1? [L,R=301]
RewriteRule ^results-details/([0-9]+)$ results-details.php?mls_number=$1

Related

Redirect certain subfolders by removing the parameter question mark

I am using .htaccess to redirect certain subfolders of my domain, to remove the question mark to improve my URLs.
Currently my URLs are like this:
www.example.com/post/?sometitle
I am trying to remove the question mark, so it is the following URL:
www.example.com/post/sometitle
Currently I have the following code in my .htaccess file:
RewriteCond %{THE_REQUEST} /post/?([^\s&]+) [NC]
RewriteRule ^ /post/%1 [R=302,L,NE]
i am using php GET parameters, i am attempting for when the browser visits example.com/post/sometitle that the page that is currently example.com/post/?sometitle is displayed
In that case you need to the opposite of what you are asking in your question: you need to internally rewrite (not externally "redirect") the request from example.com/post/sometitle to example.com/post/?sometitle.
However, you must have already changed all the URLs in your application to use the new URL format (without the query string). You shouldn't be using .htaccess alone for this.
I also assume that /post is a physical directory and that you are really serving index.php in that directory (mod_dir is issuing an internal subrequest to this file). So, instead of /post/?sometitle, it's really /post/index.php?sometitle?
For example:
RewriteEngine On
# Rewrite /post/sometitle to filesystem path
RewriteRule ^post/([\w-]+)$ /post/index.php?$1 [L]
So, now when you request /post/sometitle the request is internally rewritten and handled by /post/index.php?sometitle instead.
I have assumed that "sometitle" can consist of 1 or more of the characters a-z, A-Z, 0-9, _ and -. Hence the regex [\w-]+.
If this is a new site then you can stop there. However, if you are changing an existing URL structure that has already been indexed by search engines and linked to by external third parties then you'll need to redirect the old URLs to the new. (Just to reiterate, you must have already changed the URL in your application, otherwise users will experience repeated redirects as they navigate your site.)
To implement the redirect, you can add something like the following before the above rewrite:
# Redirect any "stray" requests to the old URL
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ([\w-]+)
RewriteRule ^post/$ /post/%1 [R=302,NE,QSD,L]
The check against the REDIRECT_STATUS environment variable is to ensure we only redirect "direct requests" and thus avoiding a redirect loop.
(Change to 301 only when tested as OK, to avoid caching issues.)
In Summary:
RewriteEngine On
# Redirect any "stray" requests to the old URL
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ([\w-]+)
RewriteRule ^post/$ /post/%1 [R=302,NE,QSD,L]
# Rewrite /post/sometitle to filesystem path
RewriteRule ^post/([\w-]+)$ /post/index.php?$1 [L]
UPDATE: If you have multiple URLs ("folders") that all follow the same pattern, such as /post/<title>, /home/<title> and /build/<title> then you can modify the above to cater for all three, for example:
# Redirect any "stray" requests to the old URL
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ([\w-]+)
RewriteRule ^(post|home|build)/$ /$1/%1 [R=302,NE,QSD,L]
# Rewrite /post/sometitle to filesystem path
RewriteRule ^(post|home|build)/([\w-]+)$ /$1/index.php?$2 [L]
Aside: (With my Webmasters hat on...) This is not really much of an "improvement" to the URL structure. If this is an established website with many backlinks and good SE ranking then you should think twice about making this change as you could see a dip in rankings at least initially.
If only changing from query is your requirement then try with below, we are using QSD flag to discard our query string after our rule matched.
RewriteCond %{QUERY_STRING} ([^\s&]+) [NC]
RewriteRule ^ /post/%1 [R=302,L,NE,QSD]

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]

Rewriting Dynamic URLs in htaccess not working

I want to rewrite
mypage.com/country/country.php?country=something
to
mypage.com/country/something
in the address bar, using htaccess
I've tried many things and looked everywhere and the closest I've got is:
RewriteCond %{QUERY_STRING} country=([^\&]*)
RewriteRule ^country.php$ /country/%1? [R,L]
But this just produces a rewrite loop that alternates between the two links above and I don't understand why.
I want both
mypage.com/country.php?country=something
and
mypage.com/country/something
when entered, to show
mypage.com/country/something
in the address bar
Any help?
If you have a rewrite loop it suggests that besides that rule, you also have a rule that translates it back. You'll need the 'ugly' url to only trigger when it is an external request. The easiest way to do that is by matching %{THE_REQUEST}.
#Ugly to fancy url; should be R=301 when it works
RewriteCond %{THE_REQUEST} ^(GET|POST)\ /country\.php\?country=([^\&]*)\ HTTP
RewriteRule ^country.php$ /country/%2? [R,L]
RewriteRule ^country/(.*)/?$ /country.php?country=$1 [L]

htaccess redirect old URL to new URL

On my website for SEO purpose the link to hotel.php?hotel_id=104 is changed to parkgrand.html
and changed htaccess to refer to the same script
code : RewriteRule ^parkgrand\.html$ /hotel.php?hotel_id=104
Till this it works fine. But I want if some user still accesses the old url i.e. hotel.php?hotel_id=104 then he should get automatically redirected to parkgrand.html and user agent should get a response 301
So, the code now becomes
RewriteCond %{REQUEST_URI} ^/hotel.php
RewriteCond %{QUERY_STRING} ^hotel_id=104
RewriteRule ^hotel.php /parkgrand.html [L,R=301]
RewriteRule ^parkgrand\.html$ /hotel.php?hotel_id=104
But this is causing a redirect loop and the intended page doesn't gets displayed to the user.
Can anyone tell me what should be the correct code for this.
Give this a try:
# Redirect /hotel.php?hotel_id=104 to /parkgrand.html
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+hotel\.php\?hotel_id=104[&\s] [NC]
RewriteRule ^ /parkgrand.html? [R=302,L]
Change from R=302 to R=301 once you confirm it is working to avoid caching.
Keep in mind you may have been cached from your previous attempts since you're using R=301, I will recommend you to test the above using a different browser to make sure its working in case your usual browser is cached.

.htaccess and SEO URLs - why is this an infinite loop?

I have a dirty URL like this: http://www.netairspace.com/photos/photo.php?photo=3392.
I want to do something like http://www.netairspace.com/photos/OH-LTU/Finnair_Airbus_330-202X/OUL_EFOU_Oulu/photo_3392/ (and later support short URLs like http://www.netairspace.com/pic/3392/ but I'll leave that out).
So I have a script photo_seo_url.php, which takes the photo ID, builds the SEO URL, and does a redirect (302 for testing, 301 when I'm happy with it). I then planned to add .htaccess mod_rewrite rules so that on calling the old URL:
the old URL would be rewritten internally to photo_seo_url.php
photo_seo_url.php would 301/302 redirect to the SEO URL
the SEO URL would be rewritten internally to the original photo.php
That way I would, in theory, get the benefits of the SEO URL while being able to retire the old ones at my leisure.
These are the rules I used:
RewriteEngine on
RewriteRule ^photos/.*/photo_([0-9]+)/?$ photos/photo.php?photo=$1 [NC,L]
RewriteCond %{QUERY_STRING} photo=([0-9]+)
RewriteRule ^photos/photo\.php$ photos/photo_seo_url.php?photo=%1 [NC,L]
But that goes into an infinite redirect loop. Why, if these two are doing internal rewrites rather than external redirects - or is that what I'm missing?
I've solved the problem adding a new file showphoto.php, which does nothing but include the original photo.php, and changing line 2:
RewriteEngine on
RewriteRule ^photos/.*/photo_([0-9]+)/?$ photos/showphoto.php?photo=$1 [NC,L]
RewriteCond %{QUERY_STRING} photo=([0-9]+)
RewriteRule ^photos/photo\.php$ photos/photo_seo_url.php?photo=%1 [NC,L]
But I'd still like to understand why the original version goes into an infinite loop. I've missed or misunderstood something. Is my approach sound?
To answer your question, why does this loop occur? This is what happens with an SEO URI, with a GET /photos/OH-LTU/Finnair_Airbus_330-202X/OUL_EFOU_Oulu/photo_3392/, say.
Rule 1 fires converting this to a GET /photos/photo.php?photo=3392 which triggers an internal redirect which then restarts the scan of the .htaccessfile.
Rule 2 then fires converting this to a GET photos/photo_seo_url.php?photo=339 which triggers an internal redirect which again restarts the scan of the .htaccessfile.
No further matches occur and hence this is passed to the script photos/photo_seo_url.php which then does a 302 to /photos/OH-LTU/Finnair_Airbus_330-202X/OUL_EFOU_Oulu/photo_3392/ and the browser detects a redirection loop.
What you need happen is for rule 1 firing to prevent rule 2 firing even after an internal redirect. One way to do this is to set an environment variable, say END (which gets converted to REDIRECT_END on the next pass) and to skip the rules if this is set:
RewriteEngine on
RewriteBase /
RewriteRule ^photos/.*/photo_([0-9]+)/?$ photos/photo.php?photo=$1 [NC,E=END:1,L]
RewriteCond %{ENV:REDIRECT_END}:%{QUERY_STRING} ^:photo=([0-9]+)$
RewriteRule ^photos/photo\.php$ photos/photo_seo_url.php?photo=%1 [NC,L]
An alternative approach is to add a dummy noredir parameter to the rewritten URI and add a:
RewriteCond %{QUERY_STRING} !\bnoredir
to the original second rule. However, photo.php would need to ignore this. Hope this helps :-)
RewriteEngine on
RewriteRule ^photos/.*/photo_([0-9]+)/?$ photos/photo.php?photo=$1&rewritten [NC,L]
RewriteCond %{QUERY_STRING} !rewritten
RewriteCond %{QUERY_STRING} photo=([0-9]+)
RewriteRule ^photos/photo\.php$ photos/photo_seo_url.php?photo=%1 [NC,L]

Resources