使用 Flask 代理到另一个 Web 服务
我想将对 Flask 应用程序发出的请求代理到计算机上本地运行的另一个 Web 服务。我宁愿使用 Flask 而不是更高级别的 nginx 实例,这样我们就可以重用应用程序中内置的现有身份验证系统。我们越能保持这种“单点登录”越好。
是否有现有的模块或其他代码可以执行此操作?尝试将 Flask 应用程序桥接到 httplib 或 urllib 之类的东西被证明是一件痛苦的事情。
I want to proxy requests made to my Flask app to another web service running locally on the machine. I'd rather use Flask for this than our higher-level nginx instance so that we can reuse our existing authentication system built into our app. The more we can keep this "single sign on" the better.
Is there an existing module or other code to do this? Trying to bridge the Flask app through to something like httplib or urllib is proving to be a pain.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我花了很多时间研究同样的事情,并最终找到了一个使用 requests 库的解决方案,该解决方案似乎运行良好。它甚至可以在一个响应中设置多个 cookie,这需要一些调查才能弄清楚。这是 Flask 视图函数:
2021 年 4 月更新:
excluded_headers
可能应该包含 RFC 2616 第 13.5.1 节。I spent a good deal of time working on this same thing and eventually found a solution using the requests library that seems to work well. It even handles setting multiple cookies in one response, which took a bit of investigation to figure out. Here's the flask view function:
Update April 2021:
excluded_headers
should probably include all "hop-by-hop headers" defined by RFC 2616 section 13.5.1.我在基于 Werkzeug 的应用程序中使用 httplib 实现了代理(就像您的情况一样,我需要使用 web 应用程序的身份验证和授权)。
尽管 Flask 文档没有说明如何访问 HTTP 标头,但您可以使用
request.headers
(请参阅 Werkzeug 文档)。如果您不需要修改响应,并且代理应用程序使用的标头是可预测的,则代理是直接的。请注意,如果您不需要修改响应,则应使用
werkzeug.wsgi.wrap_file
来包装 httplib 的响应流。这允许将打开的操作系统级文件描述符传递到 HTTP 服务器以获得最佳性能。I have an implementation of a proxy using httplib in a Werkzeug-based app (as in your case, I needed to use the webapp's authentication and authorization).
Although the Flask docs don't state how to access the HTTP headers, you can use
request.headers
(see Werkzeug documentation). If you don't need to modify the response, and the headers used by the proxied app are predictable, proxying is staightforward.Note that if you don't need to modify the response, you should use the
werkzeug.wsgi.wrap_file
to wrap httplib's response stream. That allows passing of the open OS-level file descriptor to the HTTP server for optimal performance.我最初的计划是面向公众的 URL 类似于
http://www.example.com/admin/myapp
代理到http://myapp.internal.example.com /。沿着这条路走下去会导致疯狂。
大多数网络应用程序,特别是自托管的网络应用程序,假设它们将在 HTTP 服务器的根目录下运行,并执行诸如通过绝对路径引用其他文件之类的操作。要解决此问题,您必须重写所有位置的 URL:位置标头以及 HTML、JavaScript 和 CSS 文件。
我编写了一个 Flask 代理蓝图,它做到了这一点,虽然它对于我真正想要代理的一个 Web 应用程序来说工作得足够好,但它是不可持续的。这是一团乱七八糟的正则表达式。
最后,我在 nginx 中设置了一个新的虚拟主机并使用了它自己的代理。由于两者都位于主机的根目录,因此几乎不需要重写 URL。 (nginx 的代理模块处理了几乎不需要的事情。)被代理的 web 应用程序会进行自己的身份验证,目前这已经足够好了。
My original plan was for the public-facing URL to be something like
http://www.example.com/admin/myapp
proxying tohttp://myapp.internal.example.com/
. Down that path leads madness.Most webapps, particularly self-hosted ones, assume that they're going to be running at the root of a HTTP server and do things like reference other files by absolute path. To work around this, you have to rewrite URLs all over the place: Location headers and HTML, JavaScript, and CSS files.
I did write a Flask proxy blueprint which did this, and while it worked well enough for the one webapp I really wanted to proxy, it was not sustainable. It was a big mess of regular expressions.
In the end, I set up a new virtual host in nginx and used its own proxying. Since both were at the root of the host, URL rewriting was mostly unnecessary. (And what little was necessary, nginx's proxy module handled.) The webapp being proxied to does its own authentication which is good enough for now.