From 79755dc624bbfac489e9bb6c2e301330bae457fa Mon Sep 17 00:00:00 2001 From: Jim Paris Date: Mon, 4 Mar 2013 14:08:37 -0500 Subject: [PATCH] Fix Allow: header by switching to cherrypy's built in tools.allow(). Replaces custom tools.allow_methods which didn't return the Allow: header. --- nilmdb/server/server.py | 27 ++++++++------------------- tests/test_client.py | 6 ------ tests/test_cmdline.py | 5 ----- tests/test_layout.py | 7 ------- tests/test_nilmdb.py | 12 +++++++++--- 5 files changed, 17 insertions(+), 40 deletions(-) diff --git a/nilmdb/server/server.py b/nilmdb/server/server.py index 3be56f6..a26a70f 100644 --- a/nilmdb/server/server.py +++ b/nilmdb/server/server.py @@ -71,17 +71,6 @@ def exception_to_httperror(*expected): # care of that. return decorator.decorator(wrapper) -# Custom Cherrypy tools -def allow_methods(methods): - method = cherrypy.request.method.upper() - if method not in methods: - if method in cherrypy.request.methods_with_bodies: - cherrypy.request.body.read() - allowed = ', '.join(methods) - cherrypy.response.headers['Allow'] = allowed - raise cherrypy.HTTPError(405, method + " not allowed; use " + allowed) -cherrypy.tools.allow_methods = cherrypy.Tool('before_handler', allow_methods) - # CherryPy apps class Root(NilmApp): """Root application for NILM database""" @@ -142,7 +131,7 @@ class Stream(NilmApp): @cherrypy.expose @cherrypy.tools.json_out() @exception_to_httperror(NilmDBError, ValueError) - @cherrypy.tools.allow_methods(methods = ["POST"]) + @cherrypy.tools.allow(methods = ["POST"]) def create(self, path, layout): """Create a new stream in the database. Provide path and one of the nilmdb.layout.layouts keys. @@ -153,7 +142,7 @@ class Stream(NilmApp): @cherrypy.expose @cherrypy.tools.json_out() @exception_to_httperror(NilmDBError) - @cherrypy.tools.allow_methods(methods = ["POST"]) + @cherrypy.tools.allow(methods = ["POST"]) def destroy(self, path): """Delete a stream and its associated data.""" return self.db.stream_destroy(path) @@ -186,7 +175,7 @@ class Stream(NilmApp): @cherrypy.expose @cherrypy.tools.json_out() @exception_to_httperror(NilmDBError, LookupError, TypeError) - @cherrypy.tools.allow_methods(methods = ["POST"]) + @cherrypy.tools.allow(methods = ["POST"]) def set_metadata(self, path, data): """Set metadata for the named stream, replacing any existing metadata. Data should be a json-encoded @@ -198,7 +187,7 @@ class Stream(NilmApp): @cherrypy.expose @cherrypy.tools.json_out() @exception_to_httperror(NilmDBError, LookupError, TypeError) - @cherrypy.tools.allow_methods(methods = ["POST"]) + @cherrypy.tools.allow(methods = ["POST"]) def update_metadata(self, path, data): """Update metadata for the named stream. Data should be a json-encoded dictionary""" @@ -208,7 +197,7 @@ class Stream(NilmApp): # /stream/insert?path=/newton/prep @cherrypy.expose @cherrypy.tools.json_out() - @cherrypy.tools.allow_methods(methods = ["PUT"]) + @cherrypy.tools.allow(methods = ["PUT"]) def insert(self, path, start, end): """ Insert new data into the database. Provide textual data @@ -264,7 +253,7 @@ class Stream(NilmApp): @cherrypy.expose @cherrypy.tools.json_out() @exception_to_httperror(NilmDBError) - @cherrypy.tools.allow_methods(methods = ["POST"]) + @cherrypy.tools.allow(methods = ["POST"]) def remove(self, path, start = None, end = None): """ Remove data from the backend database. Removes all data in @@ -427,8 +416,8 @@ class Server(object): # Only allow GET and HEAD by default. Individual handlers # can override. - app_config.update({ 'tools.allow_methods.on': True, - 'tools.allow_methods.methods': ['GET', 'HEAD'] }) + app_config.update({ 'tools.allow.on': True, + 'tools.allow.methods': ['GET', 'HEAD'] }) # Send tracebacks in error responses. They're hidden by the # error_page function for client errors (code 400-499). diff --git a/tests/test_client.py b/tests/test_client.py index 1d9d030..89a7fe7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -55,12 +55,6 @@ class TestClient(object): client.version() client.close() - # Trigger same error with a PUT request - client = nilmdb.Client(url = "http://localhost:1/") - with assert_raises(nilmdb.client.ServerError): - client.version() - client.close() - # Then a fake URL on a real host client = nilmdb.Client(url = "http://localhost:32180/fake/") with assert_raises(nilmdb.client.ClientError): diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index 14037f4..4ea8a17 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -11,12 +11,7 @@ from nose.tools import assert_raises import itertools import os import re -import shutil import sys -import threading -import urllib2 -from urllib2 import urlopen, HTTPError -import Queue import StringIO import shlex diff --git a/tests/test_layout.py b/tests/test_layout.py index 178307d..9d9dd1c 100644 --- a/tests/test_layout.py +++ b/tests/test_layout.py @@ -9,14 +9,7 @@ from nose.tools import assert_raises import distutils.version import itertools import os -import shutil import sys -import cherrypy -import threading -import urllib2 -from urllib2 import urlopen, HTTPError -import Queue -import cStringIO import random import unittest diff --git a/tests/test_nilmdb.py b/tests/test_nilmdb.py index 319ab95..6213bef 100644 --- a/tests/test_nilmdb.py +++ b/tests/test_nilmdb.py @@ -6,15 +6,13 @@ import distutils.version import simplejson as json import itertools import os -import shutil import sys -import cherrypy import threading import urllib2 from urllib2 import urlopen, HTTPError -import Queue import cStringIO import time +import requests from nilmdb.utils import serializer_proxy @@ -208,3 +206,11 @@ class TestServer(object): data = getjson("/stream/get_metadata?path=/newton/prep" "&key=foo") eq_(data, {'foo': None}) + + def test_options(self): + # OPTIONS request should be disallowed, but should return + # a Allow: heeader. + r = requests.options("http://127.0.0.1:32180/stream/list") + eq_(r.status_code, 405) + eq_(r.headers["allow"], "GET, HEAD") + in_("405 Method Not Allowed", r.text)