diff --git a/bottle-rest b/bottle-rest
deleted file mode 100644
index f655599..0000000
--- a/bottle-rest
+++ /dev/null
@@ -1,593 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import sys
-import dbus
-import dbus.exceptions
-import json
-import logging
-from xml.etree import ElementTree
-from rocket import Rocket
-from bottle import Bottle, abort, request, response, JSONPlugin, HTTPError
-import OpenBMCMapper
-from OpenBMCMapper import Mapper, PathTree, IntrospectionNodeParser, ListMatch
-
-DBUS_UNKNOWN_INTERFACE = 'org.freedesktop.UnknownInterface'
-DBUS_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
-DBUS_INVALID_ARGS = 'org.freedesktop.DBus.Error.InvalidArgs'
-DELETE_IFACE = 'org.openbmc.object.Delete'
-
-_4034_msg = "The specified %s cannot be %s: '%s'"
-
-def find_case_insensitive(value, lst):
-	return next((x for x in lst if x.lower() == value.lower()), None)
-
-def makelist(data):
-	if isinstance(data, list):
-		return data
-	elif data:
-		return [data]
-	else:
-		return []
-
-class RouteHandler(object):
-	def __init__(self, app, bus, verbs, rules):
-		self.app = app
-		self.bus = bus
-		self.mapper = Mapper(bus)
-		self._verbs = makelist(verbs)
-		self._rules = rules
-
-	def _setup(self, **kw):
-		request.route_data = {}
-		if request.method in self._verbs:
-			return self.setup(**kw)
-		else:
-			self.find(**kw)
-			raise HTTPError(405, "Method not allowed.",
-					Allow=','.join(self._verbs))
-
-	def __call__(self, **kw):
-		return getattr(self, 'do_' + request.method.lower())(**kw)
-
-	def install(self):
-		self.app.route(self._rules, callback = self,
-				method = ['GET', 'PUT', 'PATCH', 'POST', 'DELETE'])
-
-	@staticmethod
-	def try_mapper_call(f, callback = None, **kw):
-		try:
-			return f(**kw)
-		except dbus.exceptions.DBusException, e:
-			if e.get_dbus_name() != OpenBMCMapper.MAPPER_NOT_FOUND:
-				raise
-			if callback is None:
-				def callback(e, **kw):
-					abort(404, str(e))
-
-			callback(e, **kw)
-
-	@staticmethod
-	def try_properties_interface(f, *a):
-		try:
-			return f(*a)
-		except dbus.exceptions.DBusException, e:
-			if DBUS_UNKNOWN_INTERFACE in e.get_dbus_message():
-				# interface doesn't have any properties
-				return None
-			if DBUS_UNKNOWN_METHOD == e.get_dbus_name():
-				# properties interface not implemented at all
-				return None
-			raise
-
-class DirectoryHandler(RouteHandler):
-	verbs = 'GET'
-	rules = '<path:path>/'
-
-	def __init__(self, app, bus):
-		super(DirectoryHandler, self).__init__(
-				app, bus, self.verbs, self.rules)
-
-	def find(self, path = '/'):
-		return self.try_mapper_call(
-				self.mapper.get_subtree_paths,
-				path = path, depth = 1)
-
-	def setup(self, path = '/'):
-		request.route_data['map'] = self.find(path)
-
-	def do_get(self, path = '/'):
-		return request.route_data['map']
-
-class ListNamesHandler(RouteHandler):
-	verbs = 'GET'
-	rules = ['/list', '<path:path>/list']
-
-	def __init__(self, app, bus):
-		super(ListNamesHandler, self).__init__(
-				app, bus, self.verbs, self.rules)
-
-	def find(self, path = '/'):
-		return self.try_mapper_call(
-				self.mapper.get_subtree, path = path).keys()
-
-	def setup(self, path = '/'):
-		request.route_data['map'] = self.find(path)
-
-	def do_get(self, path = '/'):
-		return request.route_data['map']
-
-class ListHandler(RouteHandler):
-	verbs = 'GET'
-	rules = ['/enumerate', '<path:path>/enumerate']
-
-	def __init__(self, app, bus):
-		super(ListHandler, self).__init__(
-				app, bus, self.verbs, self.rules)
-
-	def find(self, path = '/'):
-		return self.try_mapper_call(
-				self.mapper.get_subtree, path = path)
-
-	def setup(self, path = '/'):
-		request.route_data['map'] = self.find(path)
-
-	def do_get(self, path = '/'):
-		objs = {}
-		mapper_data = request.route_data['map']
-		tree = PathTree()
-		for x,y in mapper_data.iteritems():
-			tree[x] = y
-
-		try:
-			# Check to see if the root path implements
-			# enumerate in addition to any sub tree
-			# objects.
-			root = self.try_mapper_call(self.mapper.get_object,
-					path = path)
-			mapper_data[path] = root
-		except:
-			pass
-
-		have_enumerate = [ (x[0], self.enumerate_capable(*x)) \
-				for x in mapper_data.iteritems() \
-					if self.enumerate_capable(*x) ]
-
-		for x,y in have_enumerate:
-			objs.update(self.call_enumerate(x, y))
-			tmp = tree[x]
-			# remove the subtree
-			del tree[x]
-			# add the new leaf back since enumerate results don't
-			# include the object enumerate is being invoked on
-			tree[x] = tmp
-
-		# make dbus calls for any remaining objects
-		for x,y in tree.dataitems():
-			objs[x] = self.app.instance_handler.do_get(x)
-
-		return objs
-
-	@staticmethod
-	def enumerate_capable(path, bus_data):
-		busses = []
-		for name, ifaces in bus_data.iteritems():
-			if OpenBMCMapper.ENUMERATE_IFACE in ifaces:
-				busses.append(name)
-		return busses
-
-	def call_enumerate(self, path, busses):
-		objs = {}
-		for b in busses:
-			obj = self.bus.get_object(b, path, introspect = False)
-			iface = dbus.Interface(obj, OpenBMCMapper.ENUMERATE_IFACE)
-			objs.update(iface.enumerate())
-		return objs
-
-class MethodHandler(RouteHandler):
-	verbs = 'POST'
-	rules = '<path:path>/action/<method>'
-	request_type = list
-
-	def __init__(self, app, bus):
-		super(MethodHandler, self).__init__(
-				app, bus, self.verbs, self.rules)
-
-	def find(self, path, method):
-		busses = self.try_mapper_call(self.mapper.get_object,
-				path = path)
-		for items in busses.iteritems():
-			m = self.find_method_on_bus(path, method, *items)
-			if m:
-				return m
-
-		abort(404, _4034_msg %('method', 'found', method))
-
-	def setup(self, path, method):
-		request.route_data['method'] = self.find(path, method)
-
-	def do_post(self, path, method):
-		try:
-			if request.parameter_list:
-				return request.route_data['method'](*request.parameter_list)
-			else:
-				return request.route_data['method']()
-
-		except dbus.exceptions.DBusException, e:
-			if e.get_dbus_name() == DBUS_INVALID_ARGS:
-				abort(400, str(e))
-			raise
-
-	@staticmethod
-	def find_method_in_interface(method, obj, interface, methods):
-		if methods is None:
-			return None
-
-		method = find_case_insensitive(method, methods.keys())
-		if method is not None:
-			iface = dbus.Interface(obj, interface)
-			return iface.get_dbus_method(method)
-
-	def find_method_on_bus(self, path, method, bus, interfaces):
-		obj = self.bus.get_object(bus, path, introspect = False)
-		iface = dbus.Interface(obj, dbus.INTROSPECTABLE_IFACE)
-		data = iface.Introspect()
-		parser = IntrospectionNodeParser(
-				ElementTree.fromstring(data),
-				intf_match = ListMatch(interfaces))
-		for x,y in parser.get_interfaces().iteritems():
-			m = self.find_method_in_interface(method, obj, x,
-					y.get('method'))
-			if m:
-				return m
-
-class PropertyHandler(RouteHandler):
-	verbs = ['PUT', 'GET']
-	rules = '<path:path>/attr/<prop>'
-
-	def __init__(self, app, bus):
-		super(PropertyHandler, self).__init__(
-				app, bus, self.verbs, self.rules)
-
-	def find(self, path, prop):
-		self.app.instance_handler.setup(path)
-		obj = self.app.instance_handler.do_get(path)
-		try:
-			obj[prop]
-		except KeyError, e:
-			if request.method == 'PUT':
-				abort(403, _4034_msg %('property', 'created', str(e)))
-			else:
-				abort(404, _4034_msg %('property', 'found', str(e)))
-
-		return { path: obj }
-
-	def setup(self, path, prop):
-		request.route_data['obj'] = self.find(path, prop)
-
-	def do_get(self, path, prop):
-		return request.route_data['obj'][path][prop]
-
-	def do_put(self, path, prop, value = None):
-		if value is None:
-			value = request.parameter_list
-
-		prop, iface, properties_iface = self.get_host_interface(
-				path, prop, request.route_data['map'][path])
-		try:
-			properties_iface.Set(iface, prop, value)
-		except ValueError, e:
-			abort(400, str(e))
-		except dbus.exceptions.DBusException, e:
-			if e.get_dbus_name() == DBUS_INVALID_ARGS:
-				abort(403, str(e))
-			raise
-
-	def get_host_interface(self, path, prop, bus_info):
-		for bus, interfaces in bus_info.iteritems():
-			obj = self.bus.get_object(bus, path, introspect = True)
-			properties_iface = dbus.Interface(
-				obj, dbus_interface=dbus.PROPERTIES_IFACE)
-
-			info = self.get_host_interface_on_bus(
-					path, prop, properties_iface,
-					bus, interfaces)
-			if info is not None:
-				prop, iface = info
-				return prop, iface, properties_iface
-
-	def get_host_interface_on_bus(self, path, prop, iface, bus, interfaces):
-		for i in interfaces:
-			properties = self.try_properties_interface(iface.GetAll, i)
-			if properties is None:
-				continue
-			prop = find_case_insensitive(prop, properties.keys())
-			if prop is None:
-				continue
-			return prop, i
-
-class InstanceHandler(RouteHandler):
-	verbs = ['GET', 'PUT', 'DELETE']
-	rules = '<path:path>'
-	request_type = dict
-
-	def __init__(self, app, bus):
-		super(InstanceHandler, self).__init__(
-				app, bus, self.verbs, self.rules)
-
-	def find(self, path, callback = None):
-		return { path: self.try_mapper_call(
-			self.mapper.get_object,
-			callback,
-			path = path) }
-
-	def setup(self, path):
-		callback = None
-		if request.method == 'PUT':
-			def callback(e, **kw):
-				abort(403, _4034_msg %('resource',
-					'created', path))
-
-		if request.route_data.get('map') is None:
-			request.route_data['map'] = self.find(path, callback)
-
-	def do_get(self, path):
-		properties = {}
-		for item in request.route_data['map'][path].iteritems():
-			properties.update(self.get_properties_on_bus(
-				path, *item))
-
-		return properties
-
-	@staticmethod
-	def get_properties_on_iface(properties_iface, iface):
-		properties = InstanceHandler.try_properties_interface(
-				properties_iface.GetAll, iface)
-		if properties is None:
-			return {}
-		return properties
-
-	def get_properties_on_bus(self, path, bus, interfaces):
-		properties = {}
-		obj = self.bus.get_object(bus, path, introspect = False)
-		properties_iface = dbus.Interface(
-				obj, dbus_interface=dbus.PROPERTIES_IFACE)
-		for i in interfaces:
-			properties.update(self.get_properties_on_iface(
-				properties_iface, i))
-
-		return properties
-
-	def do_put(self, path):
-		# make sure all properties exist in the request
-		obj = set(self.do_get(path).keys())
-		req = set(request.parameter_list.keys())
-
-		diff = list(obj.difference(req))
-		if diff:
-			abort(403, _4034_msg %('resource', 'removed',
-				'%s/attr/%s' %(path, diff[0])))
-
-		diff = list(req.difference(obj))
-		if diff:
-			abort(403, _4034_msg %('resource', 'created',
-				'%s/attr/%s' %(path, diff[0])))
-
-		for p,v in request.parameter_list.iteritems():
-			self.app.property_handler.do_put(
-					path, p, v)
-
-	def do_delete(self, path):
-		for bus_info in request.route_data['map'][path].iteritems():
-			if self.bus_missing_delete(path, *bus_info):
-				abort(403, _4034_msg %('resource', 'removed',
-					path))
-
-		for bus in request.route_data['map'][path].iterkeys():
-			self.delete_on_bus(path, bus)
-
-	def bus_missing_delete(self, path, bus, interfaces):
-		return DELETE_IFACE not in interfaces
-
-	def delete_on_bus(self, path, bus):
-		obj = self.bus.get_object(bus, path, introspect = False)
-		delete_iface = dbus.Interface(
-				obj, dbus_interface = DELETE_IFACE)
-		delete_iface.Delete()
-
-class JsonApiRequestPlugin(object):
-	''' Ensures request content satisfies the OpenBMC json api format. '''
-	name = 'json_api_request'
-	api = 2
-
-	error_str = "Expecting request format { 'data': <value> }, got '%s'"
-	type_error_str = "Unsupported Content-Type: '%s'"
-	json_type = "application/json"
-	request_methods = ['PUT', 'POST', 'PATCH']
-
-	@staticmethod
-	def content_expected():
-		return request.method in JsonApiRequestPlugin.request_methods
-
-	def validate_request(self):
-		if request.content_length > 0 and \
-				request.content_type != self.json_type:
-			abort(415, self.type_error_str %(request.content_type))
-
-		try:
-			request.parameter_list = request.json.get('data')
-		except ValueError, e:
-			abort(400, str(e))
-		except (AttributeError, KeyError, TypeError):
-			abort(400, self.error_str %(request.json))
-
-	def apply(self, callback, route):
-		verbs = getattr(route.get_undecorated_callback(),
-				'_verbs', None)
-		if verbs is None:
-			return callback
-
-		if not set(self.request_methods).intersection(verbs):
-			return callback
-
-		def wrap(*a, **kw):
-			if self.content_expected():
-				self.validate_request()
-			return callback(*a, **kw)
-
-		return wrap
-
-class JsonApiRequestTypePlugin(object):
-	''' Ensures request content type satisfies the OpenBMC json api format. '''
-	name = 'json_api_method_request'
-	api = 2
-
-	error_str = "Expecting request format { 'data': %s }, got '%s'"
-
-	def apply(self, callback, route):
-		request_type = getattr(route.get_undecorated_callback(),
-				'request_type', None)
-		if request_type is None:
-			return callback
-
-		def validate_request():
-			if not isinstance(request.parameter_list, request_type):
-				abort(400, self.error_str %(str(request_type), request.json))
-
-		def wrap(*a, **kw):
-			if JsonApiRequestPlugin.content_expected():
-				validate_request()
-			return callback(*a, **kw)
-
-		return wrap
-
-class JsonApiResponsePlugin(object):
-	''' Emits normal responses in the OpenBMC json api format. '''
-	name = 'json_api_response'
-	api = 2
-
-	def apply(self, callback, route):
-		def wrap(*a, **kw):
-			resp = { 'data': callback(*a, **kw) }
-			resp['status'] = 'ok'
-			resp['message'] = response.status_line
-			return resp
-		return wrap
-
-class JsonApiErrorsPlugin(object):
-	''' Emits error responses in the OpenBMC json api format. '''
-	name = 'json_api_errors'
-	api = 2
-
-	def __init__(self, **kw):
-		self.app = None
-		self.function_type = None
-		self.original = None
-		self.json_opts = { x:y for x,y in kw.iteritems() \
-			if x in ['indent','sort_keys'] }
-
-	def setup(self, app):
-		self.app = app
-		self.function_type = type(app.default_error_handler)
-		self.original = app.default_error_handler
-		self.app.default_error_handler = self.function_type(
-			self.json_errors, app, Bottle)
-
-	def apply(self, callback, route):
-		return callback
-
-	def close(self):
-		self.app.default_error_handler = self.function_type(
-				self.original, self.app, Bottle)
-
-	def json_errors(self, res, error):
-		response_object = {'status': 'error', 'data': {} }
-		response_object['message'] = error.status_line
-		response_object['data']['description'] = str(error.body)
-		if error.status_code == 500:
-			response_object['data']['exception'] = repr(error.exception)
-			response_object['data']['traceback'] = error.traceback.splitlines()
-
-		json_response = json.dumps(response_object, **self.json_opts)
-		res.content_type = 'application/json'
-		return json_response
-
-class RestApp(Bottle):
-	def __init__(self, bus):
-		super(RestApp, self).__init__(autojson = False)
-		self.bus = bus
-		self.mapper = Mapper(bus)
-
-		self.install_hooks()
-		self.install_plugins()
-		self.create_handlers()
-		self.install_handlers()
-
-	def install_plugins(self):
-		# install json api plugins
-		json_kw = {'indent': 2, 'sort_keys': True}
-		self.install(JSONPlugin(**json_kw))
-		self.install(JsonApiErrorsPlugin(**json_kw))
-		self.install(JsonApiResponsePlugin())
-		self.install(JsonApiRequestPlugin())
-		self.install(JsonApiRequestTypePlugin())
-
-	def install_hooks(self):
-		self.real_router_match = self.router.match
-		self.router.match = self.custom_router_match
-		self.add_hook('before_request', self.strip_extra_slashes)
-
-	def create_handlers(self):
-		# create route handlers
-		self.directory_handler = DirectoryHandler(self, self.bus)
-		self.list_names_handler = ListNamesHandler(self, self.bus)
-		self.list_handler = ListHandler(self, self.bus)
-		self.method_handler = MethodHandler(self, self.bus)
-		self.property_handler = PropertyHandler(self, self.bus)
-		self.instance_handler = InstanceHandler(self, self.bus)
-
-	def install_handlers(self):
-		self.directory_handler.install()
-		self.list_names_handler.install()
-		self.list_handler.install()
-		self.method_handler.install()
-		self.property_handler.install()
-		# this has to come last, since it matches everything
-		self.instance_handler.install()
-
-	def custom_router_match(self, environ):
-		''' The built-in Bottle algorithm for figuring out if a 404 or 405 is
-                    needed doesn't work for us since the instance rules match everything.
-                    This monkey-patch lets the route handler figure out which response is
-                    needed.  This could be accomplished with a hook but that would require
-		    calling the router match function twice.
-		'''
-		route, args = self.real_router_match(environ)
-		if isinstance(route.callback, RouteHandler):
-			route.callback._setup(**args)
-
-		return route, args
-
-	@staticmethod
-	def strip_extra_slashes():
-		path = request.environ['PATH_INFO']
-		trailing = ("","/")[path[-1] == '/']
-		parts = filter(bool, path.split('/'))
-		request.environ['PATH_INFO'] = '/' + '/'.join(parts) + trailing
-
-if __name__ == '__main__':
-	log = logging.getLogger('Rocket.Errors')
-	log.setLevel(logging.INFO)
-	log.addHandler(logging.StreamHandler(sys.stdout))
-
-	bus = dbus.SystemBus()
-	app = RestApp(bus)
-	default_cert = os.path.join(sys.prefix, 'share',
-			os.path.basename(__file__), 'cert.pem')
-
-	server = Rocket(('0.0.0.0',
-			443,
-			default_cert,
-			default_cert),
-		'wsgi', {'wsgi_app': app})
-	server.start()
diff --git a/phosphor-rest b/phosphor-rest
index 026eb74..f655599 100644
--- a/phosphor-rest
+++ b/phosphor-rest
@@ -1,273 +1,140 @@
 #!/usr/bin/env python
 
