什么是中间件

我们从一个简单的例子开始。

高流量的站点通常需要将Django部署在负载平衡proxy(参见第20章)之后。 这种方式将带来一些复杂性,其一就是每个request中的远程IP地址(request.META["REMOTE_IP"])将指向该负载平衡proxy,而不是发起这个request的实际IP。 负载平衡proxy处理这个问题的方法在特殊的 X-Forwarded-For 中设置实际发起请求的IP。

因此,需要一个小小的中间件来确保运行在proxy之后的站点也能够在 request.META["REMOTE_ADDR"] 中得到正确的IP地址:

  1. class SetRemoteAddrFromForwardedFor(object):
  2. def process_request(self, request):
  3. try:
  4. real_ip = request.META['HTTP_X_FORWARDED_FOR']
  5. except KeyError:
  6. pass
  7. else:
  8. # HTTP_X_FORWARDED_FOR can be a comma-separated list of IPs.
  9. # Take just the first one.
  10. real_ip = real_ip.split(",")[0]
  11. request.META['REMOTE_ADDR'] = real_ip

(Note: Although the HTTP header is called X-Forwarded-For , Django makes it available as request.META['HTTPX_FORWARDED_FOR'] . With the exception of content-length and content-type , any HTTP headers in the request are converted to request.META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP prefix to the name.)

一旦安装了该中间件(参见下一节),每个request中的 X-Forwarded-For 值都会被自动插入到 request.META['REMOTE_ADDR'] 中。这样,Django应用就不需要关心自己是否位于负载平衡proxy之后;简单读取 request.META['REMOTE_ADDR'] 的方式在是否有proxy的情形下都将正常工作。

实际上,为针对这个非常常见的情形,Django已将该中间件内置。 它位于 django.middleware.http 中, 下一节将给出这个中间件相关的更多细节。