2017-07-03 80 views
3

爲什麼django忽略HTTP_X_FORWARDED_PROTO,如果它通過線路?爲什麼django忽略HTTP_X_FORWARDED_PROTO而不是在測試中?

我加入的settings.xml以下配置:

# 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開頭。

但是如果我嘗試:

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://」網址的基礎喜歡在我的單元測試?

回答

4

問題是標題名稱。當通過WSGI服務器訪問Django的,你應該使用X-Forwarded-Proto頭,而不是HTTP_X_FORWARDED_PROTO

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

的WSGI協議規定,有關CGI規範必須遵循的,這說:

薈萃如果使用的協議是HTTP,那麼名稱以'HTTP_'開頭的變量包含從客戶端請求標頭字段讀取的 值。 將HTTP標題字段名轉換爲大寫,將所有 出現的「 - 」替換爲「_」,並將'HTTP_'前置爲 以提供元變量名稱。

source

所以每當你正在使用WSGI服務器,之前在給Django是通過X-Forwarded-Proto頭被自動轉換爲HTTP_X_FORWARDED_PROTO。當您傳入HTTP_X_FORWARDED_PROTO標題時,HTTP_仍必須根據規範進行預設。因此,你最終在Django中得到一個名爲HTTP_HTTP_X_FORWARDED_PROTO的頭文件。

self.client不是WSGI服務器,通過kwargs傳入的值直接插入到WSGI環境中,無需任何處理。因此,在這種情況下,你必須自己做轉換和實際使用HTTP_X_FORWARDED_PROTO鍵:

CGI規範

通過**額外發送應遵循CGI規範的標頭。例如,模擬與從瀏覽器發送到服務器的HTTP請求中發送的不同的「主機」頭文件應該作爲HTTP_HOST傳遞。

source