-# Contributors Listed Below - COPYRIGHT 2015
-# [+] International Business Machines Corp.
-#
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# permissions and limitations under the License.
-
-import BaseHTTPServer
-import SocketServer
-import json
+import os
+import sys
 import dbus
-from OpenBMCMapper import Path, Mapper, PathTree
+import dbus.exceptions
+import json
+import logging
+from xml.etree import ElementTree
+from rocket import Rocket
+from bottle import Bottle, abort, request, response, JSONPlugin, HTTPError
 import OpenBMCMapper
+from OpenBMCMapper import Mapper, PathTree, IntrospectionNodeParser, ListMatch
 
-class RestException(Exception):
-	def __init__(self, msg, http_status=403):
-		self.status = http_status
-		super(RestException, self).__init__(msg)
+DBUS_UNKNOWN_INTERFACE = 'org.freedesktop.UnknownInterface'
+DBUS_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
+DBUS_INVALID_ARGS = 'org.freedesktop.DBus.Error.InvalidArgs'
+DELETE_IFACE = 'org.openbmc.object.Delete'
 
-class Response(object):
-	def render(self, handler):
-		raise NotImplemented()
+_4034_msg = "The specified %s cannot be %s: '%s'"
 
-class ErrorResponse(Response):
-	def __init__(self, ex):
-		self.ex = ex
+def find_case_insensitive(value, lst):
+	return next((x for x in lst if x.lower() == value.lower()), None)
 
