mod_rewrite help needed for 410 status code - .htaccess

I want to send 410 status code if there is any ? on the URL. Because the site is only works with SEO enabled URLs (Like www.domain.com/seo-enabled-urls).
With the StatckOverflow community support did this 301 redirection that works perfectly:
RewriteBase /
RewriteRule ^romance-package-two\.html$ http://www.domain.com/wedding-champagne [QSA,NC,R=301,L]
In the same way I want to add 410 message code that will tell Google (like search engines) permanently deleted so we wont have problem with SEO unknown or not found URLs.
If the URL looks like this
www.domain.com/seo-enabled-urls?param1=val1&param2=val2
I want to keep the same URL but just with that 410 code like this
RewriteCond %{query_string} ^(.*&)?$ [NC]
RewriteRule ^1$ same url code [QSA,NC,R=410,L]
Please help me.

You can't redirect with a HTTP 410 code -- 410 means that the requested page is permanently gone, and that there's no replacement:
410 Gone
The requested resource is no longer available at the server and no forwarding address is known. This condition is expected to be considered permanent. Clients with link editing capabilities SHOULD delete references to the Request-URI after user approval. If the server does not know, or has no facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) SHOULD be used instead. This response is cacheable unless indicated otherwise.
-- http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11
The corresponding definition for HTTP 301 indicates that it's already exactly what you wanted:
301 Moved Permanently
The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. This response is cacheable unless indicated otherwise.
-- http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2

The accepted answer is no longer correct at least as far back as Apache 2.0, where mod_rewrite supports a 410 GONE target:
'gone|G' (force URL to be gone)
This forces the current URL to be gone - it immediately sends back a HTTP response of 410 (GONE). Use this flag to mark pages which no longer exist as gone.
(see http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriterule)
That means that a rule such as you had above should simply be:
RewriteCond %{query_string} ^(.*&)?$ [NC]
RewriteRule ^1$ - [G]

Related

HTACCESS 301 redirect keep sending to the wrong page

I am trying to redirect an old page from a website I have redesigned, to the new one, but it's not working.
Here's my 2 lines of code in the .htaccess file regarding that domain:
Redirect 301 /deaneco http://solutionsgtr.ca/fr/deaneco/accueil.html
RewriteRule ^/deaneco/contact http://solutionsgtr.ca/fr/deaneco/contact.html [R=301,L,QSA]
If go on the solutionsgtr.ca/deaneco/contact URL, it gives me the following page:
http://solutionsgtr.ca/fr/deaneco/accueil.html/contact
The first rule works though (deaneco/ to solutionsgtr.ca/fr/deaneco/accueil.html).
I feel like both lines are being mixed together and are giving me the wrong page, that doesn't exist so I get a 404 error.
There are a couple of issues here:
The Redirect directive (part of mod_alias) is prefix-matching and everything after the match is appended on the end of the target URL. This explains the redirect you are seeing.
The RewriteRule (mod_rewrite) pattern ^/deaneco/contact will never match in a .htaccess context since the URL-path that is matched does not start with a slash. So, this rule is not doing anything currently.
You should avoid mixing redirects from both modules since they execute independently and at different times during the request (mod_rewrite executes first, despite the apparent order of the directives).
Either use mod_alias, ordering the directives most specific first:
Redirect 301 /deaneco/contact http://solutionsgtr.ca/fr/deaneco/contact.html
Redirect 301 /deaneco http://solutionsgtr.ca/fr/deaneco/accueil.html
NB: You will need to clear your browser cache, since the erroneous 301 (permanent) redirect will have been cached by the browser. Test with 302 (temporary) redirects to avoid potential caching issues.
OR, if you are already using mod_rewrite for other redirects/rewrites then consider using mod_rewrite instead (to avoid potential conflicts as mentioned above):
RewriteEngine On
RewriteRule ^deaneco/contact$ http://solutionsgtr.ca/fr/deaneco/contact.html [R=301,L]
RewriteRule ^deaneco$ http://solutionsgtr.ca/fr/deaneco/accueil.html [R=301,L]
The QSA flag is not required, since the query string is passed through to the substitution by default.
The order of the RewriteRule directives are not important in this instance, since they match just that specific URL.
If go on the solutionsgtr.ca/deaneco/contact URL
If you are redirecting to the same host then you don't need to explicitly include the scheme + hostname in the target URL, since this will default.

