你好,我是 somenzz,可以叫我征哥。
提到反向代理,你会说用 nginx。没错,nginx 是理想的反向代理工具。
但现在条件苛刻,服务器没有 nginx,也没有 root 权限,意味着你无法编译安装 nginx,且只有一个端口 80 开放访问。怎么让这个 80 端口的某一请求转发到其他端口的 http 服务上?
换句话说,不用 nginx,如何让 http://localhost:80/new_req 的请求转发到 http://localhost:9999 的服务上,就像直接访问 http://localhost:9999 一样?
那么,这就需要我们自己实现反向代理的功能。
本文分享如何仅用 Django 实现反向代理。
1、安装轮子
pip install django-revproxy
这个轮子有对应的 whl 文件,非常容易安装成功,且不依赖其他轮子,如果是内网环境,pypi.org 上下载 whl 文件,复制进去 pip 安装一下就可以了。
2、配置
在 Django 的配置文件 settings.py 中的 INSTALLED_APPS 中,添加 'revproxy'。
#Add 'revproxy' to INSTALLED_APPS.
INSTALLED_APPS = (
# ...
'django.contrib.auth',
'revproxy',
# ...
)
然后编写一个视图类,比如 myproxy/views.py:
from revproxy.views import ProxyView
class TestProxyView(ProxyView):
upstream = "http://localhost:9999" ##http://example.com
然后修改 Django 的 urls.py 文件,添加这样一条路由:
from myproxy.views import TestProxyView
from django.conf.urls import url
urls = [
# ...
url(r'^new_req/(?P<path>.*)$', TestProxyView.as_view()),
# ...
]
或者,你不想新建一个 views.py 文件,可以直接在 url.py 中这样写:
from django.urls import re_path
from revproxy.views import ProxyView
urlpatterns = [
re_path(r'(?P<path>.*)', ProxyView.as_view(upstream='http://example.com/')),
]
最后,将 Django 服务部署在 80 端口上,然后访问:
http://localhost/new_req
就相当于访问
http://localhost:9999
3、它是如何工作的
这个图就是 django-revproxy 所做的事情:
![49e864d98bf8d439ddf1366891742e9d.png](https://i-blog.csdnimg.cn/blog_migrate/7a91f78341ca32619ddf8a48013e493a.png)
1、Django 接收来自客户端的请求,并使用 revproxy.proxy.ProxyView 对其进行处理。
2、Revproxy 将克隆客户端请求。
3、如果用户在 Django 中通过身份验证,并且 add_remote_user 属性设置为 True,则 HTTP 标头 REMOTE_USER 将设置为request.user.username。
class CustomProxyView(ProxyView):
upstream = 'http://www.example.com'
add_remote_user = True
4、如果 add_x_forwarded 属性设置为 True,则 HTTP 标头 X-Forwarded-For 和 X-Forwarded-Proto 将分别设置为请求者的 IP 地址和协议(http 或 https)。
5、克隆的请求被发送到上游服务器,也就是 upstream。
6、在收到来自上游的响应后,视图将对其进行处理以确保正确设置所有 headers。一些 headers 像 Location 这样的被视为特殊情况。
7、从上游服务器接收到的响应被转换为 django.http.HttpResponse。对于二进制文件,使用 StreamingHttpResponse 来减少内存使用。
8、如果用户设置了一组 diazo 规则和一个主题模板,则会在响应正文上应用 diazo/XSLT 转换。
views.py :
from django.urls import re_path
from revproxy.views import DiazoProxyView
proxy_view = DiazoProxyView.as_view(
upstream='http://example.com/',
html5=True,
diazo_theme_template='base.html',
)
urlpatterns = [
re_path(r'(?P<path>.*)', proxy_view),
]
base.html :
<html>
<head>...</head>
<body>
...
<div id="content"></div>
...Fix all links in the docs (and README file etc) from old to new repo
9、最后,响应将返回给用户。
4、轮子的源代码
来这里一探究竟:django-revproxy[1]
最后的话
分享文件,我比较常用的方式是在某一目录下执行一条 Python 命令: python -m http.server
,可以让该目录下的文件或文件夹通过 http 的方式共享给他人下载使用,使用 django-revproxy 这个轮子,可以让这个功能集成在 Django 的某一个路由中,在开发者服务器部署,大家用起来是着实方便。这也是为什么我找到了这个轮子。
本文分享了如何仅用 Django 就实现反向代理功能,如果觉得有用的话,还请点赞,在看,评论支持。感谢老铁。
留言讨论
推荐阅读
参考资料
[1]
django-revproxy: https://github.com/jazzband/django-revproxy