2011-06-20 26 views
7

Tôi có một WSGI ứng dụng (một dự án Django) chạy dưới gunicorn trên 127.0.0.1:18731 và tôi sử dụng Apache với mod_proxy để chuyển hướng yêu cầu từ http://example.com/my-project/* để http://127.0.0.1:18731/*. Các tệp tĩnh được lưu trữ bên ngoài /my-project/. Nếu ứng dụng Django không cần chuyển hướng bất cứ điều gì, điều này chỉ hoạt động tốt, nhưng nếu nó cố gắng chuyển hướng một yêu cầu (ví dụ: để thêm dấu gạch chéo vào http://example.com/my-project/foo), kết thúc sẽ xóa /my-project/ khỏi URL, để lại cho tôi URL không hợp lệ http://example.com/foo/.gunicorn qua mod_proxy được chuyển hướng bên ngoài phạm vi của dự án, mặc dù ProxyPassReverse

cấu hình mod_proxy của tôi là như sau:

<Proxy *> 
    Order deny,allow 
    Allow from all 
</Proxy> 
ProxyRequests On 
ProxyPass /my-project/ http://127.0.0.1:18731/ retry=0 
ProxyPassReverse /my-project/ http://127.0.0.1:18731/ retry=0 
ProxyPreserveHost On 
ProxyErrorOverride Off 

Tôi không muốn để buộc Django tiền tố /my-project/ cho tất cả các URL của nó, vì lợi ích của tính di động. Apache dường như sẽ tự xử lý tiền tố với dòng ProxyPassReverse. Tôi đang làm gì sai?

Trả lời

0

Tôi đã quyết định chuyển sang nginx, không thể tìm thấy giải pháp cho vấn đề ProxyPassReverse của Apache trong nhiều ngày sau khi yêu cầu nhiều trang trợ giúp. Chưa kể đến nhiều vấn đề khác mà tôi đã gặp với Apache trong năm qua. Vấn đề cũng có thể được giải quyết bằng cách tạo một máy chủ ảo riêng biệt chỉ dành cho máy chủ proxy, nhưng cá nhân tôi không hài lòng với giải pháp này.

Điều đó nói rằng, Tôi khuyên bạn nên thử trước Chris's answer trước tiên. Tôi chưa đích thân kiểm tra nhưng lý do của anh ấy là âm thanh (mặc dù một vài tháng đã quá muộn đối với tôi).

+0

Bạn không thích điều gì về giải pháp? –

+0

Tôi muốn cho các ứng dụng tôi phát triển để có sẵn dưới tên miền phụ cá nhân của tôi, thay vì tạo ra một cái mới dành riêng cho Django. – Fraxtil

2

Bạn đã thử cái này chưa? Tôi đã thêm dự án của tôi vào url mà bạn cũng đang ủy quyền.

<Proxy *> 
    Order deny,allow 
    Allow from all 
</Proxy> 
ProxyRequests On 
ProxyPass /my-project/ http://127.0.0.1:18731/my-project/ retry=0 
ProxyPassReverse /my-project/ http://127.0.0.1:18731/my-project/ retry=0 
ProxyPreserveHost On 
ProxyErrorOverride Off 

Tôi thường sử dụng nginx cho loại điều này, vì vậy tôi không chắc liệu điều đó có hiệu quả hay không.

Cập nhật: phần trên không hoạt động nên hãy thử một thứ khác.

Hãy thử một cái gì đó như thế này và xem điều đó có hữu ích không. Nó được thiết lập một chút khác nhau. Nó ủy quyền mọi thứ ngoại trừ phương tiện được phục vụ thông qua một bí danh. Điều này loại bỏ sự cần thiết phải có/dự án của tôi/ở tất cả.

<VirtualHost *:80> 
ServerName example.com 
UseCanonicalName On 
ServerAdmin [email protected] 

LogLevel warn 
CustomLog /var/log/apache2/example.com/access.log combined 
ErrorLog /var/log/apache2/example.com/error.log 
ServerSignature On 

Alias /media/ /home/example/example.com/pysrc/project/media/ 

ProxyPass /media/ ! 
ProxyPass/http://127.0.0.1:18731/ 
ProxyPassReverse/http://127.0.0.1:18731/ 
ProxyPreserveHost On 
ProxyErrorOverride Off 
</VirtualHost> 
+0

này không hoạt động. Django đang mong đợi các yêu cầu, ví dụ:/foo /, not/my-project/foo /, vì vậy ProxyPass phải đúng theo cách của nó. Thay đổi ProxyPassReverse không ảnh hưởng đến kết thúc của tôi, điều này khiến tôi tin rằng nó không được sử dụng chút nào. – Fraxtil

+0

Cập nhật câu trả lời của tôi với một tùy chọn khác xem có giúp ích gì không. –

+0

Cũng lưu ý rằng các yêu cầu proxy bị thiếu có nghĩa là nó sẽ mặc định tắt mà thường là những gì bạn có cho proxy ngược. Một thiết lập khác để chơi nếu nó không hoạt động là proxypreservehost. –

6

Tôi gặp sự cố này.

ProxyPreserveHost On 

<Location "/my-project/"> 
    ProxyPass http://127.0.0.1:18173/my-project/ 
    ProxyPassReverse http://127.0.0.1:18173/my-project/ 
    RequestHeader set SCRIPT_NAME /my-project 
    RequestHeader set X-FORWARDED-PROTOCOL ssl 
    RequestHeader set X-FORWARDED-SSL on 
</Location> 

Để kích hoạt ứng dụng WSGI để xây dựng một địa chỉ tuyệt đối chúng ta cần:

  • ProxyPreserveHost On, vì vậy tiêu đề Host: được thông qua và ứng dụng biết Hostname khách hàng nhìn thấy chúng tôi tại.
  • Thêm tiêu đề SCRIPT_NAME để ứng dụng biết gốc của nó ở đâu.
  • Đặt tiêu đề X-FORWARDED- nếu cần. Tôi đang sử dụng ssl quá, vì vậy tôi phải nói với ứng dụng nó nên sử dụng sơ đồ https.

Tôi sử dụng <Location> chỉ thị, vì tôi làm nhiều thứ hơn trên vhost này. Nhưng bạn có thể dễ dàng viết lại điều này bằng cách chuyển các đối số path tới chỉ thị ProxyPassProxyPassReverse.

NB: ProxyRequests phải là Tắt, trừ khi bạn cũng muốn có proxy chuyển tiếp. Nếu bạn đang đọc này, bạn có thể chỉ muốn một proxy đảo ngược.

Ghi chú cụ thể của Django: settings.LOGIN_URL được sử dụng , vì vậy, bạn sẽ cần phải tự thêm một mình vào số SCRIPT_NAME.

0

tôi đã giải quyết được vấn đề gốc bằng cách thiết lập ProxyPassReverse cấu hình tên miền thực:

ProxyPass /my-project/ http://127.0.0.1:18731/ 
ProxyPassReverse /my-project/ http://mydomain.com/ 

Gợi ý: Apache ProxyPassReverse values

Các vấn đề liên quan