我正在对我的Tastypie api发出POST请求,这会创建一个资源。 它通常通过响应中的Location标头返回资源uri。 我遇到的问题是Location标头包含一个非ssl网址,即使我的初始请求(以及我的整个应用程序)都在https下。
来自我的请求标题:
URL: https://example.com/api/v1/resource/
来自我的回复标题:
Location: http://example.com/api/v1/resource/80/
因为这是一个并不总是在ssl下运行的可重用应用程序,所以我不想硬编码丑陋的字符串替换。此外,已经有一个301重定向,从http到https,但我不希望重定向发生。
所有帮助表示赞赏!
更新 这实际上与Tastypie没有任何关系,这是因为服务器/代理配置。请参阅下面的答案以获取解决方案详情。
答案 0 :(得分:6)
原因很简单:看似request.is_secure()
在您的案例中返回False
,因此网址是使用http
而不是https
构建的。
有几种解决方案,但您应首先找到导致request.is_secure()
返回False
的原因。我打赌你在一些代理或负载均衡器后面运行。如果您没有更改URL生成背后的逻辑,那么这可能是您的问题的原因。
要解决此问题,您可以查看SECURE_PROXY_SSL_HEADER
setting in Django,它定义表示与代理或负载均衡器建立的SSL连接的标头:
但是,如果您的Django应用程序位于代理服务器后面,那么代理服务器可能会吞噬"吞咽"事实上,请求是HTTPS,使用代理和Django之间的非HTTPS连接。在这种情况下,
is_secure()
将始终返回False
- 即使是最终用户通过HTTPS发出的请求也是如此。在这种情况下,您需要配置代理以设置自定义HTTP标头,告诉Django该请求是否通过HTTPS传入,并且您要设置
SECURE_PROXY_SSL_HEADER
以便Django知道要查找的标题。
但是,如果您正在设计一个可重复使用的应用程序,并且上述情况在您的情况下是正确的,请确保它不是不同的东西。如果您确定是这种情况,那么请将其留给用户 - 负责安全请求指示的标头应该由显式设置,只有使用您的应用程序的程序员才能设置。否则,这可能意味着安全问题。