.htaccess slicing first two characters from GET for forwarding path - .htaccess

Hey guys I got a tricky one here, but I believe it will allow me to bypass the need for a PHP controller file for forwarding. I have a url that I hit example.com/ if it has no following sequence, it will route like this
#example.com
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^$ http://www\.example2\.com/?CampID=dm/DMdefault [R=301,L]
The question is the second redirect. If I want to slice the first two (alphanum) as one part of the forwarding url, and the next five as the second part, would this work?
RewriteMap lc int:tolower
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^(\w{2})(\w{5})$ http://www\.example2\.com/landing/external-marketing/direct-mail/${lc:$1}?CampId=${lc:$1$2} [R=301,L]
This *should normalize case, and forward http://example.com/BA025JD to
http://www.example2.com/landing/external-marketing/direct-mail/ba?CampId=ba025jd correct?

You can't use the RewriteMap directive inside an htaccess file, you need to define maps in server or vhost config. Unfortunately, apache chooses not to bring that to your attention. If you use a map that hasn't been defined, it just silently does nothing.
However, once that map has been defined, your rules work for me:
my request
GET /A1b2C3d HTTP/1.1
Host: example.com
apache's response, with the lc map defined
HTTP/1.1 301 Moved Permanently
Date: Mon, 15 Oct 2012 18:44:37 GMT
Server: Apache
Location: http://www.example2.com/landing/external-marketing/direct-mail/a1?CampId=a1b2c3d
Content-Length: 349
Content-Type: text/html; charset=iso-8859-1

Related

500 error for html site on shared hosting, is my .htaccess syntax wrong?

