From 9dccbcbb3800f83149edf08330f6926659bc5d73 Mon Sep 17 00:00:00 2001 From: Dave Kuhn Date: Sun, 3 Mar 2013 00:00:58 +1100 Subject: [PATCH 1/4] Support for X-HTTP-Method-Override header --- rest_framework/request.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rest_framework/request.py b/rest_framework/request.py index 3e2fbd88e..4cdc8b738 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -231,9 +231,15 @@ class Request(object): """ self._content_type = self.META.get('HTTP_CONTENT_TYPE', self.META.get('CONTENT_TYPE', '')) + + # Look for method override in header + self._method = self.META.get('HTTP_X_HTTP_METHOD_OVERRIDE', None) + if self._method: + return + self._perform_form_overloading() # if the HTTP method was not overloaded, we take the raw HTTP method - if not _hasattr(self, '_method'): + if self._method: self._method = self._request.method def _load_stream(self): From 104614c600a391b2d416074f3929e543b86a8492 Mon Sep 17 00:00:00 2001 From: Dave Kuhn Date: Mon, 4 Mar 2013 07:14:38 +1100 Subject: [PATCH 2/4] Modified to allow form overloading to take precedence over header. --- rest_framework/request.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/rest_framework/request.py b/rest_framework/request.py index 4cdc8b738..f26d934d7 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -232,15 +232,12 @@ class Request(object): self._content_type = self.META.get('HTTP_CONTENT_TYPE', self.META.get('CONTENT_TYPE', '')) - # Look for method override in header - self._method = self.META.get('HTTP_X_HTTP_METHOD_OVERRIDE', None) - if self._method: - return - self._perform_form_overloading() - # if the HTTP method was not overloaded, we take the raw HTTP method - if self._method: - self._method = self._request.method + if not _hasattr(self, '_method'): + # Method wasn't overloaded by hidden form element, so look for + # method override in header. If not present default to raw HTTP method + self._method = self.META.get('HTTP_X_HTTP_METHOD_OVERRIDE', + self._request.method) def _load_stream(self): """ From 2e481f3318609fff5b884a09cbc9d2c5782deae4 Mon Sep 17 00:00:00 2001 From: Dave Kuhn Date: Tue, 12 Mar 2013 12:00:41 +1100 Subject: [PATCH 3/4] Added test for X-HTTP-Method-Override header --- rest_framework/tests/request.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rest_framework/tests/request.py b/rest_framework/tests/request.py index 4892f7a63..97e5af207 100644 --- a/rest_framework/tests/request.py +++ b/rest_framework/tests/request.py @@ -58,6 +58,14 @@ class TestMethodOverloading(TestCase): request = Request(factory.post('/', {api_settings.FORM_METHOD_OVERRIDE: 'DELETE'})) self.assertEqual(request.method, 'DELETE') + def test_x_http_method_override_header(self): + """ + POST requests can also be overloaded to another method by setting + the X-HTTP-Method-Override header. + """ + request = Request(factory.post('/', {'foo': 'bar'}, HTTP_X_HTTP_METHOD_OVERRIDE='DELETE')) + self.assertEqual(request.method, 'DELETE') + class TestContentParsing(TestCase): def test_standard_behaviour_determines_no_content_GET(self): From 2bcb8ff12c967e71fb4871a9ac9e72395394d291 Mon Sep 17 00:00:00 2001 From: Dave Kuhn Date: Tue, 12 Mar 2013 13:48:40 +1100 Subject: [PATCH 4/4] Documentation for X-HTTP-Method-Override --- docs/topics/browser-enhancements.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/topics/browser-enhancements.md b/docs/topics/browser-enhancements.md index 6a11f0fac..8b1914231 100644 --- a/docs/topics/browser-enhancements.md +++ b/docs/topics/browser-enhancements.md @@ -19,6 +19,23 @@ For example, given the following form: `request.method` would return `"DELETE"`. +## HTTP header based method overriding + +REST framework also supports method overriding via the `X-HTTP-Method-Override` +header. This is useful if you are working with non-form content such as +JSON and are working with an older web server and/or hosting provider +(e.g. [Amazon Web Services ELB][aws_elb]) that doesn't recognise particular +HTTP methods such as `PATCH`. + +For example, making a `PATCH` request via `POST` in jQuery: + + $.ajax({ + url: '/myresource/', + method: 'POST', + headers: {'X-HTTP-Method-Override': 'PATCH'}, + ... + }); + ## Browser based submission of non-form content Browser-based submission of content types other than form are supported by @@ -62,3 +79,4 @@ as well as how to support content types other than form-encoded data. [rails]: http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-put-or-delete-methods-work [html5]: http://www.w3.org/TR/html5-diff/#changes-2010-06-24 [put_delete]: http://amundsen.com/examples/put-delete-forms/ +[aws_elb]: https://forums.aws.amazon.com/thread.jspa?messageID=400724