2011-07-11 11 views
19

Tôi muốn yêu cầu proxy được thực hiện cho ứng dụng Flask của tôi đến một dịch vụ web khác chạy cục bộ trên máy. Tôi muốn sử dụng Flask cho điều này hơn là phiên bản nginx cấp cao hơn của chúng tôi để chúng tôi có thể sử dụng lại hệ thống xác thực hiện có của chúng tôi được tích hợp trong ứng dụng của chúng tôi. Chúng ta càng có thể giữ "dấu hiệu đơn" này càng tốt.Ủy quyền cho một dịch vụ web khác bằng Flask

Có mô-đun hiện tại hoặc mã khác để thực hiện việc này không? Đang cố gắng kết nối ứng dụng Flask với một cái gì đó như httplib hoặc urllib đang chứng tỏ là một cơn đau.

+0

Câu hỏi này có liên quan khi thực hiện dịch vụ AJAX cho các trình duyệt cũ như IE7 không hỗ trợ bảo mật tên miền chéo. –

+0

Bạn đang gặp vấn đề gì với httplib? –

+0

@jd: Vì bình đó nằm ở phía ứng dụng của WSGI, tôi không chắc tôi có được tất cả dữ liệu để chuyển tiếp hiệu quả hay không. Ví dụ, đối tượng yêu cầu Flask dường như không bao gồm yêu cầu thô (hoặc thậm chí là các tiêu đề yêu cầu) mà tôi muốn chuyển vào httplib. Nó không phải là nó không thể, nó chỉ là một nỗi đau và tôi đã hy vọng cho một mô-đun hiện tại đã làm nó đã. –

Trả lời

8

Tôi có triển khai proxy sử dụng httplib trong ứng dụng dựa trên Werkzeug (như trong trường hợp của bạn, tôi cần sử dụng xác thực và ủy quyền của webapp).

Mặc dù tài liệu Flask không nêu cách truy cập vào tiêu đề HTTP, bạn có thể sử dụng request.headers (xem Werkzeug documentation). Nếu bạn không cần phải sửa đổi phản hồi và các tiêu đề được ứng dụng proxy sử dụng có thể dự đoán được, proxy sẽ rất dễ hiểu.

Lưu ý rằng nếu bạn không cần sửa đổi phản hồi, bạn nên sử dụng werkzeug.wsgi.wrap_file để bao gồm luồng phản hồi của httplib. Điều đó cho phép truyền mô tả tệp cấp hệ điều hành mở cho máy chủ HTTP để có hiệu suất tối ưu.

+0

Cảm ơn, tôi đã hack thứ gì đó vào chiều nay. Có tất cả các loại vấn đề với cookie, mặc dù, vì httplib không xử lý chúng đặc biệt tốt. Thật không may tôi nghĩ rằng tôi sẽ cần phải sửa đổi các phản ứng để làm một số URL viết lại đơn giản (tức là, để

+0

Trong trường hợp của tôi chỉ có một cookie để bắt, do đó, một regex đã làm công việc phân tích nó, nó dễ dàng hơn nhiều để thiết lập rằng libs cookie của Python. –

7

Gói ban đầu của tôi là cho URL công khai giống như http://www.example.com/admin/myapp ủy quyền cho http://myapp.internal.example.com/. Trên con đường đó dẫn đến điên khùng.

Hầu hết các ứng dụng web, đặc biệt là các ứng dụng tự lưu trữ, giả định rằng chúng sẽ chạy ở gốc của máy chủ HTTP và thực hiện những việc như tham chiếu các tệp khác theo đường dẫn tuyệt đối. Để giải quyết vấn đề này, bạn phải viết lại URL tất cả các địa điểm: Tiêu đề vị trí và các tệp HTML, JavaScript và CSS.

Tôi đã làm write a Flask proxy blueprint đã làm điều này, và trong khi nó hoạt động tốt đủ cho một webapp tôi thực sự muốn proxy, nó không bền vững. Đó là một mớ hỗn độn lớn của các biểu thức thông thường.

Cuối cùng, tôi thiết lập một máy chủ ảo mới trong nginx và sử dụng proxy của riêng nó. Vì cả hai đều ở gốc của máy chủ, nên việc viết lại URL hầu như không cần thiết. (Và cái gì là cần thiết, mô-đun proxy của nginx được xử lý.) Webapp được ủy quyền để thực hiện xác thực riêng của nó đủ tốt cho đến bây giờ.

+0

sẽ đọc lại 7/10 –

19

Tôi đã dành rất nhiều thời gian làm việc trên cùng một điều này và cuối cùng đã tìm thấy giải pháp sử dụng thư viện yêu cầu có vẻ hoạt động tốt. Nó thậm chí còn xử lý việc thiết lập nhiều cookie trong một câu trả lời, điều này mất một chút điều tra để tìm ra. Đây là chức năng xem bình:

from flask import request, Response 
import requests 

def _proxy(*args, **kwargs): 
    resp = requests.request(
     method=request.method, 
     url=request.url.replace('old-domain.com', 'new-domain.com'), 
     headers={key: value for (key, value) in request.headers if key != 'Host'}, 
     data=request.get_data(), 
     cookies=request.cookies, 
     allow_redirects=False) 

    excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection'] 
    headers = [(name, value) for (name, value) in resp.raw.headers.items() 
       if name.lower() not in excluded_headers] 

    response = Response(resp.content, resp.status_code, headers) 
    return response 
+1

Chỉ chỉnh sửa ngay bây giờ để xóa 'Máy chủ' khỏi tiêu đề yêu cầu và xóa một vài mục khỏi tiêu đề phản hồi. – Evan

+1

'tiêu đề' dường như không được sử dụng? – luckydonald

+1

@ luckydonald Tôi nghĩ rằng nó đã được sửa ngay bây giờ. Cảm ơn bạn đã chỉ ra điều đó. – Evan