First time here. I'm actually an Industrial & Systems Engineer from Mexico, trying to become a self-taught Web Developer/Graphic Designer. I'M SORRY if my english is flawed & for being such a noob, especially if my question was already asked by someone else, or whatever. (I did search questions, though)
I just finished (out of a bought html template) the 1º stage of the website (& everything design wise) of a new company (which is my client): https://www.starhauss.com/
The site works fine... considering what was requested of me, considering it's the 1º stage, it has minor flaws... I think.
ANYWAY...
I need to do (& tried) several things with .htaccess for my client, ASAP:
Redirect to custom 404
Declare Spanish language (the site will soon have an english version on /en/ directory)
Block sensible Server info
Disable directory listings
Remove www from urls
Remove html file extensions from urls
Block hidden files from appearing
Block "risky" files from appearing
Force https on the urls
Check & correct simple spelling errors on urls
I researched the Apache guides & everything, from different sources & I came up with my own .htaccess file, but I'm not sure if the syntax is wrong, or if I need to contact the respective Hosting Support Guys so they allow my file to be executed, because when it's uploaded (RIGHT NOW IT'S NOT UPLOADED) with CyberDuck to the root directory encoding text via US-ASCII with 755 file permissions, accessing my site results in a 500 Internal Server Error. I don't know what modules are on by default on the server of the shared hosting company, but of what I understand, they do work with the Apache Platform.
My .htaccess code is the next
# redirect not found
ErrorDocument 404 /404.html
# declare language for multilingual sites, adding a .htaccess file for each language subdirectory
DefaultLanguage es
# prevent server from outputing sensible information
ServerSignature Off
# disable directory listings, only when on
Options -Indexes
# requirement to change urls & such
RewriteEngine On
# use in subdirectories if rewrite rules are not working properly
# RewriteBase /
# mod_rewrite.c wrapper works mainly with WordPress & such
# <IfModule mod_rewrite.c>
# remove www from urls
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
# remove html file extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC, L]
# block hidden files
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
# </IfModule>
# block risky files
<FilesMatch "(^#.*#|\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$">
Order allow,deny
Deny from all
Satisfy All
</FilesMatch>
# force https
<IfModule mod_headers.c>
Header set Strict-Transport-Security max-age=16070400;
</IfModule>
# check & correct url spelling errors, useful for SEO
<IfModule mod_speling.c>
CheckSeplling On
</IfModule>
So, what do you think guys? Should it work? Is something wrong with the code syntax, the order or whatever? Is something missing Server Side for the file to work & if so, how can I know, if I have no access to the Httpd.Conf? Should I get in contact with the shared hosting support for them to allow my file?
RewriteRule ^([^\.]+)$ $1.html [NC, L]
You have an erroneous space in the RewriteRule flags argument. This will result in a 500 Internal Server Error and if you look at your server's error.log you will see an error reported like "RewriteRule: bad flag delimiters".
Whenever you get a 500 error (which is just a generic server response), you need to check the server's error log for the details of that error.
In this case, [NC, L] should be [NC,L]. Although the NC flag is superfluous here, so [L] is sufficient.
<IfModule mod_speling.c>
CheckSeplling On
</IfModule>
You've spelt CheckSpelling wrong. (This would also trigger a 500 error response.)
Force https on the urls
# remove www from urls
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
You're not actually "forcing HTTPS" anywhere.
The above only removes www on HTTP only. Why are you specifically checking that the request is not HTTPS in the above www to non-www redirect and redirecting to HTTP, not HTTPS?
You could change the above to the following in order to remove www on HTTP and HTTPS (canonicalising HTTPS at the same time):
# Remove www (redirect to HTTPS)
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
And add an additional rule to force HTTPS (however, see note below about HSTS*1):
# Force HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# force https
<IfModule mod_headers.c>
Header set Strict-Transport-Security max-age=16070400;
</IfModule>
This doesn't strictly "force https".
This "HSTS header" instructs the browser to always request HTTPS, once the user has visited the site over HTTPS. It does nothing if the user has only visited the site over HTTP (hence the requirement to first redirect/force the user to HTTPS - see above). However, this is not complete - you need to redirect on the same host first (*1ie. reverse the two redirects above) and also set the header on the 301 redirect that removes www over HTTPS (this directive does not). And ideally you should avoid sending the header over plain HTTP (although that does not strictly matter, as the browser will simply ignore it).
I would avoid setting HSTS initially, until your site is working correctly over HTTPS. You should consider HSTS as a one-way trip, it is problematic to backtrack on this (max-age=16070400 will persist this for 6+ months for anyone who visits over HTTPS).
See the following related question on the CodeReview stack regarding HSTS implementation: https://codereview.stackexchange.com/questions/250805/hsts-recommendations-in-htaccess
Order allow,deny
Deny from all
Satisfy All
These are Apache 2.2 directives and are formerly deprecated on Apache 2.4. I assume you are using Apache 2.4 (Apache 2.2 was EOL almost 2 years ago). You should use the Apache 2.4 directives instead:
Require all denied

Clicking on my web in google results redirects me back to google

Im helping a friend out on a website which is created using an online platform powered by plesk and theres an issue when trying to access this web through google.
Writing the domain directly in the browser works fine but when accessing it through a google search it redirects the user back to google.
What could be the issue?
this is my .htaccess file
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
#HTTP-HTTPS
RewriteCond %{HTTPS} off
RewriteRule (.*) https://srad.wtf/es_ES/$1 [R=301,L,QSA]
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite all other queries to the front controller.
RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 307 ^/$ /index.php/
# RedirectTemp cannot be used instead
</IfModule>
</IfModule>
Ive removed the majority of the comments from the file to keep it clean
As stated in comments, there doesn't appear to be anything in your .htaccess file that would cause this redirect.
the redirect response ... appears to be coming from an Nginx server (possibly a front-end proxy), not Apache.
#MrWhite does that mean its something that I cant solve myself?
The Nginx server, from which the response is ultimately being served from/through (a front-end/caching proxy I suspect) is part of your server config - so you would expect to have some control over this - although "using an online platform" then maybe not?
However, the redirect(s) you are seeing may be coming from your application server/PHP (not Nginx or Apache). The problem isn't just with "Google Chrome" (as you have tagged) or even with Google SERPs. Any inbound link to the homepage is being 302 redirected back to itself (the HTTP Referer).
Not wanting to sound alarming, but this sort of redirect is quite typical of a site being hacked - as it is potentially damaging for SEO. Although since this only affects the homepage and is a 302 (temporary) redirect and you appear to have other language specific redirects in the application logic then this may just be a missconfiguration - although redirecting back to the "HTTP Referer" is quite a deliberate action!
For example, the following link to your homepage currently 302 redirects back to "this page"!
https://srad.wtf/
Workaround
Your site appears to be in two languages, as denoted by the first path segment, /en/ or /es_ES/ (default). The application logic appears to unconditionally redirect(302) to /es_ES/ if omitted (it is not deduced from the user's browser preferences or remembered for returning visitors).
You may be able to redirect to /es_ES/ early in .htaccess before the application kicks in. (By the same logic that requesting the HTTP homepage also works OK, since it is redirected to HTTPS early in .htaccess.)
Try the following, after the RewriteEngine directive:
RewriteRule ^$ https://example.com/es_ES/ [R=302,L]
Note that this is a "workaround", it doesn't fix the underlying problem.
Additionally...
#HTTP-HTTPS
RewriteCond %{HTTPS} off
RewriteRule (.*) https://srad.wtf/es_ES/$1 [R=301,L,QSA]
This HTTP to HTTPS redirect is not strictly correct, as it unconditionally prefixes the request with /es_ES/ even when a valid language code might already be present. eg. Request http://example.com/es_ES/about (HTTP) and you are redirected to https://example.com/es_ES/es_ES/about (404). etc.
The HTTP to HTTPS redirect should simply redirect to the same URL-path (resolve any other language/path issues elsewhere*1). For example, this should be written:
RewriteCond %{HTTPS} off
RewriteRule (.*) https://example.com/$1 [R=301,L]
The QSA (Query String Append) flag is not required since the query string (if any) is passed through by default, unless you create a new query string on the substitution string (the QSA flag would then be required to append the query string from the original request).
(*1 To some extent, the preceding "workaround" resolves the missing language code.)
Strictly speaking, the language should be defaulted conditionally based on the value of the Accept-Language HTTP request header - but this is best done in PHP, not .htaccess.

How do I set 410 for entire website?

We have a number of websites that have now been closed down and deleted however are still indexed in Google, even though they are returning a 404.
I want to set http 410 for everything on the domain, how would I do this in the htaccess? Use wildcards?
I want to set http 410 for everything on the domain
You can use this rule as your first rule in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?domain\.com$ [NC]
RewriteRule ^ - [L,R=410]
Don't forget to replace domain.com with your actual domain name.

How do I use htaccess to collect jsonp callback value

I have a url
api/something/json?callback=abc and I want to redirect it to
dothis.php?strEndPoint=something&callback=abc&format=json
The base htaccess I tried was:
RewriteRule ^api/(.)/(json)?callback=(.) client.php?strEndPoint=$1&callback=$3&format=($2)
Doesn't appear to work : p
tested
using .*
RewriteEngine On
RewriteCond %{QUERY_STRING} callback\=(.*)
RewriteRule /api/(.*)/(json) /client.php?strEndPoint=$1&callback=%1&format=$2 [R=301]
you can remove r=301 just for test
$ curl localhost/api/1111/json?callback=2222 -I
HTTP/1.1 301 Moved Permanently
Date: Fri, 01 Nov 2013 03:16:25 GMT
Server: Apache/2.2.24 (Unix) DAV/2 mod_ssl/2.2.24 OpenSSL/0.9.8y
Location: http://localhost/client.php?strEndPoint=1111&callback=2222&format=json

htaccess: how to redirect all pages to a holding page

I have to put a site down for about half an hour while we put a second server in place. Using .htaccess, how can I redirect ANY request to domain.com to domain.com/holding_page.php?
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_URI} !/holding_page.php$
RewriteRule $ /holding_page.php$l [R=307,L]
Use 307 (thanks Piskvor!) rather than 302 - 307 means:
The requested resource resides
temporarily under a different URI.
Since the redirection MAY be altered
on occasion, the client SHOULD
continue to use the Request-URI for
future requests.
As I came across this problem, here is the solution I used (brief explanations in the comments):
RewriteEngine On
RewriteBase /
# do not redirect when using your IP if necessary
# edit to match your IP
RewriteCond %{REMOTE_ADDR} !^1\.1\.1\.1
# do not redirect certain file types if necessary
# edit to match the file types needed
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif|css)
# this holding page that will be shown while offline
RewriteCond %{REQUEST_URI} !^/offline\.html$
# use 503 redirect code during the maintenance job
RewriteRule ^(.*)$ /offline.html [R=503,L]
ErrorDocument 503 /offline.html
# bots should retry accessing your page after x seconds
# edit to match your maintenance window
Header always set Retry-After "3600"
# disable caching
Header Set Cache-Control "max-age=0, no-cache, no-store"
Besides the additional conditions and headers, the main idea is to use a 503 status code when you are doing a maintenance job.
The 503 code stands for Service Unavailable, which is exactly the case during the maintenance. Using this will also be SEO friendly as the bots won't index the 503 pages, and they will come back later-on after the specified Retry-After to look for the actual content.
Read more details here:
Use a 503 HTTP status code (from a person who worked at Google) - https://plus.google.com/+PierreFar/posts/Gas8vjZ5fmB
Redirect Site to Maintenance Page using Apache and HTAccess - http://www.shellhacks.com/en/Redirect-Site-to-Maintenance-Page-using-Apache-and-HTAccess
HTTP 503: Handling site maintenance correctly for SEO - https://yoast.com/http-503-site-maintenance-seo/
This works better...
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_URI} !/holding_page.php$
RewriteRule $ /holding_page.php [R=307,L]

Resources