-	def render(self, handler):
-		err = {'status': 'error', 'error': self.ex.message,}
-		handler.send_response(self.ex.status)
-		handler.send_header('Content-Type', 'application/json')
-		handler.end_headers()
-		handler.wfile.write(json.dumps(err, indent=2, sort_keys=True))
+def makelist(data):
+	if isinstance(data, list):
+		return data
+	elif data:
+		return [data]
+	else:
+		return []
 
-class JSONResponse(Response):
-	def __init__(self, data):
-		self.data = data
+class RouteHandler(object):
+	def __init__(self, app, bus, verbs, rules):
+		self.app = app
+		self.bus = bus
+		self.mapper = Mapper(bus)
+		self._verbs = makelist(verbs)
+		self._rules = rules
 
-	def render(self, handler):
-		handler.send_response(200)
-		handler.send_header('Content-Type', 'application/json')
-		handler.end_headers()
-		handler.wfile.write(json.dumps(self.data, indent=2, sort_keys=True))
+	def _setup(self, **kw):
+		request.route_data = {}
+		if request.method in self._verbs:
+			return self.setup(**kw)
+		else:
+			self.find(**kw)
+			raise HTTPError(405, "Method not allowed.",
+					Allow=','.join(self._verbs))
 
-class RequestHandler(object):
-	def __init__(self, req, path, data):
-		self.req = req
-		self.path = path
-		self.bus = req.server.bus
-		self.mapper = req.server.mapper
-		self.data = data
+	def __call__(self, **kw):
+		return getattr(self, 'do_' + request.method.lower())(**kw)
 
