Finally figured out what's going on. My hypothesis: An HTTP request with POST method sent to a Django view wrapped with @csrf_exempt will still raise a 403 CSRF error if the wrapped view raises an Http404 exception.
In this specific case, we raise 404 when there is no valid video_id passed in the POST request: 264 # Make sure there's at least one 265 if len(distro_list) < 1: 266 raise Http404 Raising a 403 was obviously not the result behavior we expected, instead we would have expected the 404 to be raised without CSRF interfering given the initial view was properly wrapped with @csrf_exempt. Further contributing, this was rather difficult to diagnose due to the opaque 403 error message even when DEBUG = True. Is this expected Django behavior? If not, can we please address this in a future release? Is there a better way to provide debugging information for 403 errors raised from the built-in CSRF methods? All the best and thanks for a great framework. Kieran On Jul 27, 6:54 pm, Kieran Farr <kieran.f...@gmail.com> wrote: > Further research shows that CSRF is enabled regardless of my > settings.py if we use Django's built-in auth. > > Obviously, we need to still use Django's auth, so we can't just > disable CSRF site-wide like this > hack:http://stackoverflow.com/questions/1650941/django-csrf-framework-cann... > ...or this hack...http://djangosnippets.org/snippets/2069/ > > Obviously also, we have no control over the third-party server sending > the POST request, so we can't resort to this > hack:http://stackoverflow.com/questions/2405353/having-a-postable-api-and-... > > The decorator @csrf_exempt does not work as described in the docs as > our view always returns a 403 when any content is POSTed. > > Very confusing! > > Kieran > > On Jul 27, 1:32 pm, Kieran Farr <kieran.f...@gmail.com> wrote: > > > > > Raj sorry I misread your question. This initial response is in re: my > > listener. > > > The "sender" of this POST request is a third party server that we have > > no control over. > > > However, even when debugging with wget we receive the 403. > > > Here is the wget command I've been testing with: > > > $ wgethttp://www.url.com/subdir/listener/--post-data"?test=test" -U > > "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/ > > 533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16" > > > --2010-07-27 20:06:36-- http://www.url.com/subdir/listener/ > > Resolving [URL] ... [IP ADDRESS] > > Connecting to [URL]|[IP ADDRESS]|:80... connected. > > HTTP request sent, awaiting response... 403 Forbidden > > 2010-07-27 20:06:37 ERROR 403: Forbidden. > > > However, if I send without the post-data, here's the response: > > > $ wgethttp://www.url.com/subdir/listener/ > > > --2010-07-27 20:31:14-- http://www.url.com/subdir/listener/ > > Resolving [URL]... [IP ADDRESS] > > Connecting to [URL|[IP ADDRESS]|:80... connected. > > HTTP request sent, awaiting response... 200 OK > > Length: unspecified [text/plain] > > Saving to: `index.html.1' > > > [ <=> > > ] > > 27 --.-K/s in 0s > > > 2010-07-27 20:31:14 (1.84 MB/s) - `index.html.1' saved [27] > > > On Jul 27, 11:34 am, Kieran Farr <kieran.f...@gmail.com> wrote: > > > > This is intended not to be protected by auth, so this page is publicly > > > accessible, no login required. > > > > Here's the function in its entirety: > > > > 255 @csrf_response_exempt > > > 256 def DistroHeySpreadListener(request): > > > 257 if request.method == 'POST': > > > 258 post = request.POST > > > 259 raw = request.raw_post_data > > > 260 remote_media_id = post.get("video_id", "") > > > 261 # Try to fetch the distros for this > > > remote_media_id > > > 262 distro_list = > > > Distro.objects.filter(remote_media_id__exact=remote_media_id) > > > 263 > > > 264 # Make sure there's at least one > > > 265 if len(distro_list) < 1: > > > 266 raise Http404 > > > 267 > > > 268 # For each distro instance, check to see if > > > there's a response in this api call > > > 269 for distro in distro_list: > > > 270 # Prepare logging > > > 271 log = distro.log > > > 272 log += "Raw data from POST" + str(raw) > > > 273 distro.log = log > > > 274 distro.save() > > > 275 > > > 276 # Get distro short name > > > 277 dest_short_name = > > > distro.credential.destination.short_name > > > 278 > > > 279 # From short_name, return either error or > > > link starting with http:// > > > 280 response = post.get('link[%s]' % > > > dest_short_name, False) or post.get('error[%s]' % dest_short_name, > > > False) > > > 281 > > > 282 if response.startswith('http://'): > > > 283 # If response starts with http > > > then success, populate as link > > > 284 distro.destination_url = response > > > 285 distro.state = TRANSCODE_SUCCESS > > > 286 log += '\nSUCCESS, url = %s' % > > > response > > > 287 else: > > > 288 # Else, change state to error and > > > log error message > > > 289 log += '\nERROR, error = %s' % > > > response > > > 290 distro.state = TRANSCODE_ERROR > > > 291 > > > 292 distro.log = log > > > 293 distro.save() > > > 294 > > > 295 > > > 296 h = HttpResponse("Thanks, HeySpread! We love > > > you.", mimetype="text/plain", status=200) > > > 297 h.csrf_exempt = True > > > 298 return h > > > 299 # return HttpResponse("Thanks, HeySpread! We love > > > you.", mimetype="text/plain", status=200) > > > 300 else: > > > 301 return HttpResponse("Oops, something went wrong.", > > > mimetype="text/plain", status=200) > > > > On Jul 27, 11:30 am, raj <rajeeshrn...@gmail.com> wrote: > > > > > Most probably it has something to do with permissions. Go thru the > > > > exact code block which tries to post the data. Is the login successful > > > > and does the logged-in user have got all necessary permissions > > > > required? Post that part of the code if you can't find out. > > > > > Rajeesh. > > > > > On Jul 27, 11:20 pm, Kieran Farr <kieran.f...@gmail.com> wrote: > > > > > > Further, debugging 403s is nearly impossible. It'd be very helpful > > > > > when in DEBUG mode to reveal who/what/why raised the 403. > > > > > > > What am I doing wrong/missing? -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.