为什么django从网上忽略HTTP_X_FORWARDED_PROTO但在测试中没有呢? [英] Why does django ignore HTTP_X_FORWARDED_PROTO from the wire but not in tests?

查看:271
本文介绍了为什么django从网上忽略HTTP_X_FORWARDED_PROTO但在测试中没有呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果django通过网络传输,为什么它会忽略HTTP_X_FORWARDED_PROTO?

Why does django ignore the HTTP_X_FORWARDED_PROTO if it comes through the wire?

我将以下配置添加到settings.xml中:

I added to the settings.xml the following config:

# make sure we know when we are secure when we are behind a proxy
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

我进行了测试以测试

def testHttpSupport(self):
    url = reverse('configuration-list')
    response = self.client.get(url, HTTP_X_FORWARDED_PROTO='https')
    cfg = response.data[0]
    cfg_url = cfg['url']
    self.assertTrue(cfg_url.startswith('https'))

这很好用。返回对象的URL以https开头。

this works fine. The url of the return object starts with https.

但是,如果我尝试:

curl -v -H 'HTTP_X_FORWARDED_PROTO: https' http://localhost:8000/api/users/
...
> GET /api/users/ HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.51.0
> Accept: */*
> HTTP_X_FORWARDED_PROTO: https
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Date: Mon, 03 Jul 2017 16:22:04 GMT
< Server: WSGIServer/0.2 CPython/3.6.1
< Content-Type: application/json
< Allow: GET, POST, OPTIONS
< Vary: Accept, Cookie
< X-Frame-Options: SAMEORIGIN
< Content-Length: 197 
<
* Curl_http_done: called premature == 0
* Closing connection 0
[{"url":"http://localhost:8000/api/users/1/",...

为什么不像我的单元测试中那样返回基于https://的URL?

How come it does not return 'https://' based urls like in my unit-test?

推荐答案

问题是标题名称。通过WSGI服务器访问Django时,应使用 X-Forwarded-Proto 标头而不是 HTTP_X_FORWARDED_PROTO

The issue is the header name. When accessing Django through a WSGI server, you should use the X-Forwarded-Proto header instead of the HTTP_X_FORWARDED_PROTO:

curl -v -H 'X-Forwarded-Proto: https' http://localhost:8000/api/users/

WSGI协议规定必须遵循相关的CGI规范,即:

The WSGI protocol states that the relevant CGI specifications must be followed, which say:


以'HTTP_'开头的元变量包含从客户端请求标头字段读取
的值。
HTTP标头字段名称转换为大写,将所有
出现的-都替换为 _,并在
之前加上 HTTP_以提供元变量名称。 / p>

Meta-variables with names beginning with 'HTTP_' contain values read from the client request header fields, if the protocol used is HTTP. The HTTP header field name is converted to upper case, has all occurrences of "-" replaced with "_" and has 'HTTP_' prepended to give the meta-variable name.

因此,每当您使用WSGI服务器时, X-Forwarded-Proto 标头在传递给Django之前会自动转换为 HTTP_X_FORWARDED_PROTO 。当您传入 HTTP_X_FORWARDED_PROTO 标头时,必须仍然根据规范在 HTTP _ 之前添加。因此,您最终在Django中使用名为 HTTP_HTTP_X_FORWARDED_PROTO 的标头。

So whenever you are using a WSGI server, the X-Forwarded-Proto header is automatically converted to HTTP_X_FORWARDED_PROTO before it is passed in to Django. When you pass in the HTTP_X_FORWARDED_PROTO header instead, HTTP_ must still be prepended according to the specification. Thus, you end up with a header named HTTP_HTTP_X_FORWARDED_PROTO in Django.

self.client 不是WSGI服务器,并且通过kwarg传递的值直接插入到WSGI中环境,无需任何处理。因此,在这种情况下,您必须自己进行转换,并实际使用 HTTP_X_FORWARDED_PROTO 键:

self.client is not a WSGI server, and values passed in through the kwargs are inserted directly into the WSGI environment, without any processing. So in that case you have to do the conversion yourself and actually use the HTTP_X_FORWARDED_PROTO key:


CGI规范

通过** extra发送的标头应遵循CGI规范。例如,模拟在HTTP请求中从浏览器发送到服务器的另一个主机标头应作为HTTP_HOST传递。

The headers sent via **extra should follow CGI specification. For example, emulating a different "Host" header as sent in the HTTP request from the browser to the server should be passed as HTTP_HOST.

这篇关于为什么django从网上忽略HTTP_X_FORWARDED_PROTO但在测试中没有呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