-	def do_command(self):
-		f = getattr(self, 'do_' + self.req.command)
-		return f()
+	def install(self):
+		self.app.route(self._rules, callback = self,
+				method = ['GET', 'PUT', 'PATCH', 'POST', 'DELETE'])
 
-	def do_GET(self):
-		raise RestException("Not Implemented", 501)
-
-	def do_PUT(self):
-		raise RestException("Not Implemented", 501)
-
-	def do_POST(self):
-		raise RestException("Not Implemented", 501)
-
-	def do_PATCH(self):
-		raise RestException("Not Implemented", 501)
-
-	def do_DELETE(self):
-		raise RestException("Not Implemented", 501)
-
-class MethodHandler(RequestHandler):
-	def __init__(self, req, path, data):
-		super(MethodHandler, self).__init__(req, path, data)
-		self.method = Path(self.req.path).rel(first = -1)
-
-	def find_method_in_interface(self, obj, interface):
+	@staticmethod
+	def try_mapper_call(f, callback = None, **kw):
 		try:
-			iface = dbus.Interface(obj, interface)
-			return getattr(iface, self.method)
-		except dbus.DBusException:
-			return None
+			return f(**kw)
+		except dbus.exceptions.DBusException, e:
+			if e.get_dbus_name() != OpenBMCMapper.MAPPER_NOT_FOUND:
+				raise
+			if callback is None:
+				def callback(e, **kw):
+					abort(404, str(e))
 
-	def find_method_on_bus(self, bus, interfaces):
-		obj = self.bus.get_object(bus, self.path)
-		for i in interfaces:
-			m = self.find_method_in_interface(obj, i)
-			if not m:
-				continue
-		return m
+			callback(e, **kw)
 
