diff roundup/rest.py @ 5620:5f8e6034427c

Do not honor the X-HTTP-Method-Override if the original method used was GET. GET's are supposed to be a safe operation. Require a non-GET method (POST is suggested) in order for the override to occur.
author John Rouillard <rouilj@ieee.org>
date Sun, 24 Feb 2019 21:34:17 -0500
parents 1c9208fa9127
children 39dbe83643c0
line wrap: on
line diff
--- a/roundup/rest.py	Sat Feb 16 16:12:37 2019 -0500
+++ b/roundup/rest.py	Sun Feb 24 21:34:17 2019 -0500
@@ -32,6 +32,9 @@
     basestring = str
     unicode = str
 
+import logging
+logger = logging.getLogger('roundup.rest')
+
 def _data_decorator(func):
     """Wrap the returned data into an object."""
     def format_object(self, *args, **kwargs):
@@ -1110,7 +1113,21 @@
         """format and process the request"""
         # if X-HTTP-Method-Override is set, follow the override method
         headers = self.client.request.headers
-        method = headers.getheader('X-HTTP-Method-Override') or method
+        # Never allow GET to be an unsafe operation (i.e. data changing).
+        # User must use POST to "tunnel" DELETE, PUT, OPTIONS etc.
+        override = headers.getheader('X-HTTP-Method-Override')
+        output = None
+        if override:
+            if method.upper() != 'GET':
+                logger.debug(
+                    'Method overridden from %s to %s', method, override)
+                method = override
+            else:
+                output = self.error_obj(400,
+                               "X-HTTP-Method-Override: %s can not be used with GET method. Use Post instead." % override)
+                logger.info(
+                    'Ignoring X-HTTP-Method-Override for GET request on %s',
+                    uri)
 
         # parse Accept header and get the content type
         accept_header = parse_accept_header(headers.getheader('Accept'))
@@ -1154,7 +1171,10 @@
 
         # Call the appropriate method
         try:
-            output = Routing.execute(self, uri, method, input)
+            # If output was defined by a prior error
+            # condition skip call
+            if not output:
+                output = Routing.execute(self, uri, method, input)
         except NotFound as msg:
             output = self.error_obj(404, msg)
         except Reject as msg:

Roundup Issue Tracker: http://roundup-tracker.org/