Send authenticated POST request to tastypie

I am trying to send an ApoKey-authenticated POST request to tastypie API

my Model:

class Thing(models.Model): name = models.TextField() def __unicode__(self): return u'%s'%self.name 

my ModelResource

 class ThingResource(ModelResource): class Meta: queryset = Thing.objects.all() resource_name="thing" authentication = ApiKeyAuthentication() authorization = DjangoAuthorization() 

my urls.py

 from django.conf.urls.defaults import patterns, include, url from tastypie.api import Api from myapp.api import ThingResource mobile_api = Api(api_name='mobile') mobile_api.register(ThingResource()) from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/', include(admin.site.urls)), (r'^api/', include(mobile_api.urls)), ) 

and my cURL team

 curl --dump-header - -H "Accept: application/json" -H "Content-Type: application/json" -d"username=vikingosegundo" -d"api_key=12345" -X POST --data "{\"name\":\"arrrg\"}" http://localhost:8000/api/mobile/thing/ 

Answer

 {"error_message": "No JSON object could be decoded", "traceback": "Traceback (most recent call last):\n\n File \"/Users/vikingosegundo/Coding/Project/serverside/mysite/tastypie/resources.py\", line 178, in wrapper\n response = callback(request, *args, **kwargs)\n\n File \"/Users/vikingosegundo/Coding/Project/serverside/mysite/tastypie/resources.py\", line 379, in dispatch_list\n return self.dispatch('list', request, **kwargs)\n\n File \"/Users/vikingosegundo/Coding/Project/serverside/mysite/tastypie/resources.py\", line 409, in dispatch\n response = method(request, **kwargs)\n\n File \"/Users/vikingosegundo/Coding/Project/serverside/mysite/tastypie/resources.py\", line 1077, in post_list\n deserialized = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))\n\n File \"/Users/vikingosegundo/Coding/Project/serverside/mysite/tastypie/resources.py\", line 328, in deserialize\n deserialized = self._meta.serializer.deserialize(data, format=request.META.get('CONTENT_TYPE', 'application/json'))\n\n File \"/Users/vikingosegundo/Coding/Project/serverside/mysite/tastypie/serializers.py\", line 161, in deserialize\n deserialized = getattr(self, \"from_%s\" % desired_format)(content)\n\n File \"/Users/vikingosegundo/Coding/Project/serverside/mysite/tastypie/serializers.py\", line 305, in from_json\n return simplejson.loads(content)\n\n File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/json/__init__.py\", line 307, in loads\n return _default_decoder.decode(s)\n\n File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/json/decoder.py\", line 319, in decode\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n\n File \"/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/json/decoder.py\", line 338, in raw_decode\n raise ValueError(\"No JSON object could be decoded\")\n\n ValueError: No JSON object could be decoded\n" } 

What am I doing wrong? How to point tastypie to json object? Auth + auth seems to work.

+4
source share
2 answers

Using -d and --data with curl is POSTed data processing.

Including the username and api_key in the GET should solve this, for example:

  curl --dump-header - -H "Accept: application/json"\ -H "Content-Type: application/json" -X POST\ --data "{\"name\":\"arrrg\"}"\ "http://localhost:8000/api/mobile/thing/?username=vikingosegundo&api_key=12345" 
+9
source

I want to add the answer myself. Instead of a Josh solution, I do not add credentials as GET parameters, but I pass them as custom HTTP headers.

 class CustomApiKeyAuthentication(ApiKeyAuthentication): def is_authenticated(self, request, **kwargs): username = request.META.get('HTTP_X_MYAPP_USERNAME') or request.GET.get('username') api_key = request.META.get('HTTP_X_MYAPP_APIKEY') or request.GET.get('apikey') if not username or not api_key: return self._unauthorized() try: user = User.objects.get(username=username) except (User.DoesNotExist, User.MultipleObjectsReturned): return self._unauthorized() request.user = user return self.get_key(user, api_key) class ThingResource(MopedModelResource): creator = fields.ForeignKey(UserResource, 'creator', full = not True) class Meta: queryset = Thing.objects.all() resource_name = "thing" authentication = CustomApiKeyAuthentication() authorization = ThingAuthorization() 

Now we can add X-MYAPP-USERNAME and X-MYAPP-APIKEY to the request.
Here's a simple telnet session using GET

 GET /api/mobile/thing/ HTTP/1.1 X-MYAPP-APIKEY: 12345 X-MYAPP-USERNAME: vikingosegundo HTTP/1.0 200 OK Date: Wed, 24 Aug 2011 19:37:05 GMT Server: WSGIServer/0.1 Python/2.7.1 Content-Type: application/json; charset=utf-8 {"meta": {"limit": 20, "next": null, … 

and session for POST:

 POST /api/mobile/thing/ HTTP/1.1 Content-Type: application/json Content-Length: 49 X-MYAPP-APIKEY: 12345 X-MYAPP-USERNAME: vikingosegundo {"name":"qwerty","creator":"/api/mobile/user/1/"} HTTP/1.0 201 CREATED Date: Wed, 24 Aug 2011 20:12:32 GMT Server: WSGIServer/0.1 Python/2.7.1 Content-Type: text/html; charset=utf-8 Location: http://1.0.0.127.in-addr.arpa:8000/api/mobile/thing/8/ 

And since we also check the GET parameters in the absence of a header, this also works:

 http://localhost:8000/api/mobile/thing/?username=vikingosegundo;apikey=12345;format=json 
+6
source

All Articles