Add HTTP OPTIONS support
The OPTIONS HTTP method allows clients to query the allowed methods
on a given path.
Change-Id: I762e85a6dbe2df3473dfa79c252c51ebe49c3ecb
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/module/obmc/wsgi/apps/rest_dbus.py b/module/obmc/wsgi/apps/rest_dbus.py
index aa08bfa..ead6ec5 100644
--- a/module/obmc/wsgi/apps/rest_dbus.py
+++ b/module/obmc/wsgi/apps/rest_dbus.py
@@ -76,16 +76,23 @@
if 'GET' in self._verbs:
self._verbs = list(set(self._verbs + ['HEAD']))
+ if 'OPTIONS' not in self._verbs:
+ self._verbs.append('OPTIONS')
def _setup(self, **kw):
request.route_data = {}
+
if request.method in self._verbs:
- return self.setup(**kw)
+ if request.method != 'OPTIONS':
+ return self.setup(**kw)
- # Return 404 if path not found.
- self.find(**kw)
+ # Javascript implementations will not send credentials
+ # with an OPTIONS request. Don't help malicious clients
+ # by checking the path here and returning a 404 if the
+ # path doesn't exist.
+ return None
- # Return 405.
+ # Return 405
raise HTTPError(
405, "Method not allowed.", Allow=','.join(self._verbs))
@@ -95,10 +102,17 @@
def do_head(self, **kw):
return self.do_get(**kw)
+ def do_options(self, **kw):
+ for v in self._verbs:
+ response.set_header(
+ 'Allow',
+ ','.join(self._verbs))
+ return None
+
def install(self):
self.app.route(
self._rules, callback=self,
- method=['GET', 'PUT', 'PATCH', 'POST', 'DELETE'])
+ method=['OPTIONS', 'GET', 'PUT', 'PATCH', 'POST', 'DELETE'])
@staticmethod
def try_mapper_call(f, callback=None, **kw):
@@ -525,8 +539,9 @@
def __call__(self, *a, **kw):
sid = request.get_cookie('sid', secret=self.session_mgr.hmac_key)
session = self.session_mgr.get_session(sid)
- for x in self.validators:
- x(session, *a, **kw)
+ if request.method != 'OPTIONS':
+ for x in self.validators:
+ x(session, *a, **kw)
return self.callback(*a, **kw)
@@ -633,15 +648,21 @@
name = 'json_api_response'
api = 2
+ @staticmethod
+ def has_body():
+ return request.method not in ['OPTIONS']
+
def __init__(self, app):
app.install_error_callback(self.error_callback)
def apply(self, callback, route):
def wrap(*a, **kw):
- resp = {'data': callback(*a, **kw)}
- resp['status'] = 'ok'
- resp['message'] = response.status_line
- return resp
+ data = callback(*a, **kw)
+ if self.has_body():
+ resp = {'data': data}
+ resp['status'] = 'ok'
+ resp['message'] = response.status_line
+ return resp
return wrap
def error_callback(self, error, response_object, **kw):