-	def find_method(self):
-		busses = self.mapper.get_object(
-				self.path)
-		for items in busses.iteritems():
-			m = self.find_method_on_bus(*items)
-			if not m:
-				continue
-
-		return m
-
-	def do_POST(self):
+	@staticmethod
+	def try_properties_interface(f, *a):
 		try:
-			method = self.find_method()
-		except:
-			raise RestException("Not Found", 404)
-		try:
-			d = { 'result': method(*self.data),
-					'status': 'OK'}
-		except Exception, e:
-			d = { 'error': str(e),
-					'status': 'error'}
-		return d
+			return f(*a)
+		except dbus.exceptions.DBusException, e:
+			if DBUS_UNKNOWN_INTERFACE in e.get_dbus_message():
+				# interface doesn't have any properties
+				return None
+			if DBUS_UNKNOWN_METHOD == e.get_dbus_name():
+				# properties interface not implemented at all
+				return None
+			raise
 
-class InstanceHandler(RequestHandler):
-	def __init__(self, req, path, data, busses):
-		super(InstanceHandler, self).__init__(req, path, data)
-		self.busses = busses
+class DirectoryHandler(RouteHandler):
+	verbs = 'GET'
+	rules = '<path:path>/'
 
-	def get_one_iface(self, properties_iface, iface):
-		try:
-			return properties_iface.GetAll(iface)
-		except:
-			# interface doesn't have any properties
-			return {}
+	def __init__(self, app, bus):
+		super(DirectoryHandler, self).__init__(
+				app, bus, self.verbs, self.rules)
 
-	def get_one_bus(self, bus, interfaces):
-		properties = {}
-		obj = self.bus.get_object(bus, self.path)
-		properties_iface = dbus.Interface(
-				obj, dbus_interface=dbus.PROPERTIES_IFACE)
-		for i in interfaces:
-			properties.update(self.get_one_iface(properties_iface, i))
+	def find(self, path = '/'):
+		return self.try_mapper_call(
+				self.mapper.get_subtree_paths,
+				path = path, depth = 1)
 
-		return properties
+	def setup(self, path = '/'):
+		request.route_data['map'] = self.find(path)
 
-	def do_GET(self):
-		properties = {}
-		for item in self.busses.iteritems():
-			properties.update(self.get_one_bus(*item))
+	def do_get(self, path = '/'):
+		return request.route_data['map']
 
-		return properties
+class ListNamesHandler(RouteHandler):
+	verbs = 'GET'
+	rules = ['/list', '<path:path>/list']
 
-	def try_set_one_interface(self, prop, value, properties_iface, interface):
-		try:
-			properties_iface.Set(interface, prop, value)
-			return True
-		except:
-			# property doesn't live on this interface/bus
-			return False
+	def __init__(self, app, bus):
+		super(ListNamesHandler, self).__init__(
+				app, bus, self.verbs, self.rules)
 
-	def try_set_one_bus(self, prop, value, bus, interfaces):
-		obj = self.bus.get_object(bus, self.path)
-		properties_iface = dbus.Interface(
-				obj, dbus_interface=dbus.PROPERTIES_IFACE)
+	def find(self, path = '/'):
+		return self.try_mapper_call(
+				self.mapper.get_subtree, path = path).keys()
 
-		for iface in interfaces:
-			if self.try_set_one_interface(prop, value,
-					properties_iface, iface):
-				return True
+	def setup(self, path = '/'):
+		request.route_data['map'] = self.find(path)
 
-		return False
+	def do_get(self, path = '/'):
+		return request.route_data['map']
 
-	def set_one_property(self, prop, value):
-		for item in self.busses.iteritems():
-			if not self.try_set_one_bus(prop, value, *item):
-				raise RestException("Not Found", 404)
+class ListHandler(RouteHandler):
+	verbs = 'GET'
+	rules = ['/enumerate', '<path:path>/enumerate']
 
-	def validate_json(self):
-		if type(self.data) != dict:
-			raise RestException("Bad Request", 400)
+	def __init__(self, app, bus):
+		super(ListHandler, self).__init__(
+				app, bus, self.verbs, self.rules)
 
-		obj = self.do_GET()
-		if len(self.data) != len(obj):
-			raise RestException("Bad Request", 400)
-		for x in obj.iterkeys():
-			if x not in self.data:
-				raise RestException("Bad Request", 400)
+	def find(self, path = '/'):
+		return self.try_mapper_call(
+				self.mapper.get_subtree, path = path)
 
-	def do_PUT(self):
-		try:
-			self.validate_json()
-			for p in self.data.iteritems():
-				self.set_one_property(*p)
+	def setup(self, path = '/'):
+		request.route_data['map'] = self.find(path)
 
-			d = { 'status': 'OK'}
-		except Exception, e:
-			d = { 'error': str(e),
-					'status': 'error'}
-		return d
-
-	def do_POST(self):
-		for p in self.data.iteritems():
-			self.set_one_property(*p)
-
-class AttrHandler(RequestHandler):
-	def __init__(self, req, path, data):
-		super(AttrHandler, self).__init__(req, path, data)
-		try:
-			self.inst = InstanceHandler(req, path, data,
-					self.mapper.get_object(path))
-		except KeyError:
-			raise RestException("Not Found", 404)
-		self.attr = Path(self.req.path).rel(first = -1)
-
-	def do_GET(self):
-		obj = self.inst.do_GET()
-		try:
-			return obj[self.attr]
-		except KeyError:
-			raise RestException("Not Found", 404)
-
-	def do_PUT(self):
-		self.inst.set_one_property(self.attr, self.data)
-
-class TypesHandler(RequestHandler):
-	def __init__(self, req, path, data):
-		super(TypesHandler, self).__init__(req, path, data)
-
-	def do_GET(self):
-		types = self.mapper.get_subtree_paths(self.path, 1)
-		if not types:
-			raise RestException("Not Found", 404)
-
-		return types
-
-class ListHandler(RequestHandler):
-	def __init__(self, req, path, data):
-		super(ListHandler, self).__init__(req, path, data)
-
-	def do_GET(self):
-		objs = self.mapper.get_subtree(self.path)
-		if not objs:
-			raise RestException("Not Found", 404)
-
-		return objs.keys()
-
-class EnumerateHandler(RequestHandler):
-	def __init__(self, req, path, data):
-		super(EnumerateHandler, self).__init__(req, path, data)
-
-	def get_enumerate(self, path, data):
-		busses = []
-		for s, i in data.iteritems():
-			if OpenBMCMapper.ENUMERATE_IFACE in i:
-				busses.append(s)
-		return busses
-
-	def call_enumerate(self, path, busses):
+	def do_get(self, path = '/'):
 		objs = {}
