Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tastypie POST Location HTTPS vs. HTTP

When I POST a new resource to my RESTful Tastypie API, I create a resource and get a 201 response like this:

HTTP/1.1 201 CREATED
Content-Type: text/html; charset=utf-8
Date: Wed, 19 Sep 2012 01:02:48 GMT
Location: http://example.com/api/v1/resource/12/
Server: gunicorn/0.14.6
Content-Length: 0
Connection: keep-alive

Great! Except I posted to an HTTPS URL and would like to get a HTTPS Location header back. How can I configure tastypie to do this?

Addition

I am using some middleware to force SSL, but I don't think it is the cause of this issue. Here it is anyway:

class SSLifyMiddleware(object):
    # Derived from https://github.com/rdegges/django-sslify
    def process_request(self, request):
        if not any((not settings.FORCE_SSL, request.is_secure(), request.META.get('HTTP_X_FORWARDED_PROTO', '') == 'https')):
            url = request.build_absolute_uri(request.get_full_path())
            secure_url = url.replace('http://', 'https://')
            return HttpResponseRedirect(secure_url)

Addition

This is a Heroku app.

like image 782
Erik Avatar asked Sep 19 '12 03:09

Erik


1 Answers

As we have determined, the reason of the URL beginning with http instead of https is request.is_secure() being False.

There are several possible reasons resulting in request.is_secure() being False, such as being behind load balancer or reverse proxy that connects to the server using HTTP while the connection between client and load balancer / reverse proxy is made using SSL.

Please take a look at the documentation of SECURE_PROXY_SSL_HEADER, which is some solution, if you are behind a proxy or load balancer:

If your Django app is behind a proxy, though, the proxy may be "swallowing" the fact that a request is HTTPS, using a non-HTTPS connection between the proxy and Django. In this case, is_secure() would always return False -- even for requests that were made via HTTPS by the end user.

In this situation, you'll want to configure your proxy to set a custom HTTP header that tells Django whether the request came in via HTTPS, and you'll want to set SECURE_PROXY_SSL_HEADER so that Django knows what header to look for.

like image 123
Tadeck Avatar answered Oct 13 '22 00:10

Tadeck