Reputation: 165
I am trying to rewrite /index.html to / for SEO purposes (stupid search engines which confuse index.html with / and penalize for duplicate content) -- also to reconcile web analytics data.
I've tried every solution I've found on stackoverflow, nginx documentation, etc and have had no success. I'm thinking I must have some other configuration issue or something else painfully obvious. This is my first nginx installation -- used to Apache and IIS!!
Here is my default.conf:
server {
listen 80;
server_name web.local;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
Here is my virtual.conf (commented out section was my most recent attempt -- when uncommented it gives a 301 Moved Permanently error when you attempt to access www.domain.com/index.html):
server {
listen 80;
server_name www.domain.com;
location / {
root /var/www/html/domain.com;
index index.html;
#if ($request_uri = /index.html) {
# rewrite ^ http://www.domain.com permanent;
#}
}
}
server {
listen 80;
server_name domain.com;
rewrite ^/(.*) http://www.domain.com/$1 permanent;
}
HTTP Response Headers for cobaco's solution:
URL:
http://www.domain.com
http/1.1 301 moved permanently
server: nginx/1.2.8
date: Thu, 16 May 2013 01:42:58 GMT
content-type: text/html
content-length: 184
connection: keep-alive
location: http://domain.com/
Redirecting URL:
http://domain.com/
http/1.1 301 moved permanently
server: nginx/1.2.8
date: Thu, 16 May 2013 01:42:58 GMT
content-type: text/html
content-length: 184
connection: keep-alive
location: http://www.domain.com/
I figured that this line might be causing problems: "location = /index.html {return 301 $scheme://domain.com/;}" so I added www. after "scheme://" -- let me know if this is a bad thing to do! This resulted in the following HTTP Response Headers:
URL:
http://www.domain.com
http/1.1 301 moved permanently
server: nginx/1.2.8
date: Thu, 16 May 2013 01:42:58 GMT
content-type: text/html
content-length: 184
connection: keep-alive
location: http://www.domain.com/
Redirecting URL:
http://www.domain.com/
http/1.1 301 moved permanently
server: nginx/1.2.8
date: Thu, 16 May 2013 01:42:58 GMT
content-type: text/html
content-length: 184
connection: keep-alive
location: http://www.domain.com/
After some more tinkering, the following configuration does what I want it to do but is not ideal due to the if statement. Any suggestions?
server {
server_name www.domain.com;
root /var/www/html/domain.com;
index index.html;
if ($request_uri = /index.html) {
return 301 http://www.domain.com/;
}
#location = /index.html {
# return 301 $scheme://www.domain.com/;
#}
}
server {
listen 80;
server_name domain.com;
return 301 $scheme://www.domain.com$request_uri;
}
Upvotes: 16
Views: 26148
Reputation: 10546
The following will do what you want:
server {
server_name www.domain.com;
root /var/www/html/domain.com;
index index.html;
location = /index.html {return 301 $scheme://www.domain.com/;}
}
server {
listen 80;
server_name domain.com;
return 301 $scheme://www.domain.com$request_uri;
}
To note:
location
block instead of if
when possible (because if
inside a location
is known to cause problems see http://wiki.nginx.org/IfIsEvil for the details)return
not rewrite
for 301's (as it's more efficient)root
and index
directives should normally always be at the main level of the server
-block (else you need to repeat them for each sub-block)Upvotes: 0
Reputation: 9914
You final solution is totally fine.
if
directive is evil ONLY IF it is inside a location
block. Also you only have a return
directive inside the if
block. I don't see anything wrong with that. reference: http://wiki.nginx.org/IfIsEvil
The infinite redirect loop in cobaco's solution is because
index index.html;
triggers another round of location match. So nginx will be trapped into the location = /index.html
again after it's redirected to http://www.domain.com/
.
Upvotes: 12
Reputation: 42799
301 isn't really an error, It's just a header telling the browser that it needs to redirect to the new destination, web browsers handle those headers automatically and silently, but if you are writing some curl app then you should instruct it to respect and handle those headers.
And it's 301 because you write permanent
in the configuration, 302 is temporary
when i tried your rewrite it worked with me, but i used return instead of rewrite in the non redirecting server
location = /index.html {
return 301 $scheme://$host;
}
also it would be better if you change your redirecting server to use return as well
server {
server_name domain.com;
return 301 $scheme://www.domain.com$request_uri;
}
EDIT: changed the if block to location block like @cobaco suggested, I don't know why i missed such a silly mistake
Upvotes: 0