-		for b in busses:
-			obj = self.bus.get_object(b, path)
-			iface = dbus.Interface(obj, OpenBMCMapper.ENUMERATE_IFACE)
-			objs.update(iface.enumerate())
-		return objs
-
-	def do_GET(self):
-		objs = {}
-		mapper_data = self.mapper.get_subtree(self.path)
+		mapper_data = request.route_data['map']
 		tree = PathTree()
 		for x,y in mapper_data.iteritems():
 			tree[x] = y
@@ -276,95 +143,451 @@
 			# Check to see if the root path implements
 			# enumerate in addition to any sub tree
 			# objects.
-			root = self.mapper.get_object(self.path)
-			mapper_data[self.path] = root
+			root = self.try_mapper_call(self.mapper.get_object,
+					path = path)
+			mapper_data[path] = root
 		except:
 			pass
 
-		have_enumerate = [ (x[0], self.get_enumerate(*x)) for x in mapper_data.iteritems() \
-				if self.get_enumerate(*x) ]
+		have_enumerate = [ (x[0], self.enumerate_capable(*x)) \
+				for x in mapper_data.iteritems() \
+					if self.enumerate_capable(*x) ]
 
 		for x,y in have_enumerate:
 			objs.update(self.call_enumerate(x, y))
 			tmp = tree[x]
+			# remove the subtree
 			del tree[x]
+			# add the new leaf back since enumerate results don't
+			# include the object enumerate is being invoked on
 			tree[x] = tmp
 
+		# make dbus calls for any remaining objects
 		for x,y in tree.dataitems():
-			objs[x] = InstanceHandler(self.req, x, self.data, y).do_GET()
-
-		if not objs:
-			raise RestException("Not Found", 404)
+			objs[x] = self.app.instance_handler.do_get(x)
 
 		return objs
 
-class DBusRestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
-	def get_real_handler(self, data):
-		path = Path(self.path)
+	@staticmethod
+	def enumerate_capable(path, bus_data):
+		busses = []
+		for name, ifaces in bus_data.iteritems():
+			if OpenBMCMapper.ENUMERATE_IFACE in ifaces:
+				busses.append(name)
+		return busses
 
-		if self.path[-1] == '/':
-			return TypesHandler(self, path.fq(), data)
+	def call_enumerate(self, path, busses):
+		objs = {}
+		for b in busses:
+			obj = self.bus.get_object(b, path, introspect = False)
+			iface = dbus.Interface(obj, OpenBMCMapper.ENUMERATE_IFACE)
+			objs.update(iface.enumerate())
+		return objs
 
-		if path.parts[-1] == 'list':
-			return ListHandler(self, path.fq(last = -1), data)
+class MethodHandler(RouteHandler):
+	verbs = 'POST'
+	rules = '<path:path>/action/<method>'
+	request_type = list
 
-		if path.parts[-1] == 'enumerate':
-			return EnumerateHandler(self, path.fq(last = -1), data)
+	def __init__(self, app, bus):
+		super(MethodHandler, self).__init__(
+				app, bus, self.verbs, self.rules)
 
-		if path.depth() > 1 and path.parts[-2] == 'attr':
-			return AttrHandler(self, path.fq(last = -2), data)
+	def find(self, path, method):
+		busses = self.try_mapper_call(self.mapper.get_object,
+				path = path)
+		for items in busses.iteritems():
+			m = self.find_method_on_bus(path, method, *items)
+			if m:
+				return m
 
-		if path.depth() > 1 and path.parts[-2] == 'action':
-			return MethodHandler(self, path.fq(last = -2), data)
+		abort(404, _4034_msg %('method', 'found', method))
 
-		# have to do an objectmapper query at this point
-		mapper_entry = self.server.mapper.get_object(path.fq())
-		if mapper_entry:
-			return InstanceHandler(self, path.fq(), data,
-					mapper_entry)
+	def setup(self, path, method):
+		request.route_data['method'] = self.find(path, method)
 
-		raise RestException("Not Found", 404)
-
-	def do_command(self):
-		data = None
+	def do_post(self, path, method):
 		try:
-			if self.command in ['POST', 'PUT', 'PATCH']:
-       		 		length = int(self.headers.getheader(
-					'content-length'))
-			        data = json.loads(self.rfile.read(length))
+			if request.parameter_list:
+				return request.route_data['method'](*request.parameter_list)
+			else:
+				return request.route_data['method']()
 
-			resp = self.get_real_handler(data).do_command()
-			if not resp:
-				resp = {'status': 'OK' }
-			response = JSONResponse(resp)
-		except RestException, ex:
-			response = ErrorResponse(ex)
+		except dbus.exceptions.DBusException, e:
+			if e.get_dbus_name() == DBUS_INVALID_ARGS:
+				abort(400, str(e))
+			raise
 
-		response.render(self)
-		self.wfile.close()
+	@staticmethod
+	def find_method_in_interface(method, obj, interface, methods):
+		if methods is None:
+			return None
 
-	def do_GET(self):
-		return self.do_command()
+		method = find_case_insensitive(method, methods.keys())
+		if method is not None:
+			iface = dbus.Interface(obj, interface)
+			return iface.get_dbus_method(method)
 
-	def do_POST(self):
-		return self.do_command()
+	def find_method_on_bus(self, path, method, bus, interfaces):
+		obj = self.bus.get_object(bus, path, introspect = False)
+		iface = dbus.Interface(obj, dbus.INTROSPECTABLE_IFACE)
+		data = iface.Introspect()
+		parser = IntrospectionNodeParser(
+				ElementTree.fromstring(data),
+				intf_match = ListMatch(interfaces))
+		for x,y in parser.get_interfaces().iteritems():
+			m = self.find_method_in_interface(method, obj, x,
+					y.get('method'))
+			if m:
+				return m
 
