webapp: use content detection for return
Rather than having end-points with ".json", check the accept-header and return the correct thing based on that. Change-Id: Ia0e4cb90cdaa113bb1bf7b4636bc10293811f0f6
This commit is contained in:
parent
89790013f3
commit
2dcd79b987
|
@ -232,26 +232,18 @@ launchers, all will provide the same information.
|
|||
The status of uploaded images
|
||||
|
||||
:query fields: comma-separated list of fields to display
|
||||
:resheader Content-Type: text/plain
|
||||
|
||||
.. http:get:: /image-list.json
|
||||
|
||||
The status of uploaded images
|
||||
|
||||
:resheader Content-Type: application/json
|
||||
:reqheader Accept: ``application/json`` or ``text/*``
|
||||
:resheader Content-Type: ``application/json`` or ``text/plain``
|
||||
depending on the :http:header:`Accept` header
|
||||
|
||||
.. http:get:: /dib-image-list
|
||||
|
||||
The status of images built by ``diskimage-builder``
|
||||
|
||||
:query fields: comma-separated list of fields to display
|
||||
:resheader Content-Type: text/plain
|
||||
|
||||
.. http:get:: /dib-image-list.json
|
||||
|
||||
The status of images built by ``diskimage-builder``
|
||||
|
||||
:resheader Content-Type: application/json
|
||||
:reqheader Accept: ``application/json`` or ``text/*``
|
||||
:resheader Content-Type: ``application/json`` or ``text/plain``
|
||||
depending on the :http:header:`Accept` header
|
||||
|
||||
.. http:get:: /node-list
|
||||
|
||||
|
@ -259,24 +251,15 @@ launchers, all will provide the same information.
|
|||
|
||||
:query node_id: restrict to a specific node
|
||||
:query fields: comma-separated list of fields to display
|
||||
:resheader Content-Type: text/plain
|
||||
|
||||
.. http:get:: /node-list.json
|
||||
|
||||
The status of currently active nodes
|
||||
|
||||
:query node_id: restrict to a specific node
|
||||
:resheader Content-Type: application/json
|
||||
:reqheader Accept: ``application/json`` or ``text/*``
|
||||
:resheader Content-Type: ``application/json`` or ``text/plain``
|
||||
depending on the :http:header:`Accept` header
|
||||
|
||||
.. http:get:: /request-list
|
||||
|
||||
Outstanding requests
|
||||
|
||||
:query fields: comma-separated list of fields to display
|
||||
:resheader Content-Type: text/plain
|
||||
|
||||
.. http:get:: /request-list.json
|
||||
|
||||
Outstanding requests
|
||||
|
||||
:resheader Content-Type: application/json
|
||||
:reqheader Accept: ``application/json`` or ``text/*``
|
||||
:resheader Content-Type: ``application/json`` or ``text/plain``
|
||||
depending on the :http:header:`Accept` header
|
||||
|
|
|
@ -39,6 +39,9 @@ class TestWebApp(tests.DBTestCase):
|
|||
|
||||
req = request.Request(
|
||||
"http://localhost:%s/image-list" % port)
|
||||
# NOTE(ianw): we want pretty printed text/plain back, but
|
||||
# simulating a normal web-browser request.
|
||||
req.add_header('Accept', 'text/html')
|
||||
f = request.urlopen(req)
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'text/plain; charset=UTF-8')
|
||||
|
@ -59,6 +62,7 @@ class TestWebApp(tests.DBTestCase):
|
|||
|
||||
req = request.Request(
|
||||
"http://localhost:%s/image-list?fields=id,image,state" % port)
|
||||
req.add_header('Accept', 'text/html')
|
||||
f = request.urlopen(req)
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'text/plain; charset=UTF-8')
|
||||
|
@ -79,7 +83,8 @@ class TestWebApp(tests.DBTestCase):
|
|||
self.waitForNodes('fake-label')
|
||||
|
||||
req = request.Request(
|
||||
"http://localhost:%s/image-list.json" % port)
|
||||
"http://localhost:%s/image-list" % port)
|
||||
req.add_header('Accept', 'application/json')
|
||||
f = request.urlopen(req)
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'application/json')
|
||||
|
@ -103,7 +108,8 @@ class TestWebApp(tests.DBTestCase):
|
|||
self.waitForNodes('fake-label')
|
||||
|
||||
req = request.Request(
|
||||
"http://localhost:%s/dib-image-list.json" % port)
|
||||
"http://localhost:%s/dib-image-list" % port)
|
||||
req.add_header('Accept', 'application/json')
|
||||
f = request.urlopen(req)
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'application/json')
|
||||
|
@ -128,7 +134,8 @@ class TestWebApp(tests.DBTestCase):
|
|||
self.waitForNodes('fake-label')
|
||||
|
||||
req = request.Request(
|
||||
"http://localhost:%s/node-list.json" % port)
|
||||
"http://localhost:%s/node-list" % port)
|
||||
req.add_header('Accept', 'application/json')
|
||||
f = request.urlopen(req)
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'application/json')
|
||||
|
@ -143,9 +150,10 @@ class TestWebApp(tests.DBTestCase):
|
|||
'state': 'ready'}, objs[0])
|
||||
# specify valid node_id
|
||||
req = request.Request(
|
||||
"http://localhost:%s/node-list.json?node_id=%s" % (port,
|
||||
'0000000000'))
|
||||
"http://localhost:%s/node-list?node_id=%s" % (port,
|
||||
'0000000000'))
|
||||
f = request.urlopen(req)
|
||||
req.add_header('Accept', 'application/json')
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'application/json')
|
||||
data = f.read()
|
||||
|
@ -159,8 +167,9 @@ class TestWebApp(tests.DBTestCase):
|
|||
'state': 'ready'}, objs[0])
|
||||
# node_id not found
|
||||
req = request.Request(
|
||||
"http://localhost:%s/node-list.json?node_id=%s" % (port,
|
||||
'999999'))
|
||||
"http://localhost:%s/node-list?node_id=%s" % (port,
|
||||
'999999'))
|
||||
req.add_header('Accept', 'application/json')
|
||||
f = request.urlopen(req)
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'application/json')
|
||||
|
@ -186,7 +195,8 @@ class TestWebApp(tests.DBTestCase):
|
|||
self.zk.storeNodeRequest(req)
|
||||
|
||||
http_req = request.Request(
|
||||
"http://localhost:%s/request-list.json" % port)
|
||||
"http://localhost:%s/request-list" % port)
|
||||
http_req.add_header('Accept', 'application/json')
|
||||
f = request.urlopen(http_req)
|
||||
self.assertEqual(f.info().get('Content-Type'),
|
||||
'application/json')
|
||||
|
|
|
@ -74,23 +74,20 @@ class WebApp(threading.Thread):
|
|||
def stop(self):
|
||||
self.server.server_close()
|
||||
|
||||
def get_cache(self, path, params):
|
||||
def get_cache(self, path, params, request_type):
|
||||
# TODO quick and dirty way to take query parameters
|
||||
# into account when caching data
|
||||
if params:
|
||||
index = path + json.dumps(params.dict_of_lists(), sort_keys=True)
|
||||
index = "%s.%s.%s" % (path,
|
||||
json.dumps(params.dict_of_lists(),
|
||||
sort_keys=True),
|
||||
request_type)
|
||||
else:
|
||||
index = path
|
||||
index = "%s.%s" % (path, request_type)
|
||||
result = self.cache.get(index)
|
||||
if result:
|
||||
return result
|
||||
|
||||
if path.endswith('.json'):
|
||||
out_fmt = 'json'
|
||||
path = path[:-5]
|
||||
else:
|
||||
out_fmt = 'pretty'
|
||||
|
||||
zk = self.nodepool.getZK()
|
||||
|
||||
if path == '/image-list':
|
||||
|
@ -109,16 +106,32 @@ class WebApp(threading.Thread):
|
|||
if params.get('fields'):
|
||||
fields = params.get('fields').split(',')
|
||||
|
||||
output = status.output(results, out_fmt, fields)
|
||||
output = status.output(results, request_type, fields)
|
||||
return self.cache.put(index, output)
|
||||
|
||||
def _request_wants(self, request):
|
||||
'''Find request content-type
|
||||
|
||||
:param request: The incoming request
|
||||
:return str: Best guess of either 'pretty' or 'json'
|
||||
'''
|
||||
best = request.accept.best_match(
|
||||
['application/json', 'text/plain'])
|
||||
if best == 'application/json':
|
||||
return 'json'
|
||||
else:
|
||||
return 'pretty'
|
||||
|
||||
def app(self, request):
|
||||
result = self.get_cache(request.path, request.params)
|
||||
|
||||
request_type = self._request_wants(request)
|
||||
result = self.get_cache(request.path, request.params,
|
||||
request_type)
|
||||
if result is None:
|
||||
raise webob.exc.HTTPNotFound()
|
||||
last_modified, output = result
|
||||
|
||||
if request.path.endswith('.json'):
|
||||
if request_type == 'json':
|
||||
content_type = 'application/json'
|
||||
else:
|
||||
content_type = 'text/plain'
|
||||
|
|
Loading…
Reference in New Issue