2013-03-17 35 views
31

Ban đầu, tôi đã cố gắng đăng một yêu cầu ajax từ phía máy khách của mình đến một URL của bên thứ ba, nhưng có vẻ như trình duyệt có vấn đề về bảo mật với điều đó. Tôi nghĩ về việc gửi một ajax đến phía máy chủ, từ đó để gửi một yêu cầu GET cho bên thứ ba, nhận được phản hồi và gửi nó trở lại phía máy khách. Làm thế nào tôi có thể làm điều đó với bình?Làm cách nào để gửi yêu cầu GET từ ứng dụng bình của tôi đến một trang web khác?

Trả lời

36

Cài đặt requests mô-đun (đẹp hơn nhiều so với sử dụng urllib2) và sau đó xác định một lộ trình mà làm theo yêu cầu cần thiết - một cái gì đó như:

import requests 
from flask import Flask 
app = Flask(__name__) 

@app.route('/some-url') 
def get_data(): 
    return requests.get('http://example.com').content 

Tùy thuộc vào thiết lập của bạn, mặc dù nó sẽ được tốt hơn để cấu hình máy chủ web của bạn để đảo ngược proxy đến trang web mục tiêu theo một URL nhất định.

+0

Sử dụng yêu cầu urllib2 của gây ra một lỗi trong máy chủ của tôi, tôi đoán là mà yêu cầu cài đặt sẽ làm tương tự (đã không kiểm tra traceback tuy nhiên) ... Không có một chức năng bình được xây dựng trong đó? @Jon Clements – user1639431

+0

@ user1639431 nope - không có chức năng dựng sẵn - là Flask đang chạy dưới apache2/nginx? –

+0

Không có ý tưởng, đó là một dịch vụ đám mây, nhưng tiền của tôi là nginx. Dù sao, tôi nhìn vào traceback, và cả hai urllib2 và yêu cầu cung cấp cho "kết nối từ chối". Tôi không có vấn đề để mở/curl url này từ cli của tôi, không thể hiểu được nguồn gốc của vấn đề này. @Jon Clements – user1639431

8

Bình một mình không có khả năng này, nhưng chỉ đơn giản là viết trình xử lý yêu cầu thực hiện yêu cầu tới máy chủ khác bằng thư viện ứng dụng khách HTTP và sau đó trả về phản hồi đó.

# third-party HTTP client library 
import requests 

# assume that "app" below is your flask app, and that 
# "Response" is imported from flask. 

@app.route("/proxy-example") 
def proxy_example(): 
    r = requests.get("http://example.com/other-endpoint") 
    return Response(
     r.text 
     status=r.status_code, 
     content_type=r.headers['content-type'], 
    ) 

Tuy nhiên, điều này sẽ không đạt được kết quả tương tự như bạn mong đợi từ yêu cầu phía máy khách. Vì máy chủ của bạn không thể "xem" bất kỳ cookie nào mà trình duyệt khách đã lưu trữ cho trang đích, yêu cầu proxy của bạn sẽ ẩn danh một cách hiệu quả và do đó, tùy thuộc vào trang đích, có thể bị lỗi hoặc phản hồi khác với yêu cầu của bạn tài nguyên đó trong trình duyệt.

Nếu bạn có mối quan hệ với URL của bên thứ ba (nghĩa là, nếu bạn kiểm soát hoặc có thể làm việc với những người làm) họ có thể cấp quyền truy cập cho yêu cầu tên miền chéo trong trình duyệt bằng cách sử dụng CORS (chỉ được hỗ trợ trong các trình duyệt hiện đại) hoặc JSON-P (một giải pháp cũ hơn có trước CORS).

Nhà cung cấp bên thứ ba cũng có thể cung cấp cho bạn quyền truy cập vào dữ liệu bạn muốn tại điểm cuối được thiết kế để chấp nhận yêu cầu từ các máy chủ khác và cung cấp cơ chế để bạn xác thực ứng dụng của mình. Giao thức phổ biến nhất cho điều này là OAuth.

+0

Bạn đã thử chạy ví dụ này bên trong một ứng dụng Flask đang chạy chưa? Cũng như những người khác đang cố gắng tìm nạp, tôi nhận được lỗi như "requests.exceptions.InvalidSchema: Không tìm thấy bộ điều hợp kết nối nào cho ..." (... == url mục tiêu của tôi). Tôi đã thử một số loại url, từ http://myurl.com đến những thứ như http: // localhost: 5000/myurl ... nhưng không yêu cầu. Và tôi thậm chí đã cố gắng gọi đệ quy tới route để xem liệu 'requests.get()' có hoạt động (và kích hoạt lại route), nhưng ngay cả các url như 'requests.get (" localhost: 5000/myroute ")' do không gây ra các cuộc gọi đệ quy. Có vẻ như yêu cầu không hoạt động ... – JMM

0

Khi các câu trả lời khác đã tuyên bố bằng cách sử dụng mô đun yêu cầu cho python sẽ là cách tốt nhất để giải quyết vấn đề này từ góc độ mã hóa. Tuy nhiên như những bình luận đã đề cập (và lý do tôi đưa ra câu hỏi này) điều này có thể đưa ra một lỗi rằng yêu cầu đó đã bị từ chối. Lỗi này có thể do SELinux gây ra.

Để kiểm tra xem đây là vấn đề đầu tiên chắc chắn SELinux được kích hoạt bằng lệnh này:

sestatus 

Nếu 'current mode' là 'thực thi' sau đó SELinux được kích hoạt.

Tiếp nhận các giá trị bool hiện tại được áp dụng trực tiếp cho apache với lệnh này:

getsebool -a | grep httpd 

Hãy tìm cài đặt 'httpd_can_network_connect' này xác định nếu apache được phép đưa ra yêu cầu TCP ra vào mạng. Nếu nó được bật thì tất cả các yêu cầu TCP apache sẽ được cho phép. Để bật tính năng này chạy sau khi root:

setsebool -P httpd_can_network_connect 1 

Nếu bạn chỉ cần truy cập cơ sở dữ liệu (Tôi có vấn đề này trước đó là lý do tôi nghi ngờ SELinux đây) sau đó nó có lẽ sẽ tốt hơn nếu chỉ bật 'httpd_cna_network_connect' .

Mục đích của chính sách này là nếu tin tặc xâm nhập máy chủ apache của bạn, họ sẽ không thể thoát ra khỏi máy chủ với phần còn lại của mạng nội bộ của bạn.

này có lẽ sẽ đã tốt hơn như một bình luận nhưng tôi không có đủ diện ..

Nguồn: https://tag1consulting.com/blog/stop-disabling-selinux https://wiki.centos.org/TipsAndTricks/SelinuxBooleans

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