-	def do_PATCH(self):
-		return self.do_command()
+class PropertyHandler(RouteHandler):
+	verbs = ['PUT', 'GET']
+	rules = '<path:path>/attr/<prop>'
 
-	def do_PUT(self):
-		return self.do_command()
+	def __init__(self, app, bus):
+		super(PropertyHandler, self).__init__(
+				app, bus, self.verbs, self.rules)
 
-	def do_DELETE(self):
-		return self.do_command()
+	def find(self, path, prop):
+		self.app.instance_handler.setup(path)
+		obj = self.app.instance_handler.do_get(path)
+		try:
+			obj[prop]
+		except KeyError, e:
+			if request.method == 'PUT':
+				abort(403, _4034_msg %('property', 'created', str(e)))
+			else:
+				abort(404, _4034_msg %('property', 'found', str(e)))
 
-class HTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
-	def __init__(self, bind, handler, bus):
-		BaseHTTPServer.HTTPServer.__init__(self, bind, handler)
+		return { path: obj }
+
+	def setup(self, path, prop):
+		request.route_data['obj'] = self.find(path, prop)
+
+	def do_get(self, path, prop):
+		return request.route_data['obj'][path][prop]
+
+	def do_put(self, path, prop, value = None):
+		if value is None:
+			value = request.parameter_list
+
+		prop, iface, properties_iface = self.get_host_interface(
+				path, prop, request.route_data['map'][path])
+		try:
+			properties_iface.Set(iface, prop, value)
+		except ValueError, e:
+			abort(400, str(e))
+		except dbus.exceptions.DBusException, e:
+			if e.get_dbus_name() == DBUS_INVALID_ARGS:
+				abort(403, str(e))
+			raise
+
+	def get_host_interface(self, path, prop, bus_info):
+		for bus, interfaces in bus_info.iteritems():
+			obj = self.bus.get_object(bus, path, introspect = True)
+			properties_iface = dbus.Interface(
+				obj, dbus_interface=dbus.PROPERTIES_IFACE)
+
+			info = self.get_host_interface_on_bus(
+					path, prop, properties_iface,
+					bus, interfaces)
+			if info is not None:
+				prop, iface = info
+				return prop, iface, properties_iface
+
+	def get_host_interface_on_bus(self, path, prop, iface, bus, interfaces):
+		for i in interfaces:
+			properties = self.try_properties_interface(iface.GetAll, i)
+			if properties is None:
+				continue
+			prop = find_case_insensitive(prop, properties.keys())
+			if prop is None:
+				continue
+			return prop, i
+
+class InstanceHandler(RouteHandler):
+	verbs = ['GET', 'PUT', 'DELETE']
+	rules = '<path:path>'
+	request_type = dict
+
+	def __init__(self, app, bus):
+		super(InstanceHandler, self).__init__(
+				app, bus, self.verbs, self.rules)
+
+	def find(self, path, callback = None):
+		return { path: self.try_mapper_call(
+			self.mapper.get_object,
+			callback,
+			path = path) }
+
+	def setup(self, path):
+		callback = None
+		if request.method == 'PUT':
+			def callback(e, **kw):
+				abort(403, _4034_msg %('resource',
+					'created', path))
+
+		if request.route_data.get('map') is None:
+			request.route_data['map'] = self.find(path, callback)
+
+	def do_get(self, path):
+		properties = {}
+		for item in request.route_data['map'][path].iteritems():
+			properties.update(self.get_properties_on_bus(
+				path, *item))
+
+		return properties
+
+	@staticmethod
+	def get_properties_on_iface(properties_iface, iface):
+		properties = InstanceHandler.try_properties_interface(
+				properties_iface.GetAll, iface)
+		if properties is None:
+			return {}
+		return properties
+
+	def get_properties_on_bus(self, path, bus, interfaces):
+		properties = {}
+		obj = self.bus.get_object(bus, path, introspect = False)
+		properties_iface = dbus.Interface(
+				obj, dbus_interface=dbus.PROPERTIES_IFACE)
+		for i in interfaces:
+			properties.update(self.get_properties_on_iface(
+				properties_iface, i))
+
+		return properties
+
+	def do_put(self, path):
+		# make sure all properties exist in the request
+		obj = set(self.do_get(path).keys())
+		req = set(request.parameter_list.keys())
+
+		diff = list(obj.difference(req))
+		if diff:
+			abort(403, _4034_msg %('resource', 'removed',
+				'%s/attr/%s' %(path, diff[0])))
+
+		diff = list(req.difference(obj))
+		if diff:
+			abort(403, _4034_msg %('resource', 'created',
+				'%s/attr/%s' %(path, diff[0])))
+
+		for p,v in request.parameter_list.iteritems():
+			self.app.property_handler.do_put(
+					path, p, v)
+
+	def do_delete(self, path):
+		for bus_info in request.route_data['map'][path].iteritems():
+			if self.bus_missing_delete(path, *bus_info):
+				abort(403, _4034_msg %('resource', 'removed',
+					path))
+
+		for bus in request.route_data['map'][path].iterkeys():
+			self.delete_on_bus(path, bus)
+
+	def bus_missing_delete(self, path, bus, interfaces):
+		return DELETE_IFACE not in interfaces
+
+	def delete_on_bus(self, path, bus):
+		obj = self.bus.get_object(bus, path, introspect = False)
+		delete_iface = dbus.Interface(
+				obj, dbus_interface = DELETE_IFACE)
+		delete_iface.Delete()
+
+class JsonApiRequestPlugin(object):
+	''' Ensures request content satisfies the OpenBMC json api format. '''
+	name = 'json_api_request'
+	api = 2
+
+	error_str = "Expecting request format { 'data': <value> }, got '%s'"
+	type_error_str = "Unsupported Content-Type: '%s'"
+	json_type = "application/json"
+	request_methods = ['PUT', 'POST', 'PATCH']
+
+	@staticmethod
+	def content_expected():
+		return request.method in JsonApiRequestPlugin.request_methods
+
+	def validate_request(self):
+		if request.content_length > 0 and \
+				request.content_type != self.json_type:
+			abort(415, self.type_error_str %(request.content_type))
+
+		try:
+			request.parameter_list = request.json.get('data')
+		except ValueError, e:
+			abort(400, str(e))
+		except (AttributeError, KeyError, TypeError):
+			abort(400, self.error_str %(request.json))
+
+	def apply(self, callback, route):
+		verbs = getattr(route.get_undecorated_callback(),
+				'_verbs', None)
+		if verbs is None:
+			return callback
+
+		if not set(self.request_methods).intersection(verbs):
+			return callback
+
+		def wrap(*a, **kw):
+			if self.content_expected():
+				self.validate_request()
+			return callback(*a, **kw)
+
+		return wrap
+
+class JsonApiRequestTypePlugin(object):
+	''' Ensures request content type satisfies the OpenBMC json api format. '''
+	name = 'json_api_method_request'
+	api = 2
+
+	error_str = "Expecting request format { 'data': %s }, got '%s'"
+
+	def apply(self, callback, route):
+		request_type = getattr(route.get_undecorated_callback(),
+				'request_type', None)
+		if request_type is None:
+			return callback
+
+		def validate_request():
+			if not isinstance(request.parameter_list, request_type):
+				abort(400, self.error_str %(str(request_type), request.json))
+
+		def wrap(*a, **kw):
+			if JsonApiRequestPlugin.content_expected():
+				validate_request()
+			return callback(*a, **kw)
+
+		return wrap
+
+class JsonApiResponsePlugin(object):
+	''' Emits normal responses in the OpenBMC json api format. '''
+	name = 'json_api_response'
+	api = 2
+
+	def apply(self, callback, route):
+		def wrap(*a, **kw):
+			resp = { 'data': callback(*a, **kw) }
+			resp['status'] = 'ok'
+			resp['message'] = response.status_line
+			return resp
+		return wrap
+
+class JsonApiErrorsPlugin(object):
+	''' Emits error responses in the OpenBMC json api format. '''
+	name = 'json_api_errors'
+	api = 2
+
+	def __init__(self, **kw):
+		self.app = None
+		self.function_type = None
+		self.original = None
+		self.json_opts = { x:y for x,y in kw.iteritems() \
+			if x in ['indent','sort_keys'] }
+
+	def setup(self, app):
+		self.app = app
+		self.function_type = type(app.default_error_handler)
+		self.original = app.default_error_handler
+		self.app.default_error_handler = self.function_type(
+			self.json_errors, app, Bottle)
+
+	def apply(self, callback, route):
+		return callback
+
+	def close(self):
+		self.app.default_error_handler = self.function_type(
+				self.original, self.app, Bottle)
+
+	def json_errors(self, res, error):
+		response_object = {'status': 'error', 'data': {} }
+		response_object['message'] = error.status_line
+		response_object['data']['description'] = str(error.body)
+		if error.status_code == 500:
+			response_object['data']['exception'] = repr(error.exception)
+			response_object['data']['traceback'] = error.traceback.splitlines()
+
+		json_response = json.dumps(response_object, **self.json_opts)
+		res.content_type = 'application/json'
+		return json_response
+
+class RestApp(Bottle):
+	def __init__(self, bus):
+		super(RestApp, self).__init__(autojson = False)
 		self.bus = bus