How to have two different custom error pages in .haccess?

1.
I have a .haccess file that requires you do be accessing from a certain IP address:
<RequireAll>
Require ip XX.XX.XX.XX.XX YY.YY.YY.YY.YY ZZ.ZZ.ZZ.ZZ.ZZ
</RequireAll>
If someone tries to access the website from a IP other then X, Y, or Z then they get an error 403 Forbidden page. I have customized it using the following:
ErrorDocument 403 /.forbidden.php
2.
If someone tries to access a restricted file in the same directory (even if they are from ip addresses X, Y, or Z) then again they prompted with the SAME custom 403 Forbidden page.
My Question
How can I have two different custom 403 Forbidden pages based on why they are forbidden from accessing? In example 1 the forbidden page would /.wrongip.php and in example 2 the forbidden page would /.restricted.php
If this is about the extent of what you are doing then it is fine but if you are going to be doing a lot of redirecting I would consider doing this in PHP, but I digress. You are going to have to use Apache (2.4) module mod_rewrite to rewrite rules and conditions for the IP restriction portion. I would leave your custom 403 Forbidden as is for handling the other cases of that status code. If you are on shared hosting this module is usually enabled by most hosting providers by default.
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^111.222.333.444$
RewriteRule ^(.*)$ /.wrongip.php [L]
You will likely avoid confusion if you keep rule rewrites up near the top of your .htaccess file. You only need the RewriteEngine On line once in your file. RewriteCond is one of the conditions for the rule immediately following. You could have multiple conditions mapped to a single rule (using [OR] flag; AND behavior is by default).
In this solution, the ^ character indicates the start of a string. Likewise, $ indicates the end. So, ^(.*)$ is a wildcard and would match any file accessed on your server. Preceded by a single space separator, the /.wrongip.php portion indicates your custom error page to be redirected to. [L] is the flag to indicate the Apache server should stop processing other rules once it matches that one. Use this unless you are using multiple rules to construct a single URL, otherwise you may cause yourself a headache.
There is an additional flag, [R], that I would suggest being aware of and trying to use when possible for easier use in maintaining good practice with HTTP response codes. These help with search rankings and I would recommend specifying a 403 response because by default it will throw a 302 error which can negatively effect ranking over time. Changing the rule to RewriteRule ^(.*)$ /.wrongip.php [R=403,L] would cause the Apache server to issue an HTTP redirect to the browser (to /.wrongip.php) and communicate a 403 Forbidden error in the header. Since my example has all pages redirecting to /.wrongip.php for non-whitelisted IPs, most likely even /.wrongip.php itself, I think in your specific case the [R] flag would result in an HTTP redirect loop where they would keep requesting /.wrongip.php. In this case you should omit the [R] flag, this will cause the Apache server to do an internal redirect.
Without the [R] flag, the client won't have any idea that this redirect went on (hence internal), so you should still emulate the error code in the header of your /.wrongip.php file using PHP.
I have not tested it, but I assume something like
<Directory /var/www/mysite>
ErrorDocument 403 /.restricted.php
<RequireAll>
Require ip XX.XX.XX.XX.XX YY.YY.YY.YY.YY ZZ.ZZ.ZZ.ZZ.ZZ
ErrorDocument 403 /.wrongip.php
</RequireAll>
</Directory>
could do the trick.
Have a look at
https://httpd.apache.org/docs/trunk/custom-error.html and https://httpd.apache.org/docs/trunk/mod/core.html#errordocument for more information on how such configurations work.

301 Redirect Rules for a Blog Migration

