Cách phân phát trực tiếp tất cả các tệp tĩnh hiện có bằng NGINX, nhưng ủy quyền phần còn lại cho máy chủ phụ trợ.


87
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    if (-f $request_filename) {
        access_log off;
        expires 30d;
        break;
        }

    if (!-f $request_filename) {
        proxy_pass http://127.0.0.1:8080; # backend server listening
        break;
        }
    }

Ở trên sẽ phục vụ trực tiếp tất cả các tệp hiện có bằng Nginx (ví dụ: Nginx chỉ hiển thị mã nguồn PHP), nếu không sẽ chuyển tiếp một yêu cầu đến Apache. Tôi cần loại trừ các tệp * .php khỏi quy tắc để các yêu cầu cho * .php cũng được chuyển tới Apache và được xử lý.

Tôi muốn Nginx xử lý tất cả các tệp tĩnh và Apache để xử lý tất cả các nội dung động.

CHỈNH SỬA: Có cách tiếp cận danh sách trắng, nhưng nó không phải là rất thanh lịch, Hãy xem tất cả các phần mở rộng đó, tôi không muốn điều này.

location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
    access_log off;
    expires 30d;
    }
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
    }

CHỈNH SỬA 2: Trên các phiên bản mới hơn của Nginx, hãy sử dụng try_filesthay thế http://wiki.nginx.org/HttpCoreModule#try_files


Chỉ để xóa mọi thứ: đoạn mã trên sẽ phục vụ một tệp tĩnh nếu nó tồn tại trên đĩa, nếu tệp không tồn tại, yêu cầu được chuyển tới Apache. Điều này hầu hết hoạt động vì tất cả các URL trong ứng dụng của tôi sử dụng mod_rewrite (hoặc định tuyến) và không thực sự tồn tại trên đĩa. Chỉ có quyền truy cập trực tiếp vào tên tệp * .php là ngoại lệ và cần được phân tích cú pháp bởi Apache.
fmalina

Câu trả lời:


152

Sử dụng try_files và khối vị trí được đặt tên ('@apachesite'). Thao tác này sẽ xóa kết hợp regex không cần thiết và nếu khối. Hiệu quả hơn.

location / {
    root /path/to/root/of/static/files;
    try_files $uri $uri/ @apachesite;

    expires max;
    access_log off;
}

location @apachesite {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Cập nhật: Giả định của cấu hình này là không tồn tại bất kỳ tập lệnh php nào bên dưới /path/to/root/of/static/files. Điều này là phổ biến trong hầu hết các framework php hiện đại. Trong trường hợp các dự án php kế thừa của bạn có cả tập lệnh php và tệp tĩnh được trộn trong cùng một thư mục, bạn có thể phải đưa vào danh sách trắng tất cả các loại tệp mà bạn muốn nginx phân phát.


Tôi đang sử dụng wordpress, vậy tôi có cần đặt thư mục tải lên trên máy chủ nginx không?
Chameron

7
Vấn đề của tôi với giải pháp này: nginx không sử dụng vị trí khác (proxy) và cố gắng hiển thị danh sách thư mục. Vì vậy, nó ném 403 vì danh sách thư mục không được kích hoạt. Chỉnh sửa: Ok nếu bạn loại bỏ $uri/thì nó hoạt động.
ChristophLSA

1
Điều này sẽ proxy / example tới apache nhưng cho phép tải xuống /example.php.
Terence Johnson

1
@TerenceJohnson Không an toàn khi đặt các tệp php của bạn trong thư mục tệp tĩnh. Lưu ý rằng tôi đã đặt root /path/to/root/of/*static*/files;. Các tệp php nên được đặt trong một thư mục khác, không thể truy cập trực tiếp từ internet.
Chuan Ma

2
Tôi biết đó là cách mọi thứ nên diễn ra, nhưng nếu ai đó đang đặt Nginx trước bất kỳ ứng dụng PHP phổ biến nào có sẵn mọi thứ dưới gốc web và dựa trên tệp .htaccess, họ không nên sao chép và dán cấu hình của bạn.
Terence Johnson,

18

Thử đi:

location / {
    root /path/to/root;
    expires 30d;
    access_log off;
}

location ~* ^.*\.php$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Hy vọng rằng nó hoạt động. Biểu thức chính quy có mức độ ưu tiên cao hơn so với chuỗi đơn giản, vì vậy tất cả các yêu cầu kết thúc bằng .phpphải được chuyển cho Apache nếu chỉ có một .phptệp tương ứng tồn tại. Phần còn lại sẽ được xử lý dưới dạng tệp tĩnh. Thuật toán đánh giá vị trí thực tế là ở đây .


6

Nếu bạn sử dụng mod_rewrite để ẩn phần mở rộng của các tập lệnh của mình hoặc nếu bạn chỉ thích các URL đẹp có kết thúc bằng /, thì bạn có thể muốn tiếp cận điều này từ hướng khác. Yêu cầu nginx cho phép bất kỳ thứ gì có phần mở rộng không tĩnh chuyển vào apache. Ví dụ:

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$
{
    root   /path/to/static-content;
}

location ~* ^!.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Tôi đã tìm thấy phần đầu tiên của đoạn mã này tại: http://code.google.com/p/scalr/wiki/NginxStatic


Điều này hoạt động tốt, mặc dù tôi vẫn gặp lỗi đối với các tệp được rút gọn (ví dụ: site.min.css và main.min.js, v.v.). Làm thế nào để tôi bắt được những thứ đó ở một vị trí regex? @lo_fye
Garth
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.