From df563fae23580062bc6d443fd2fa1c640bba4220 Mon Sep 17 00:00:00 2001 From: Adam Lowry Date: Tue, 9 Jun 2009 17:16:41 -0700 Subject: [PATCH] POSTs and PUTs with invalid data for the content-type return 400 Bad Request --- piston/resource.py | 8 ++++++-- piston/utils.py | 16 ++++++++++------ tests/test_project/apps/testapp/tests.py | 16 +++++++++++++++- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/piston/resource.py b/piston/resource.py index 57bb3e6..d78121e 100644 --- a/piston/resource.py +++ b/piston/resource.py @@ -12,7 +12,7 @@ from handler import typemapper from doc import HandlerMethod from authentication import NoAuthentication from utils import coerce_put_post, FormValidationError, HttpStatusCode -from utils import rc, format_error, translate_mime +from utils import rc, format_error, translate_mime, MimerDataException class Resource(object): """ @@ -85,7 +85,11 @@ class Resource(object): anonymous = handler.is_anonymous # Translate nested datastructs into `request.data` here. - translate_mime(request) + if rm in ('POST', 'PUT'): + try: + translate_mime(request) + except MimerDataException: + return rc.BAD_REQUEST if not rm in handler.allowed_methods: return HttpResponseNotAllowed(handler.allowed_methods) diff --git a/piston/utils.py b/piston/utils.py index 2d32920..3b57a49 100644 --- a/piston/utils.py +++ b/piston/utils.py @@ -1,4 +1,5 @@ -from django.http import HttpResponseNotAllowed, HttpResponseForbidden, HttpResponse +from django.http import (HttpResponseNotAllowed, HttpResponseForbidden, + HttpResponse, HttpResponseBadRequest) from django.core.urlresolvers import reverse from django.core.cache import cache from django import get_version as django_version @@ -146,6 +147,11 @@ def coerce_put_post(request): request.PUT = request.POST + +class MimerDataException(Exception): + """Raised if the content_type and data don't match""" + + class Mimer(object): TYPES = dict() @@ -208,11 +214,9 @@ class Mimer(object): # Reset both POST and PUT from request, as its # misleading having their presence around. self.request.POST = self.request.PUT = dict() - except TypeError: - return rc.BAD_REQUEST # TODO: Handle this in super - except Exception, e: - raise - + except (TypeError, ValueError): + raise MimerDataException + return self.request @classmethod diff --git a/tests/test_project/apps/testapp/tests.py b/tests/test_project/apps/testapp/tests.py index 29a3abf..cb70579 100644 --- a/tests/test_project/apps/testapp/tests.py +++ b/tests/test_project/apps/testapp/tests.py @@ -227,7 +227,14 @@ class IncomingExpressiveTests(MainTests): HTTP_AUTHORIZATION=self.auth_string).content self.assertEquals(result, expected) - + + def test_incoming_invalid_json(self): + resp = self.client.post('/api/expressive.json', + 'foo', + HTTP_AUTHORIZATION=self.auth_string, + content_type='application/json') + self.assertEquals(resp.status_code, 400) + def test_incoming_yaml(self): if not yaml: return @@ -267,6 +274,13 @@ class IncomingExpressiveTests(MainTests): self.assertEquals(self.client.get('/api/expressive.yaml', HTTP_AUTHORIZATION=self.auth_string).content, expected) + def test_incoming_invalid_yaml(self): + resp = self.client.post('/api/expressive.yaml', + ' 8**sad asj lja foo', + HTTP_AUTHORIZATION=self.auth_string, + content_type='application/yaml') + self.assertEquals(resp.status_code, 400) + class Issue36RegressionTests(MainTests): """ This testcase addresses #36 in django-piston where request.FILES is passed