How to do an Nginx redirect

转自于 https://bjornjohansen.no/nginx-redirect

    listen 80;
    listen [::]:80;
    hostname example.com www.example.com;
    return 301 https://example.com$request_uri;
}

Using regular expressions

If you need something more complex, don’t be afraid to use a regexp – they’re still extremely fast in Nginx:

rewrite ^/foo/(bar)/(.*)$ https://$server_name/$1/$2 permanent;

Replace permanent with redirect if you want a temporary (HTTP 302) redirect. Our full sample server block could then be:

server {
    listen 80;
    listen [::]:80;
    hostname example.com www.example.com;
    root /var/www/example.com/public;
    rewrite ^/foo/(bar)/(.*)$ $scheme://$server_name/$1/$2 permanent;
}

Using maps

If you have a list of URLs or regular expressions that you want to redirect differently, you ought to look into using a map, which you very well may define in a separate file for your convenience. Just note that the map definition must be outside the server block:

include redirect-map.conf;
server {
    […]
    if ( $redirect_uri ) {
        return 301 $redirect_uri;
    }
}

The file redirect-map.conf may then look something like this:

map $request_uri $redirect_uri {
    /about.html          /about-us;
    /customers.html      /our-customers;
    /products.html       /our-products;
}

Note the following excerpt from the docs:

A regular expression should either start from the “~” symbol for a case-sensitive matching, or from the “~*” symbols (1.0.4) for case-insensitive matching. A regular expression can contain named and positional captures that can later be used in other directives along with the resulting variable.

Here’s an example that might help you understand what that was about:

map $request_uri $redirect_uri {
    /about.html          /about-us;
    /customers.html      /our-customers;
    /products.html       /our-products;
    # Match any url that ends in products.html or producs.htm
    ~products\.html?$    /our-products;
    # case-insensitive version of the above
    ~*products\.html?$   /our-products;
    # A named capture that maps
    # e.g. product-1234.html into /products/item-1234/overview
    ~product-(?<sku>\d+)\.html   /products/item-$sku/overview;
}

Cute, huh? :-) Also please note that the variable name $redirect_uri have no special meaning: It is one I made up. You can name it whatever you like, but make sure the variable name in the map and the server block matches.

Some useful variables

I’ve used a few of these in the examples above, so you might have noticed them before. These are variables that comes predefined by Nginx, ready for you to use in your configs:
$scheme – The scheme used for the current request. E.g. “http” or “https”
$host – The hostname provided by the client for the current request.
$server_name – The first hostname from the hostname declaration in your config for the server block that responds to the request.
$request_uri – The full original request URI – with arguments.
$request_filename – The file path for the current request.

Here’s also the full list of predefined variables available in your Nginx config.

Some useful recipes for an Nginx redirect

HTTP to HTTPS

return 301 https://$host$request_uri;

Read more about HTTP to HTTPS redirects in Nginx here.

Canonical hostname

If the hostname doesn’t match the first name in the server_name list. Makes sure your content is only available at the canonical hostname, e.g. to avoid duplicate content issues. Excellent for redirecting non-www to www or redirecting www to non-www in Nginx as long as your server block is only for a single website.

server_name example.com www.example.com example.net www.example.net _;
if ( $host != $server_name ) {
    return 301 $scheme://$server_name$request_uri;
}

Nginx is very efficient, but please note that it would be more efficient to have two separate server blocks – one for the hostnames you want to redirect and one for the website. Then Nginx won’t have to do the comparison for every request.

Generic non-www/www redirects

If your server block covers multiple websites – e.g. a WordPress multisite network and you don’t want all of them to redirect to the same hostname, you can still do a universal check:

Redirect non-www to www:
if ( $host !~ ^www\. ) {
    return 301 $scheme://www.$host$request_uri;
}
Redirect www to non-www
if ( $host ~ ^www\.(?<domain>.+)$ ) {
    return 301 $scheme://$domain$request_uri;
}

For the www/non-www redirects, it is worth mentioning again that using separate server blocks, where one use the return statement described at the top, is by far the most efficient.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值