如何将 GET 请求从我的烧瓶应用程序发送到另一个站点?

Posted

技术标签:

【中文标题】如何将 GET 请求从我的烧瓶应用程序发送到另一个站点?【英文标题】:How can I send a GET request from my flask app to another site? 【发布时间】:2013-03-05 23:22:08 【问题描述】:

最初,我尝试将 ajax 请求从客户端发布到第三方 url,但浏览器似乎存在安全问题。我想过向服务器端发送一个ajax,从那里向第三方发送一个GET请求,获取响应并将其发送回客户端。我怎样才能用烧瓶做到这一点?

【问题讨论】:

【参考方案1】:

正如其他答案所述,使用 Python 的 requests 模块将是从编码角度解决此问题的最佳方法。然而,正如 cmets 提到的(以及我提出这个问题的原因),这可能会导致请求被拒绝的错误。这个错误很可能是由 SELinux 引起的。

要检查这是否是问题,首先确保使用以下命令启用 SELinux:

sestatus

如果“当前模式”为“强制”,则启用 SELinux。

接下来使用此命令获取直接应用于 apache 的当前 bool 值:

getsebool -a | grep httpd

查找设置“httpd_can_network_connect”,这决定了是否允许 apache 向网络发出 TCP 请求。如果它打开,则将允许所有 apache TCP 请求。要打开它,请以 root 身份运行以下命令:

setsebool -P httpd_can_network_connect 1

如果您只需要访问数据库(我之前遇到过这个问题,这就是我在这里怀疑 SELinux 的原因),那么最好只打开“httpd_cna_network_connect”。

此政策的目的是,如果黑客要劫持您的 apache 服务器,他们将无法通过服务器进入您的内部网络的其余部分。

作为评论可能会更好,但我没有足够的代表..

来源: https://tag1consulting.com/blog/stop-disabling-selinux https://wiki.centos.org/TipsAndTricks/SelinuxBooleans

【讨论】:

感谢您花时间彻底解释一切。评论不足以传达信息。【参考方案2】:

Flask 本身不具备此功能,但编写一个请求处理程序是一件简单的事情,该处理程序使用 HTTP 客户端库向另一台服务器发出请求,然后返回该响应。

# 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'],
    )

但是,这不会达到您对客户端请求所期望的完全相同的结果。由于您的服务器无法“看到”客户端浏览器为目标站点存储的任何 cookie,因此您的代理请求将实际上是匿名的,因此,根据目标站点,可能会失败或给您与请求不同的响应浏览器中的那个资源。

如果您与第三方 URL 有关系(也就是说,如果您控制它或能够与这样做的人合作),他们可以使用 CORS 在浏览器中授予跨域请求访问权限(仅在现代浏览器中受支持)或JSON-P(一种早于 CORS 的旧解决方法)。

第三方提供商还可以让您在端点访问所需的数据,该端点旨在接受来自其他服务器的请求,并为您提供对应用进行身份验证的机制。最流行的协议是OAuth。

【讨论】:

您是否尝试过在正在运行的 Flask 应用程序中运行此示例?与其他尝试获取的人一样,我收到类似“requests.exceptions.InvalidSchema: No connection adapters were found for ...”(... == my target url)之类的错误。我尝试了几种网址,从 myurl.com 到 localhost:5000/myurl... 但没有请求。我什至尝试对路由进行递归调用以查看requests.get() 是否可以工作(并再次触发路由),但即使像requests.get("localhost:5000/myroute") 这样的网址也不会导致递归调用。似乎请求不起作用......【参考方案3】:

安装requests 模块(比使用urllib2 好得多),然后定义一个发出必要请求的路由 - 类似于:

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

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

不过,根据您的设置,最好将您的网络服务器配置为反向代理到某个 URL 下的目标站点。

【讨论】:

使用 urllib2 的请求会导致我的主机出错,我的猜测是安装请求会做同样的事情(虽然还没有检查回溯)......没有内置的烧瓶功能为了那个原因? @乔恩克莱门茨 @user1639431 nope - 没有内置函数 - Flask 是否在 apache2/nginx 下运行? 不知道,它是一个云服务,但我的钱在 nginx 上。无论如何,我查看了回溯,并且 urllib2 和请求都给出“连接被拒绝”。我从我的 cli 打开/卷曲这个 url 没有问题,无法理解这个问题的根源。 @乔恩克莱门茨 @user1639431 如果你只使用requests.get('http://example.com') 你会得到同样的结果吗? (只是为了检查没有基于用户代理或其他东西的过滤) 是的,如果使用requests.get("http://www.google.com"),我会遇到同样的错误。我似乎找不到合适的解决方法。 @乔恩克莱门茨

以上是关于如何将 GET 请求从我的烧瓶应用程序发送到另一个站点?的主要内容,如果未能解决你的问题,请参考以下文章

如何将烧瓶服务器作为便携式精灵运行

将烧瓶请求/应用程序上下文复制到另一个进程

从 iOS 上传 Flask 文件

尝试仅使用 html 按钮将数据传递给烧瓶应用程序

烧瓶问题和错误请求

将带有 fetch 的 POST 发送到烧瓶时的端口问题