-		self.mapper = Mapper(self.bus)
+		self.mapper = Mapper(bus)
+
+		self.install_hooks()
+		self.install_plugins()
+		self.create_handlers()
+		self.install_handlers()
+
+	def install_plugins(self):
+		# install json api plugins
+		json_kw = {'indent': 2, 'sort_keys': True}
+		self.install(JSONPlugin(**json_kw))
+		self.install(JsonApiErrorsPlugin(**json_kw))
+		self.install(JsonApiResponsePlugin())
+		self.install(JsonApiRequestPlugin())
+		self.install(JsonApiRequestTypePlugin())
+
+	def install_hooks(self):
+		self.real_router_match = self.router.match
+		self.router.match = self.custom_router_match
+		self.add_hook('before_request', self.strip_extra_slashes)
+
+	def create_handlers(self):
+		# create route handlers
+		self.directory_handler = DirectoryHandler(self, self.bus)
+		self.list_names_handler = ListNamesHandler(self, self.bus)
+		self.list_handler = ListHandler(self, self.bus)
+		self.method_handler = MethodHandler(self, self.bus)
+		self.property_handler = PropertyHandler(self, self.bus)
+		self.instance_handler = InstanceHandler(self, self.bus)
+
+	def install_handlers(self):
+		self.directory_handler.install()
+		self.list_names_handler.install()
+		self.list_handler.install()
+		self.method_handler.install()
+		self.property_handler.install()
+		# this has to come last, since it matches everything
+		self.instance_handler.install()
+
+	def custom_router_match(self, environ):
+		''' The built-in Bottle algorithm for figuring out if a 404 or 405 is
+                    needed doesn't work for us since the instance rules match everything.
+                    This monkey-patch lets the route handler figure out which response is
+                    needed.  This could be accomplished with a hook but that would require
+		    calling the router match function twice.
+		'''
+		route, args = self.real_router_match(environ)
+		if isinstance(route.callback, RouteHandler):
+			route.callback._setup(**args)
+
+		return route, args
+
+	@staticmethod
+	def strip_extra_slashes():
+		path = request.environ['PATH_INFO']
+		trailing = ("","/")[path[-1] == '/']
+		parts = filter(bool, path.split('/'))
+		request.environ['PATH_INFO'] = '/' + '/'.join(parts) + trailing
 
 if __name__ == '__main__':
+	log = logging.getLogger('Rocket.Errors')
+	log.setLevel(logging.INFO)
+	log.addHandler(logging.StreamHandler(sys.stdout))
+
 	bus = dbus.SystemBus()
-	server = HTTPServer(('', 80), DBusRestHandler, bus)
-	server.serve_forever()
+	app = RestApp(bus)
+	default_cert = os.path.join(sys.prefix, 'share',
+			os.path.basename(__file__), 'cert.pem')
+
+	server = Rocket(('0.0.0.0',
+			443,
+			default_cert,
+			default_cert),
+		'wsgi', {'wsgi_app': app})
+	server.start()
