不用Nginx,如何使用 Django 实现反向代理?

提到反向代理,你会说用 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 所做的事情:

不用Nginx,如何使用 Django 实现反向代理?

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、最后,响应将返回给用户。

最后的话

分享文件,我比较常用的方式是在某一目录下执行一条 Python 命令: python -m http.server ,可以让该目录下的文件或文件夹通过 http 的方式共享给他人下载使用,使用 django-revproxy 这个轮子,可以让这个功能集成在 Django 的某一个路由中,在开发者服务器部署,大家用起来是着实方便。这也是为什么我找到了这个轮子。

原创文章,作者:Rosmontis,如若转载,请注明出处:https://rosmontis.com/archives/193

(0)
Rosmontis的头像Rosmontis
机架服务器RAID阵列卡配置详解(DELL R720XD)
上一篇 2022年4月12日 上午9:33
Django—使用channels实现websocket
下一篇 2022年5月6日 上午9:13

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注