I want to implement 3 redirect rules for a blog migration where each page will be shifted to a sub-folder structure. It currently sits at a sub-domain.
I can't really screw this one up and want to make sure I nail the correct generic rules for the 3 type of existing URLs:
Homepage
Current:
https://blog.lang.example.com
Goal:
https://www.example.com/lang-country/news/
Category
Current:
https://blog.lang.example.com/category/category-name
Goal:
https://www.example.com/lang-country/news/category/category-name
Post
Current:
https://blog.lang.example.com/yyy/mm/dd/article-name
Goal:
https://www.example.com/lang-country/news/yyy/mm/dd/article-name
Is this something you can help?
Unless you have other URLs that you don't want to be redirected then you can do something like what you require with a single redirect near the top of the .htaccess file in the subdomain's document root.
For example:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^blog\.([^.]+)\.example\.com [NC]
RewriteRule (.*) https://www.example.com/%1-country/news/$1 [R,L]
Where %1 is a backreference to the lang subdomain in the requested host.
However, you still have the problem of where country should come from in the target URL, since this is not present in the source URL. You will either need to default this to something or implement some kind of lookup based on the language. This would need server config access (to configure a RewriteMap) if you wanted to do this in .htaccess. Or, you implement this redirect entirely in your server-side script (eg. PHP).
Note that this is currently a 302 (temporary) redirect. Only change this to a 301 (permanent) redirect once you have tested that everything is working OK (if a 301 is required). 301 redirects are cached hard by the browser so can make testing problematic.

Preserve Requested Protocol in Sub-Directory with .htaccess

We have a http > https redirect on our 'top' level:
example.com/top/
Now for a sub-directory of /top/:
example.com/top/sub/
I want to preserve whatever protocol is requested there.
So if it's http://example.com/top/sub/this.php I want it to stay as 'http'
And if it's https://example.com/top/sub/this.php I want it to stay as 'https'
Currently I have an .htaccess file in the /top/sub/ directory with:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,END]
Which is doing exactly what I need it to be doing, so in terms of all the requests being sent to the sub-directory it's perfect.
The issue is I'm getting an error message in the error_log reporting this:
[REWRITE] detected external loop redirection with target URL: http://example.com/top/sub/this.php, skip.
I understand why I'm getting this message, because every time a HTTP request is made it's matching this condition, I just don't know how to stop it. I tried using the 'END' parameter to force only one redirect - but this doesn't seem to be working, or at least not working the way I expected it to.
All I want is for the protocol to remain the same as requested for /top/sub/ - the issue is the /top/ redirect sending everything to HTTPS.
Is this possible?
I would be interested to know if there is actually a way to preserve a protocol without creating a loop, however I was able to achieve what I was after by just adjusting the redirect in /top/ to only redirect pages that didn't match /top/sub/ - I really should have thought of that as a solution earlier.
Hope that can help someone.

301 redirect ?cat=

Google Webmaster Tools are constantly showing this version of my domain name:
mysite.co.uk/?cat=
I have disallowed every URL with ? in it and the above shows under the Crawl errors: URL restricted by robots.txt
I simply don't know why is that happening when I've got the following in my .htaccess file:
RewriteCond %{QUERY_STRING} ^cat=$ [NC]
RewriteRule ^(.*)$ http://misite.co.uk/? [R=301,L]
I thing the above is supposed to 301 redirect:
mysite.co.uk/?cat=
to:
mysite.co.uk/
and also if I click the first URL it actually goes to the second one in the browser.
I've got a couple more similar issues with ? URLs and I'll be really happy if somebody tells me how to properly 301 redirect them in order to show Google that these have been permanently removed and stop them from being crawled.
The appropriate HTTP response status code to tell a resource has been permanently removed would be 410 Gone:
The requested resource is no longer available at the server and no forwarding address is known. This condition is expected to be considered permanent. Clients with link editing capabilities SHOULD delete references to the Request-URI after user approval. […]
Sending this response status code will make search engines remove the requested URI from the index. But they might be crawled after all if there still are links with that URI.

Resources