I have created a Django-Rest-Framework API that allows me to successfully run a PUT request via the command line as such:
% curl -X PUT -u myUser:myPassword http://127.0.0.1:3001/api/myEndpoint/64/
{"id": 64, "myAttr1": "Blah1", "myAttr2": "Blah2"}
In my web application, I have the following JQuery AJAX that (as I understand it) should run the exact same command if I'm logged in as myUser
:
$.ajax(
{
url: "/api/myEndpoint/64/",
type: "PUT",
success: function( data )
{
console.log("Do Something Here");
}
}
);
When this .ajax command runs, however, I see the following error in the Chrome Development console:
PUT http://127.0.0.1:3001/api/myEndpoint/64/ 403 (FORBIDDEN)
After further investigation I also found this Django warning when I ran that .ajax:
WARNING [django.request:99] Forbidden (CSRF token missing or incorrect.): /api/myEndpoint/64/
Why does this work from the command line but not from my web-browser? How do I make this work? I don't fully understand how CSRF stuff works. Would love to get it to just work.
As a reference, here is an excerpt from views.py:
class MyEndPoint(mixins.UpdateModelMixin, generics.GenericAPIView):
queryset = MyObject.objects.all()
serializer_class = MyObjectSerializer
def put(self, request, *args, **kwargs):
logger.debug("myID = %s" % kwargs["myID"])
...
Here is an excerpt from urls.py:
url(r'^api/myEndpoint/(?P<myID>\d+)/?$', views.MyEndPoint.as_view()),
In your command line example you're using -u myUser:myPassword
, so you're explicitly authenticating with HTTP Basic authentication.
In the AJAX example you're not doing that, and instead the authentication is implicitly session-based. That means you need to be including a CSRF token.
Take a look at the documentation for how to include CSRF tokens, here and here.