从 Apache 到 Nginx:使用通配符子域名进行复杂重写

从 Apache 到 Nginx:使用通配符子域名进行复杂重写

我正在从 Apache 转换到 Nginx,并试图弄清楚如何让我的子域重写规则发挥作用。

阿帕奇

我使用的 Apache 配置基本上将所有流量移至 HTTPS,并将 .net 和 .org 域更改为主 .com 域。我们的一些用户仍然认为每个 URL 都应以“www”开头,因此如果还有另一个子域,设置会将其删除。没有任何子域的 URL 将被重定向到https://www.example.com这对于网站的运行来说并不是必需的。

# HTTP
<VirtualHost *:80>
    RewriteEngine on

    # Redirect http://example.tld -> https://www.example.com
    RewriteCond %{SERVER_PORT} !^443$
    RewriteCond %{HTTP_HOST} ^example\.(com|net|org)
    RewriteRule ^(.*)$ https://www.example.com$1

    # Redirect http://www.subdomain.example.tld -> https://subdomain.example.com
    RewriteCond %{SERVER_PORT} !^443$
    RewriteCond %{HTTP_HOST} ^www.([^\.]+)\.example\.(com|net|org)
    RewriteRule ^(.*)$ https://%1.example.com$1

    # Redirect http://subdomain.example.tld -> https://subdomain.example.com
    RewriteCond %{SERVER_PORT} !^443$
    RewriteCond %{HTTP_HOST} ^([^\.]+)\.example\.(com|net|org)
    RewriteRule ^(.*)$ https://%1.example.com$1 [NC,R,L]

    # ...

</VirtualHost>

# HTTPS
<VirtualHost *:443>
    RewriteEngine on

    # Redirect https://example.tld -> https://www.example.com
    RewriteCond %{HTTP_HOST} ^example\.(com|net|org)
    RewriteRule ^(.*)$ https://www.example.com$1

    # Redirect https://www.subdomain.example.tld -> https://subdomain.example.com
    RewriteCond %{HTTP_HOST} ^www.([^\.]+)\.example\.(com|net|org)
    RewriteRule ^(.*)$ https://%1.example.com$1

    # Redirect https://subdomain.example.(net|org) -> https://subdomain.example.com
    RewriteCond %{HTTP_HOST} ^([^\.]+)\.example\.(net|org)
    RewriteRule ^(.*)$ https://%1.example.com$1 [NC,R,L]

    # Otherwise serve https://subdomain.example.com

    # ...

</VirtualHost>

Nginx

到目前为止,我的 Nginx 配置在大多数情况下都有效,但我不知道如何在 URL 格式为 http(s)://www.subdomain.example.tld 时删除“www”。根据https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#server-name-if“如果是邪恶的”,所以我试图将它们排除在最常见的用例之外。

# Redirect http://subdomain.example.com -> https://subdomain.example.com
# Redirect http://example.com -> https://example.com
server {
    listen       80;
    server_name  .example.com;
    return       301 https://$host$request_uri;
}

# Redirect https://subdomain.example.(net|org) -> https://subdomain.example.com
server {
    listen       80;
    server_name  .example.net .example.org;
    if ($host ~* "^([^.]+(\.[^.]+)*)\.example\.(net|org)$") {
            set $subdomain $1;
            rewrite ^(.*)$ https://$subdomain.example.com$1 permanent;
            break;
    }
    return 301 https://www.example.com;
}

# Otherwise serve https://subdomain.example.com
server {
    listen       443 ssl;
    server_name  .example.com;

    # ...
}

所以我的问题是,当另一个子域名已经以正确的 Nginx 方式存在时,我该如何删除“www”部分?在最佳情况下,Nginx 配置应该与我的旧 Apache 配置的工作方式相同。有许多问题和答案涵盖了可以在配置文件中手动列出子域名的简单情况。这对我来说不是一个选择。

答案1

意识到这一点之后server_name 也可以是正则表达式这就是我现在所拥有的。另一个惊喜是,同一个块可以处理 HTTP 和 HTTPS 情况。我只需要从配置文件中server注释掉该行。据我所知,此设置似乎与我的旧 Apache 配置一样工作。ssl on;ssl.inc

# Redirect http://example.tld -> https://www.example.com
server {
    listen       80;
    server_name  www.example.com www.example.net www.example.org;
    return       301 https://www.example.com$request_uri;
}

# Redirect http(s)://example.tld -> https://www.example.com
server {
    listen       80;
    listen       443 ssl;
    server_name  example.com example.net example.org;
    return       301 https://www.example.com$request_uri;

    include conf.d/ssl.inc;
}

# Serve https://subdomain.example.com
server {
    listen       443 ssl;
    server_name  ~^[^\.]+\.example\.com$;

    include conf.d/ssl.inc;
    include conf.d/common.inc;
}

# Redirect http(s)://www.whatever.subdomain.example.tld -> https://subdomain.example.com
server {
    listen       80;
    listen       443 ssl;
    server_name  ~\.(?<subdomain>[^\.]+)\.example\.(com|net|org)$  ~^(?<subdomain>[^\.]+)\.example\.(net|org)$;
    return       301 https://$subdomain.example.com$request_uri;

    include conf.d/ssl.inc;
}

相关内容