如何使用 nginx 不区分大小写地提供静态文件?

How do I serve static files case-insensitively with nginx?

我正在尝试使用 nginx 提供静态文件,并且我已经尝试将 ~* 添加到位置选项,但这似乎不适用于我正在尝试做的事情:服务文件与案例-不敏感。现在,如果 URL 的大小写与文件系统中的文件名不匹配,我会得到 404。

例如,我有一个文件 /usr/share/nginx/psimages/scripts/ajaxprogress.js,我可以通过转到 /scripts/ajaxprogress.js URL 来访问它,但我还需要通过转到 /scripts/ajaxprogress.js 来访问它,这目前给我一个 404 错误当我尝试加载它时。

这是我的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
server {
    error_log /var/log/nginx/ngerror.log debug;
    listen 80 default_server;
    listen [::]:80 default_server;

    root /usr/share/nginx/psimages;
    index index.html index.htm;

    # Make site accessible from http://localhost/
    server_name localhost;

    location ~* / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
        # Uncomment to enable naxsi on this location
        # include /etc/nginx/naxsi.rules

            # Wide-open CORS config for nginx
        if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        #
        # Om nom nom cookies
        #
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
         }
         if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
         }
         if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
         }
    }
}


来自权威的万维网联盟 URL 规范:

URLs in general are case-sensitive (with the exception of machine names). There may be URLs, or parts of URLs, where case doesn't matter, but identifying these may not be easy. Users should always consider that URLs are case-sensitive.

机器名称被豁免,因为域名系统在 §2.3.1 中早已定义了不区分大小写的名称。

没有非常令人信服的理由,您不应该违反 w3.org 规范,因为您永远不知道它会产生什么副作用。

例如,使用区分大小写的 URL 会混淆可能无法区分 ThisFile.htmlThisFile.html(或该名称的 144 个大小写变体)的缓存代理。因为,根据定义,您永远不应该知道您是否已经点击了缓存代理,或者其中有多少,这很可能会产生错误的文档。


使用股票 nginx 是不可能做到这一点的。

我认为这个想法是你最好知道你的文件的名称是什么。进行不区分大小写的文件搜索需要读取和遍历整个目录结构(例如,使用 readdir(3)),将每个文件条目与输入进行比较。想象一下该目录中有 1k 个文件;然后,这会导致对这些 1k 文件中的一半文件进行不区分大小写的比较,对于一个静态文件的请求(如果目录本身重复并相乘),这将是非常低效的也必须进行不区分大小写的搜索)。当文件(具有正确的大小写和路径)已知时,将其与对 open(2) 的单个调用进行比较。

因此,确保静态文件的情况匹配,而不是遭受如此戏剧性的性能下降(以及可能不得不使用某种缓存问题)。另一方面,如果您不关心提供静态内容的性能,您不妨将您的静态文件请求代理到另一个支持/鼓励这种低效操作的服务器。