1

There are several questions on SO related to this topic, but none that I have seen solve my issue.

I have an endpoint in my Django/Tastypie API that accepts a PUT in order to update the database. This works great when testing in localhost:8000, however, my production database is located in a different domain, so I need to enable CORS to get this PUT call to update the database.

I have found the tutorial here that gives an example of how to do this, however, when I execute the cURL command:

curl -X PUT --dump-header - -H "Content-Type: application/json" -H "Authorization: ApiKey api:MYAPIKEY" -d "{\"mykey\": \"my_value\", \"resource_uri\": \"/api/v1/mytable/362/\"}" my.domain.com/api/v1/mytable/362/

I am still receiving 401 UNAUTHORIZED for my calls (header dump below):

HTTP/1.1 401 UNAUTHORIZED
Date: Mon, 22 Sep 2014 16:08:34 GMT
Server: Apache/2.4.7 (Ubuntu)
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,Authorization
X-Frame-Options: SAMEORIGIN
Content-Length: 0
Content-Type: text/html; charset=utf-8

My CoresResource superclass code:

class CorsResource(ModelResource):
    """ adds CORS headers for cross-domain requests """
    def patch_response(self, response):

        allowed_headers = ['Content-Type', 'Authorization']

        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Headers'] = ','.join(allowed_headers)
        return response

    def dispatch(self, *args, **kwargs):
        """ calls super and patches resonse headers
            or
            catches ImmediateHttpResponse, patches headers and re-raises
        """

        try:
            response = super(CorsResource, self).dispatch(*args, **kwargs)
            return self.patch_response(response)
        except ImmediateHttpResponse, e:
            response = self.patch_response(e.response)
            # re-raise - we could return a response but then anthing wrapping
            # this and expecting an exception would be confused
            raise ImmediateHttpResponse(response)

    def method_check(self, request, allowed=None):
        """ Handle OPTIONS requests """
        if request.method.upper() == 'OPTIONS':

            if allowed is None:
                allowed = []

            allows = ','.join([s.upper() for s in allowed])

            response = HttpResponse(allows)
            response['Allow'] = allows
            raise ImmediateHttpResponse(response=response)

        return super(CorsResource, self).method_check(request, allowed)

My endpoint code:

class DataModelResource(CorsResource):

    data = fields.OneToOneField(DataModelResource, "data", full=True)

    class Meta:
        allowed_methods = ['get', 'put']
        authentication = ApiKeyAuthentication()
        authorization = Authorization()
        queryset = Data.objects.all()
        resource_name = 'mytable'

Does anyone see any reason why making a PUT from a cross-domain should be failing with this code??? I'm at a complete loss here.

Community
  • 1
  • 1
Brett
  • 11,637
  • 34
  • 127
  • 213
  • Do you use some kind of proxy server like nginx on production? Make sure it's not that. – Bartosz Dabrowski Sep 23 '14 at 11:18
  • Second thing that comes to my mind is to swap `ApiKeyAuthentication()` with `Authentication()` just for debugging reasons. In addition try test cross origin with these curls: http://stackoverflow.com/questions/12173990/how-can-you-debug-a-cors-request-with-curl – Bartosz Dabrowski Sep 25 '14 at 07:19

0 Answers0