Nginx proxy theo phương thức yêu cầu


17

Có thể / làm cách nào tôi có thể định cấu hình khối vị trí Nginx thành proxy cho các phụ trợ khác nhau tùy thuộc vào phương thức yêu cầu (ví dụ: GET / POST) không?

Lý do là, tôi hiện đang xử lý 2 phương thức tại 2 URL khác nhau (một qua http proxy và một qua fcgi) và đang cố gắng làm cho nó trở nên "REST" hơn, vì vậy, lý tưởng là NHẬN tài nguyên để trả về danh sách , trong khi POST vào cùng một tài nguyên nên thêm vào danh sách.

Câu trả lời:


27

Tôi không sử dụng cấu hình này, nhưng dựa trên các ví dụ ở đây :

location /service  {
  if ($request_method = POST ) {
    fastcgi_pass 127.0.0.1:1234;
  }

  if ($request_method = GET ) {
     alias /path/to/files;
  }
}

Nếu bạn viết ứng dụng của riêng mình, bạn cũng có thể xem xét việc kiểm tra GET / POST trong đó và gửi các tiêu đề X-Accel-Redirect để chuyển giao các tệp tới nginx.


Khối GET là proxy_pass trong trường hợp của tôi, nhưng nếu không thì nó hoạt động. Hiện tại tôi không sử dụng khối if thứ hai, nginx dường như đang dừng "xử lý" khi đạt được lệnh fastcgi_pass (ví dụ: không rơi vào và chạy pass proxy) vì tôi muốn mọi thứ khác ngoài POST hoàn nguyên đến proxy.
Brenton Alker

2
Lưu ý rằng ifthường không được khuyến khích bởi tài liệu Nginx: nginx.com/resource/wiki/start/topics/depth/ifisevil
vog

1
Vậy thay thế bằng cái gì?
WM

1
@WM Xem câu trả lời của tôi: serverfault.com/a/823053/175421
vog

@vog, Thú vị. Cách khá thông minh để làm điều đó. Cám ơn vì đã chia sẻ.
WM

23

Mặc dù bạn có thể đạt được điều này với if, nhưng điều này thường không được khuyến khích bởi tài liệu Nginx , vì ifkhông chơi tốt với các chỉ thị khác. Ví dụ: giả sử rằng GET phải được mở cho tất cả mọi người, trong khi POST chỉ dành cho người dùng được xác thực, sử dụng HTTP Basic Auth. Điều đó sẽ cần ifphải được kết hợp với auth_basic, mà không hoạt động đúng.

Đây là một thay thế mà làm việc mà không có if. Mẹo nhỏ là sử dụng "GET" và "POST" như một phần của tên ngược dòng, vì vậy chúng có thể được giải quyết bằng cách thay thế biến:

http {
  upstream other_GET {
    server ...;
  }
  upstream other_POST {
    server ...;
  }
  server {
    location /service {
      proxy_pass http://other_$request_method;
    }
  }
}

Để kết hợp điều này với HTTP Basic Auth cho mọi thứ trừ GET, chỉ cần thêm một limit_exceptkhối:

  ...
    location /service {
      proxy_pass http://other_$request_method;
      limit_except GET {
        auth_basic ...;
      }
    }
  ...

Vấn đề với cách tiếp cận này là bây giờ chúng tôi sẽ quay lại 502 gateway errorno resolver defined to resolve other_HEAD(hoặc bất cứ điều gì ngược dòng của bạn là). Nó sẽ là ngữ nghĩa hơn để trả lại một cái gì đó như 405 method not allowed. Có cách nào để hoàn thành việc này?
James

1
@James: Có lẽ đây là một câu hỏi mới, đề cập đến câu hỏi này. Tôi không có câu trả lời cho chi tiết này, nhưng có lẽ những người khác cũng vậy.
vog

0

Đây là những gì tôi đã làm để làm cho mọi thứ làm việc cho tôi

add_header Allow "GET, POST, HEAD" always;
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
    proxy_pass http://back-end;
}

Hoe chính xác là chuyển đổi giữa hai điểm cuối dựa trên phương pháp yêu cầu?
Cơ bản

0

Thay đổi một chút về câu trả lời của vog để bao gồm một trình xử lý mặc định cho các phương thức khác như TÙY CHỌN, PUT, v.v.

    upstream webdav_default {
            server example.com;
    }
    upstream webdav_upload {
            server example.com:8081;
    }
    upstream webdav_download {
            server example.com:8082;
    }
    server {
            map upstream_location $request_method {
                    GET     webdav_download;
                    HEAD    webdav_download;
                    PUT     webdav_upload;
                    LOCK    webdav_upload;
                    default webdav_default;
            }
            location / {
                    proxy_pass https://$upstream_location;
            }
    }

0

Tôi không thể nhận được câu trả lời từ @timmmmmy để làm việc, nhưng nó chỉ cho tôi tài liệu bản đồ và điều này hiệu quả với tôi:

map $request_method $upstream_location {
   PUT     example.com:8081;
   POST    example.com:8081;
   PATCH   example.com:8081;
   default example.com:8082;
}
server {
   location / {
      proxy_pass https://$upstream_location;
   }
}
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.