Trước hết, của bạn ^/(123[0-9])$
regex sẽ chỉ khớp /1234
URI (hoặc /1230
, /1231
, v.v.) nhưng không phải là /1234/một số/đường dẫn
vì bạn đang sử dụng $
neo cuối chuỗi. Tôi cho rằng đó không phải là lỗi mà là giải pháp thiết kế. Nếu không, để phù hợp với cả hai /1234
và /1234/một số/đường dẫn
(nhưng không giống như /12345
), bạn có thể sử dụng cách thay thế: ^/(123[0-9])(?:/|$)
(Tôi đang sử dụng một nhóm không chụp (?:...)
ở đây, vì nó được coi là có hiệu suất tốt hơn một chút so với nhóm chụp).
Cấu hình của bạn có rất nhiều lỗi khác nhau. Hãy xem xét từng người một.
Sai lầm #1: Không chính xác viết lại ... cuối cùng;
cách sử dụng.
Thật vậy, bạn không thể chỉ định một URI cho proxy_pass
ngược dòng giống như bạn đang cố gắng thực hiện với dấu gạch chéo
proxy_pass http://localhost:$1/; # thêm dấu gạch chéo không cho phép
bên trong các vị trí khớp regex (cũng như bên trong các vị trí được đặt tên) và cách duy nhất để thay đổi URI sẽ được chuyển đến phần phụ trợ là sử dụng viết lại
chỉ thị. Tuy nhiên, cách đúng để thay đổi URI bên trong địa điểm
khối để xử lý nó sau trong cùng một vị trí là sử dụng viết lại... phá;
từ viết lại ... cuối cùng;
sẽ buộc nginx tìm kiếm một vị trí mới cho URI đã viết lại. Điều đó có nghĩa là chúng ta cần sử dụng nghỉ
cờ cho viết lại
chỉ thị:
viết lại ^/[0-9]{4}(.*)$ $1 break;
Hãy coi chừng! Không có chỉ thị từ ngx_http_rewrite_module
sẽ được thực hiện sau viết lại... phá;
(hoặc đơn giản nghỉ;
) chỉ thị (cập nhật: sau một số thử nghiệm, ngược lại với những gì được nói trong tài liệu, hóa ra nó chỉ đúng với nghỉ
chỉ đạo nhưng không phải là viết lại ... phá vỡ
one, ít nhất là cho OpenResty 1.17.8.2 dựa trên lõi nginx 17.8).
Sai lầm #2: Bạn nên trích dẫn bất kỳ chuỗi nào chứa dấu ngoặc nhọn nếu không chúng sẽ được coi là khối cấu hình nginx.
Lệnh trước sẽ cho chúng tôi lỗi sau:
nginx: [emerg] chỉ thị "viết lại" không bị chấm dứt bởi ";"
Để loại bỏ lỗi này, chúng tôi cần mã hóa mẫu biểu thức chính quy của mình do việc sử dụng dấu ngoặc nhọn:
viết lại "^/[0-9]{4}(.*)$" $1 break;
Sai lầm #3: Các ảnh chụp được đánh số bị ghi đè bất cứ khi nào biểu thức chính quy được đánh giá.
Giả sử bạn có URI là /1234
:
vị trí ~ ^/(123[0-9])$ {
# Ở đây giá trị của biến '$1' là "1234"
viết lại "^/[0-9]{4}(.*)$" $1 break;
# Ở đây giá trị của biến '$1' là một chuỗi rỗng!
proxy_pass http://localhost:$1; # Sẽ không có cổng cho chỉ thị 'proxy_pass'
}
Bạn có thể lưu nó $1
giá trị trước khi quy tắc viết lại đánh giá biểu thức chính quy của chính nó bằng cách sử dụng bộ
chỉ thị:
vị trí ~ ^/(123[0-9])$ {
đặt cổng $1;
viết lại "^/[0-9]{4}(.*)$" $1 break;
proxy_pass http://localhost:$port;
}
hoặc tốt hơn là sử dụng nhóm chụp có tên:
vị trí ~ ^/(?<port>123[0-9])$ {
viết lại "^/[0-9]{4}(.*)$" $1 break;
proxy_pass http://localhost:$port;
}
Đôi khi không thể có giải pháp nào khác ngoài việc sử dụng các ảnh chụp được đặt tên, một ví dụ tuyệt vời về tình huống như vậy được đưa ra tại cái này chủ đề.
Sai lầm #4: URI viết lại không thể là một chuỗi rỗng.
Một lần nữa, giả sử bạn có URI là /1234
. Sau quy tắc viết lại, một nginx nội bộ $uri
biến sẽ có giá trị rỗng. Điều đó sẽ dẫn đến lỗi Máy chủ nội bộ HTTP 500 và trong nhật ký lỗi nginx, bạn sẽ thấy thông báo lỗi sau:
URI được viết lại có độ dài bằng không
Để giải quyết lỗi đó, chỉ cần viết lại bất kỳ URI nào vào /
:
vị trí ~ ^/(?<port>123[0-9])$ {
viết lại ^ / ngắt;
proxy_pass http://localhost:$port;
}
Nếu bạn muốn phục vụ bất kỳ /<số_cổng>/một số/đường dẫn
yêu cầu như trên, bạn nên sử dụng khối vị trí sau để đảm bảo URI được viết lại của bạn bắt đầu bằng dấu gạch chéo:
vị trí ~ ^/(?<port>123[0-9])(?:/|$) {
viết lại "^/\d{4}(?:/(.*))?" /$1 phá vỡ;
proxy_pass http://localhost:$port;
}
Sai lầm #5: Bạn cần chỉ định trình phân giải khi sử dụng các biến với proxy_pass
chỉ thị.
Cấu hình trên gần với giải pháp làm việc. Tuy nhiên, nó vẫn không hoạt động được, gây ra lỗi HTTP 502 Bad Gateway. Bạn cần chỉ định một người giải quyết
khi bạn đang sử dụng các biến với proxy_pass
và ngược dòng của bạn được chỉ định bởi tên miền chứ không phải địa chỉ IP, nếu không, bạn sẽ gặp lỗi sau trong nhật ký lỗi nginx của mình:
không có trình phân giải nào được xác định để giải quyết localhost
Nói chung, bạn phải sử dụng một cái gì đó như
bộ giải quyết 8.8.8.8;
vị trí ~ ^/(?<port>123[0-9])$ {
viết lại ^ / ngắt;
proxy_pass http://localhost:$port;
}
nhưng vì thượng nguồn của bạn là máy chủ cục bộ
, bạn có thể chỉ định địa chỉ IP của nó thay vì tên miền, theo cách này bạn sẽ không cần điều đó người giải quyết
chỉ thị ở tất cả:
vị trí ~ ^/(?<port>123[0-9])$ {
viết lại ^ / ngắt;
proxy_pass http://127.0.0.1:$port;
}
Cấu hình này phải hoàn toàn khả thi (cuối cùng). Và một lần nữa, nếu bạn cần phục vụ bất kỳ /<số_cổng>/một số/đường dẫn
yêu cầu như trên, thay vào đó, bạn nên sử dụng khối vị trí sau:
vị trí ~ ^/(?<port>123[0-9])(?:/|$) {
viết lại "^/\d{4}(?:/(.*))?" /$1 phá vỡ;
proxy_pass http://127.0.0.1:$port;
}