Remove project ID from the URI

This patch modifies the WSGI routes to pull the project ID from
the headers (X-Project-ID) rather than from the URI. Once this
is merged, the implementation will be fully compliant with
the V1 API spec.

Note that clients will be required to include X-Project-ID in
requests since there will not always be a 1:1 relationship
between auth token and project. To support this scenario, the
service provider will also need to perform policy enforcement
in a proxy or in middleware.

Implements: blueprint v1-api
Change-Id: Ib0b1218a98521b903643f3446d2192cddde135a7
This commit is contained in:
kgriffs 2013-06-21 17:44:15 -04:00 committed by Gerrit Code Review
parent 20ddcb8e4c
commit 4208286d53
9 changed files with 311 additions and 409 deletions

View File

@ -123,7 +123,7 @@ def to_oid(obj):
try: try:
return objectid.ObjectId(obj) return objectid.ObjectId(obj)
except (TypeError, berrors.InvalidId): except (TypeError, berrors.InvalidId):
msg = _('Wrong id %s') % obj msg = _('Invalid oid: %s') % obj
raise storage_exceptions.MalformedID(msg) raise storage_exceptions.MalformedID(msg)

View File

@ -36,6 +36,10 @@ class Queue(base.QueueBase):
def list(self, project, marker=None, def list(self, project, marker=None,
limit=10, detailed=False): limit=10, detailed=False):
if project is None:
project = ''
sql = ((''' sql = (('''
select name from Queues''' if not detailed select name from Queues''' if not detailed
else ''' else '''
@ -68,6 +72,9 @@ class Queue(base.QueueBase):
yield marker_name['next'] yield marker_name['next']
def get(self, name, project): def get(self, name, project):
if project is None:
project = ''
try: try:
return self.driver.get(''' return self.driver.get('''
select metadata from Queues select metadata from Queues
@ -77,6 +84,9 @@ class Queue(base.QueueBase):
raise exceptions.QueueDoesNotExist(name, project) raise exceptions.QueueDoesNotExist(name, project)
def upsert(self, name, metadata, project): def upsert(self, name, metadata, project):
if project is None:
project = ''
with self.driver('immediate'): with self.driver('immediate'):
previous_record = self.driver.run(''' previous_record = self.driver.run('''
select id from Queues select id from Queues
@ -91,11 +101,17 @@ class Queue(base.QueueBase):
return previous_record is None return previous_record is None
def delete(self, name, project): def delete(self, name, project):
if project is None:
project = ''
self.driver.run(''' self.driver.run('''
delete from Queues delete from Queues
where project = ? and name = ?''', project, name) where project = ? and name = ?''', project, name)
def stats(self, name, project): def stats(self, name, project):
if project is None:
project = ''
with self.driver('deferred'): with self.driver('deferred'):
qid = _get_qid(self.driver, name, project) qid = _get_qid(self.driver, name, project)
claimed, free = self.driver.get(''' claimed, free = self.driver.get('''
@ -144,6 +160,9 @@ class Message(base.MessageBase):
''') ''')
def get(self, queue, message_ids, project): def get(self, queue, message_ids, project):
if project is None:
project = ''
if not isinstance(message_ids, list): if not isinstance(message_ids, list):
message_ids = [message_ids] message_ids = [message_ids]
@ -170,6 +189,9 @@ class Message(base.MessageBase):
def list(self, queue, project, marker=None, def list(self, queue, project, marker=None,
limit=10, echo=False, client_uuid=None): limit=10, echo=False, client_uuid=None):
if project is None:
project = ''
with self.driver('deferred'): with self.driver('deferred'):
sql = ''' sql = '''
select id, content, ttl, julianday() * 86400.0 - created select id, content, ttl, julianday() * 86400.0 - created
@ -209,6 +231,9 @@ class Message(base.MessageBase):
yield _marker_encode(marker_id['next']) yield _marker_encode(marker_id['next'])
def post(self, queue, messages, client_uuid, project): def post(self, queue, messages, client_uuid, project):
if project is None:
project = ''
with self.driver('immediate'): with self.driver('immediate'):
qid = _get_qid(self.driver, queue, project) qid = _get_qid(self.driver, queue, project)
@ -239,6 +264,9 @@ class Message(base.MessageBase):
return map(_msgid_encode, range(unused, my['newid'])) return map(_msgid_encode, range(unused, my['newid']))
def delete(self, queue, message_id, project, claim=None): def delete(self, queue, message_id, project, claim=None):
if project is None:
project = ''
id = _msgid_decode(message_id) id = _msgid_decode(message_id)
if not claim: if not claim:
@ -306,6 +334,9 @@ class Claim(base.ClaimBase):
''') ''')
def get(self, queue, claim_id, project): def get(self, queue, claim_id, project):
if project is None:
project = ''
with self.driver('deferred'): with self.driver('deferred'):
try: try:
id, ttl, age = self.driver.get(''' id, ttl, age = self.driver.get('''
@ -329,10 +360,13 @@ class Claim(base.ClaimBase):
raise exceptions.ClaimDoesNotExist(claim_id, queue, project) raise exceptions.ClaimDoesNotExist(claim_id, queue, project)
def create(self, queue, metadata, project, limit=10): def create(self, queue, metadata, project, limit=10):
if project is None:
project = ''
with self.driver('immediate'): with self.driver('immediate'):
qid = _get_qid(self.driver, queue, project) qid = _get_qid(self.driver, queue, project)
# cleanup all expired claims in this queue # Clean up all expired claims in this queue
self.driver.run(''' self.driver.run('''
delete from Claims delete from Claims
@ -377,6 +411,9 @@ class Claim(base.ClaimBase):
} }
def update(self, queue, claim_id, metadata, project): def update(self, queue, claim_id, metadata, project):
if project is None:
project = ''
try: try:
id = _cid_decode(claim_id) id = _cid_decode(claim_id)
except exceptions.MalformedID: except exceptions.MalformedID:
@ -414,6 +451,9 @@ class Claim(base.ClaimBase):
''', ttl, ttl, cid) ''', ttl, ttl, cid)
def delete(self, queue, claim_id, project): def delete(self, queue, claim_id, project):
if project is None:
project = ''
try: try:
cid = _cid_decode(claim_id) cid = _cid_decode(claim_id)
except exceptions.MalformedID: except exceptions.MalformedID:

View File

@ -37,6 +37,47 @@ class TestBase(util.TestBase):
self.app = boot.transport.app self.app = boot.transport.app
self.srmock = testing.StartResponseMock() self.srmock = testing.StartResponseMock()
def simulate_request(self, path, project_id=None, **kwargs):
"""Simulate a request.
Simulates a WSGI request to the API for testing.
:param path: Request path for the desired resource
:param project_id: Project ID to use for the X-Project-ID header,
or None to not set the header
:param kwargs: Same as falcon.testing.create_environ()
:returns: standard WSGI iterable response
"""
if project_id is not None:
headers = dict(kwargs['headers']) if 'headers' in kwargs else {}
headers['X-Project-ID'] = project_id
kwargs['headers'] = headers
return self.app(testing.create_environ(path=path, **kwargs),
self.srmock)
def simulate_get(self, *args, **kwargs):
kwargs['method'] = 'GET'
return self.simulate_request(*args, **kwargs)
def simulate_put(self, *args, **kwargs):
kwargs['method'] = 'PUT'
return self.simulate_request(*args, **kwargs)
def simulate_post(self, *args, **kwargs):
kwargs['method'] = 'POST'
return self.simulate_request(*args, **kwargs)
def simulate_delete(self, *args, **kwargs):
kwargs['method'] = 'DELETE'
return self.simulate_request(*args, **kwargs)
def simulate_patch(self, *args, **kwargs):
kwargs['method'] = 'PATCH'
return self.simulate_request(*args, **kwargs)
class TestBaseFaulty(TestBase): class TestBaseFaulty(TestBase):

View File

@ -19,7 +19,6 @@ import os
import pymongo import pymongo
import falcon import falcon
from falcon import testing
from marconi.common import config from marconi.common import config
from marconi.tests.transport.wsgi import base from marconi.tests.transport.wsgi import base
@ -30,173 +29,118 @@ class ClaimsBaseTest(base.TestBase):
def setUp(self): def setUp(self):
super(ClaimsBaseTest, self).setUp() super(ClaimsBaseTest, self).setUp()
self.project_id = '480924'
self.queue_path = '/v1/queues/fizbit'
self.claims_path = self.queue_path + '/claims'
doc = '{"_ttl": 60 }' doc = '{"_ttl": 60 }'
env = testing.create_environ('/v1/480924/queues/fizbit',
method='PUT', body=doc) self.simulate_put(self.queue_path, self.project_id, body=doc)
self.app(env, self.srmock) self.assertEquals(self.srmock.status, falcon.HTTP_201)
doc = json.dumps([{'body': 239, 'ttl': 30}] * 10) doc = json.dumps([{'body': 239, 'ttl': 30}] * 10)
self.simulate_post(self.queue_path + '/messages', self.project_id,
body=doc, headers={'Client-ID': '30387f00'})
self.assertEquals(self.srmock.status, falcon.HTTP_201)
env = testing.create_environ('/v1/480924/queues/fizbit/messages', def tearDown(self):
method='POST', self.simulate_delete(self.queue_path, self.project_id)
body=doc,
headers={'Client-ID': '30387f00'}) super(ClaimsBaseTest, self).tearDown()
self.app(env, self.srmock)
def test_bad_claim(self): def test_bad_claim(self):
env = testing.create_environ('/v1/480924/queues/fizbit/claims', for doc in (None, '[', '[]', '{}', '.', '"fail"'):
method='POST') self.simulate_post(self.claims_path, self.project_id,
body=doc)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ('/v1/480924/queues/fizbit/claims',
method='POST', body='[')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ('/v1/480924/queues/fizbit/claims',
method='POST', body='{}')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def test_bad_patch(self): def test_bad_patch(self):
env = testing.create_environ('/v1/480924/queues/fizbit/claims', self.simulate_post(self.claims_path, self.project_id,
method='POST',
body='{"ttl": 10}') body='{"ttl": 10}')
self.app(env, self.srmock) href = self.srmock.headers_dict['Location']
target = self.srmock.headers_dict['Location']
env = testing.create_environ(target, method='PATCH') for doc in (None, '[', '"crunchy"'):
self.simulate_patch(href, self.project_id, body=doc)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ(target, method='PATCH', body='{')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def test_lifecycle(self): def test_lifecycle(self):
doc = '{"ttl": 10}' doc = '{"ttl": 10}'
# claim some messages # First, claim some messages
body = self.simulate_post(self.claims_path, self.project_id, body=doc)
env = testing.create_environ('/v1/480924/queues/fizbit/claims',
method='POST',
body=doc)
body = self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
st = json.loads(body[0]) claim = json.loads(body[0])
target = self.srmock.headers_dict['Location'] claim_href = self.srmock.headers_dict['Location']
[msg_target, params] = st[0]['href'].split('?') message_href, params = claim[0]['href'].split('?')
# no more messages to claim # No more messages to claim
self.simulate_post(self.claims_path, self.project_id, body=doc,
env = testing.create_environ('/v1/480924/queues/fizbit/claims',
method='POST',
body=doc,
query_string='limit=3') query_string='limit=3')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
# check its metadata # Check the claim's metadata
body = self.simulate_get(claim_href, self.project_id)
env = testing.create_environ(target, method='GET') claim = json.loads(body[0])
body = self.app(env, self.srmock)
st = json.loads(body[0])
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
self.assertEquals(self.srmock.headers_dict['Content-Location'], self.assertEquals(self.srmock.headers_dict['Content-Location'],
env['PATH_INFO']) claim_href)
self.assertEquals(claim['ttl'], 10)
self.assertEquals(st['ttl'], 10) # Delete the message and its associated claim
self.simulate_delete(message_href, self.project_id,
# delete a message with its associated claim query_string=params)
env = testing.create_environ(msg_target, query_string=params,
method='DELETE')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
env = testing.create_environ(msg_target, query_string=params) # Try to get it from the wrong project
self.simulate_get(message_href, 'bogus_project', query_string=params)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
# update the claim # Get the message
self.simulate_get(message_href, self.project_id, query_string=params)
self.assertEquals(self.srmock.status, falcon.HTTP_404)
env = testing.create_environ(target, # Update the claim
body='{"ttl": 60}', self.simulate_patch(claim_href, self.project_id, body='{"ttl": 60}')
method='PATCH')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
# get the claimed messages again # Get the claimed messages (again)
body = self.simulate_get(claim_href, self.project_id)
claim = json.loads(body[0])
message_href, params = claim['messages'][0]['href'].split('?')
env = testing.create_environ(target, method='GET') self.assertEquals(claim['ttl'], 60)
body = self.app(env, self.srmock) # Delete the claim
st = json.loads(body[0]) self.simulate_delete(claim['href'], 'bad_id')
[msg_target, params] = st['messages'][0]['href'].split('?')
self.assertEquals(st['ttl'], 60)
# delete the claim
env = testing.create_environ(st['href'], method='DELETE')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
# can not delete a message with a non-existing claim self.simulate_delete(claim['href'], self.project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_204)
env = testing.create_environ(msg_target, query_string=params, # Try to delete a message with an invalid claim ID
method='DELETE') self.simulate_delete(message_href, self.project_id,
query_string=params)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_403) self.assertEquals(self.srmock.status, falcon.HTTP_403)
env = testing.create_environ(msg_target, query_string=params) # Make sure it wasn't deleted!
self.simulate_get(message_href, self.project_id, query_string=params)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
# get & update a non existing claim # Try to get a claim that doesn't exist
self.simulate_get(claim['href'])
env = testing.create_environ(st['href'], method='GET')
body = self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
env = testing.create_environ(st['href'], method='PATCH', body=doc) # Try to update a claim that doesn't exist
self.simulate_patch(claim['href'], body=doc)
body = self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
def test_nonexistent(self): def test_nonexistent(self):
doc = '{"ttl": 10}' self.simulate_post('/v1/queues/nonexistent/claims', self.project_id,
env = testing.create_environ('/v1/480924/queues/nonexistent/claims', body='{"ttl": 10}')
method='POST', body=doc)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
def tearDown(self):
env = testing.create_environ('/v1/480924/queues/fizbit',
method='DELETE')
self.app(env, self.srmock)
super(ClaimsBaseTest, self).tearDown()
class ClaimsMongoDBTests(ClaimsBaseTest): class ClaimsMongoDBTests(ClaimsBaseTest):
@ -225,32 +169,18 @@ class ClaimsFaultyDriverTests(base.TestBaseFaulty):
config_filename = 'wsgi_faulty.conf' config_filename = 'wsgi_faulty.conf'
def test_simple(self): def test_simple(self):
project_id = '480924'
claims_path = '/v1/queues/fizbit/claims'
doc = '{"ttl": 100}' doc = '{"ttl": 100}'
env = testing.create_environ('/v1/480924/queues/fizbit/claims',
method='POST',
body=doc)
self.app(env, self.srmock) self.simulate_post(claims_path, project_id, body=doc)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues/fizbit/claims' self.simulate_get(claims_path + '/nichts', project_id)
'/nonexistent',
method='GET')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues/fizbit/claims' self.simulate_patch(claims_path, project_id, body=doc)
'/nonexistent', self.assertEquals(self.srmock.status, falcon.HTTP_405)
method='PATCH',
body=doc)
self.app(env, self.srmock) self.simulate_delete(claims_path + '/foo', project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues/fizbit/claims'
'/nonexistent',
method='DELETE')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)

View File

@ -17,7 +17,6 @@ import json
import os import os
import falcon import falcon
from falcon import testing
from marconi.tests.transport.wsgi import base from marconi.tests.transport.wsgi import base
@ -27,20 +26,18 @@ class MessagesBaseTest(base.TestBase):
def setUp(self): def setUp(self):
super(MessagesBaseTest, self).setUp() super(MessagesBaseTest, self).setUp()
self.project_id = '7e55e1a7e'
self.queue_path = '/v1/queues/fizbit'
doc = '{"_ttl": 60}' doc = '{"_ttl": 60}'
env = testing.create_environ('/v1/480924/queues/fizbit', self.simulate_put(self.queue_path, self.project_id, body=doc)
method='PUT', body=doc)
self.app(env, self.srmock)
self.headers = { self.headers = {
'Client-ID': '30387f00', 'Client-ID': '30387f00',
} }
def tearDown(self): def tearDown(self):
env = testing.create_environ('/v1/480924/queues/fizbit', self.simulate_delete(self.queue_path, self.project_id)
method='DELETE')
self.app(env, self.srmock)
super(MessagesBaseTest, self).tearDown() super(MessagesBaseTest, self).tearDown()
def test_post(self): def test_post(self):
@ -52,28 +49,22 @@ class MessagesBaseTest(base.TestBase):
] ]
""" """
queue_path = '/v1/480924/queues/fizbit' messages_path = self.queue_path + '/messages'
messages_path = queue_path + '/messages' result = self.simulate_post(messages_path, self.project_id,
env = testing.create_environ(messages_path, body=doc, headers=self.headers)
method='POST',
body=doc,
headers=self.headers)
body = self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_201) self.assertEquals(self.srmock.status, falcon.HTTP_201)
result_doc = json.loads(result[0])
msg_ids = self._get_msg_ids(self.srmock.headers_dict) msg_ids = self._get_msg_ids(self.srmock.headers_dict)
print msg_ids
self.assertEquals(len(msg_ids), 3) self.assertEquals(len(msg_ids), 3)
body = json.loads(body[0])
expected_resources = [unicode(messages_path + '/' + id) expected_resources = [unicode(messages_path + '/' + id)
for id in msg_ids] for id in msg_ids]
self.assertEquals(expected_resources, body['resources']) self.assertEquals(expected_resources, result_doc['resources'])
self.assertFalse(body['partial']) self.assertFalse(result_doc['partial'])
sample_messages = json.loads(doc) sample_messages = json.loads(doc)
self.assertEquals(len(msg_ids), len(sample_messages)) self.assertEquals(len(msg_ids), len(sample_messages))
lookup = dict([(m['ttl'], m['body']) for m in sample_messages]) lookup = dict([(m['ttl'], m['body']) for m in sample_messages])
@ -81,99 +72,72 @@ class MessagesBaseTest(base.TestBase):
# Test GET on the message resource directly # Test GET on the message resource directly
for msg_id in msg_ids: for msg_id in msg_ids:
message_uri = messages_path + '/' + msg_id message_uri = messages_path + '/' + msg_id
env = testing.create_environ(message_uri, method='GET')
body = self.app(env, self.srmock)[0] # Wrong project ID
self.simulate_get(message_uri, '777777')
self.assertEquals(self.srmock.status, falcon.HTTP_404)
# Correct project ID
result = self.simulate_get(message_uri, self.project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
self.assertEquals(self.srmock.headers_dict['Content-Location'], self.assertEquals(self.srmock.headers_dict['Content-Location'],
message_uri) message_uri)
msg = json.loads(body) message = json.loads(result[0])
self.assertEquals(msg['href'], message_uri) self.assertEquals(message['href'], message_uri)
self.assertEquals(msg['body'], lookup[msg['ttl']]) self.assertEquals(message['body'], lookup[message['ttl']])
# Test bulk GET # Test bulk GET
query_string = 'ids=' + ','.join(msg_ids) query_string = 'ids=' + ','.join(msg_ids)
env = testing.create_environ(queue_path, method='GET', result = self.simulate_get(self.queue_path, self.project_id,
query_string=query_string) query_string=query_string)
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
body = self.app(env, self.srmock)[0] result_doc = json.loads(result[0])
document = json.loads(body)
expected_ttls = set(m['ttl'] for m in sample_messages) expected_ttls = set(m['ttl'] for m in sample_messages)
actual_ttls = set(m['ttl'] for m in document) actual_ttls = set(m['ttl'] for m in result_doc)
self.assertFalse(expected_ttls - actual_ttls) self.assertFalse(expected_ttls - actual_ttls)
def test_post_to_mia_queue(self): def test_post_to_mia_queue(self):
self._post_messages('/v1/480924/queues/nonexistent/messages') self._post_messages('/v1/queues/nonexistent/messages')
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
def test_post_bad_message(self): def test_post_bad_message(self):
env = testing.create_environ('/v1/480924/queues/fizbit/messages', for document in (None, '[', '[]', '{}', '.'):
method='POST', self.simulate_post(self.queue_path + '/messages',
body=document,
headers=self.headers) headers=self.headers)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ('/v1/480924/queues/fizbit/messages',
method='POST',
body='[',
headers=self.headers)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ('/v1/480924/queues/fizbit/messages',
method='POST',
body='[]',
headers=self.headers)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ('/v1/480924/queues/fizbit/messages',
method='POST',
body='{}',
headers=self.headers)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def test_delete(self): def test_delete(self):
self._post_messages('/v1/480924/queues/fizbit/messages') path = self.queue_path + '/messages'
self._post_messages(path)
# NOTE(kgriffs): This implictly tests that posting a single # NOTE(kgriffs): This implictly tests that posting a single
# message returns a message resource, not a queue resource. # message returns a message resource, not a queue resource.
msg_id = self._get_msg_id(self.srmock.headers_dict) msg_id = self._get_msg_id(self.srmock.headers_dict)
env = testing.create_environ('/v1/480924/queues/fizbit/messages/' self.simulate_get(path + '/' + msg_id, self.project_id)
+ msg_id, method='GET')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
env = testing.create_environ('/v1/480924/queues/fizbit/messages/' self.simulate_delete(path + '/' + msg_id, self.project_id)
+ msg_id, method='DELETE')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
env = testing.create_environ('/v1/480924/queues/fizbit/messages/' self.simulate_get(path + '/' + msg_id, self.project_id)
+ msg_id, method='GET')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
def test_list(self): def test_list(self):
self._post_messages('/v1/480924/queues/fizbit/messages', repeat=10) path = self.queue_path + '/messages'
self._post_messages(path, repeat=10)
env = testing.create_environ('/v1/480924/queues/fizbit/messages', query_string = 'limit=3&echo=true'
query_string='limit=3&echo=true', body = self.simulate_get(path, self.project_id,
query_string=query_string,
headers=self.headers) headers=self.headers)
body = self.app(env, self.srmock)
self.assertEquals(self.srmock.headers_dict['Content-Location'], self.assertEquals(self.srmock.headers_dict['Content-Location'],
env['PATH_INFO'] + '?' + env['QUERY_STRING']) path + '?' + query_string)
cnt = 0 cnt = 0
while self.srmock.status == falcon.HTTP_200: while self.srmock.status == falcon.HTTP_200:
@ -181,68 +145,55 @@ class MessagesBaseTest(base.TestBase):
[target, params] = contents['links'][0]['href'].split('?') [target, params] = contents['links'][0]['href'].split('?')
for msg in contents['messages']: for msg in contents['messages']:
env = testing.create_environ(msg['href']) self.simulate_get(msg['href'], self.project_id)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
env = testing.create_environ(target, body = self.simulate_get(target, self.project_id,
query_string=params, query_string=params,
headers=self.headers) headers=self.headers)
body = self.app(env, self.srmock)
cnt += 1 cnt += 1
self.assertEquals(cnt, 4) self.assertEquals(cnt, 4)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
# Stats # Stats
env = testing.create_environ('/v1/480924/queues/fizbit/stats') body = self.simulate_get(self.queue_path + '/stats', self.project_id)
body = self.app(env, self.srmock)
countof = json.loads(body[0])
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
countof = json.loads(body[0])
self.assertEquals(self.srmock.headers_dict['Content-Location'], self.assertEquals(self.srmock.headers_dict['Content-Location'],
env['PATH_INFO']) self.queue_path + '/stats')
self.assertEquals(countof['messages']['free'], 10) self.assertEquals(countof['messages']['free'], 10)
env = testing.create_environ('/v1/480924/queues/nonexistent/messages', self.simulate_get('/v1/queues/nonexistent/messages', self.project_id,
headers=self.headers) headers=self.headers)
body = self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
def test_list_with_bad_marker(self): def test_list_with_bad_marker(self):
self._post_messages('/v1/480924/queues/fizbit/messages', repeat=5) path = self.queue_path + '/messages'
self._post_messages(path, repeat=5)
query_string = 'limit=3&echo=true&marker=sfhlsfdjh2048' query_string = 'limit=3&echo=true&marker=sfhlsfdjh2048'
env = testing.create_environ('/v1/480924/queues/fizbit/messages', self.simulate_get(path, self.project_id,
query_string=query_string, query_string=query_string,
headers=self.headers) headers=self.headers)
self.app(env, self.srmock)
self.assertEqual(self.srmock.status, falcon.HTTP_400) self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_no_uuid(self): def test_no_uuid(self):
env = testing.create_environ('/v1/480924/queues/fizbit/messages', path = self.queue_path + '/messages'
method='POST',
body='[{"body": 0, "ttl": 0}]') self.simulate_post(path, '7e7e7e', body='[{"body": 0, "ttl": 0}]')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ('/v1/480924/queues/fizbit/messages', self.simulate_get(path, '7e7e7e')
method='GET')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def _post_messages(self, target, repeat=1): def _post_messages(self, target, repeat=1):
doc = json.dumps([{'body': 239, 'ttl': 30}] * repeat) doc = json.dumps([{'body': 239, 'ttl': 30}] * repeat)
self.simulate_post(target, self.project_id, body=doc,
env = testing.create_environ(target,
method='POST',
body=doc,
headers=self.headers) headers=self.headers)
self.app(env, self.srmock)
def _get_msg_id(self, headers): def _get_msg_id(self, headers):
return headers['Location'].rsplit('/', 1)[-1] return headers['Location'].rsplit('/', 1)[-1]
@ -272,36 +223,24 @@ class MessagesFaultyDriverTests(base.TestBaseFaulty):
config_filename = 'wsgi_faulty.conf' config_filename = 'wsgi_faulty.conf'
def test_simple(self): def test_simple(self):
project_id = 'xyz'
path = '/v1/queues/fizbit/messages'
doc = '[{"body": 239, "ttl": 10}]' doc = '[{"body": 239, "ttl": 10}]'
headers = { headers = {
'Client-ID': '30387f00', 'Client-ID': '30387f00',
} }
env = testing.create_environ('/v1/480924/queues/fizbit/messages', self.simulate_post(path, project_id,
method='POST',
body=doc, body=doc,
headers=headers) headers=headers)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues/fizbit/messages', self.simulate_get(path, project_id,
method='GET',
headers=headers) headers=headers)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues/fizbit/messages' self.simulate_get(path + '/nonexistent', project_id)
'/nonexistent',
method='GET')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues/fizbit/messages' self.simulate_delete(path + '/nada', project_id)
'/nonexistent',
method='DELETE')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)

View File

@ -18,7 +18,6 @@ import json
import os import os
import falcon import falcon
from falcon import testing
import pymongo import pymongo
from marconi.common import config from marconi.common import config
@ -31,76 +30,54 @@ class QueueLifecycleBaseTest(base.TestBase):
config_filename = None config_filename = None
def test_simple(self): def test_simple(self):
doc = '{"messages": {"ttl": 600}}' path = '/v1/queues/gumshoe'
for project_id in ('480924', 'foo', '', None):
# Create # Create
env = testing.create_environ('/v1/480924/queues/gumshoe', doc = '{"messages": {"ttl": 600}}'
method='PUT', body=doc) self.simulate_put(path, project_id, body=doc)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_201) self.assertEquals(self.srmock.status, falcon.HTTP_201)
location = ('Location', '/v1/480924/queues/gumshoe') location = ('Location', '/v1/queues/gumshoe')
self.assertIn(location, self.srmock.headers) self.assertIn(location, self.srmock.headers)
env = testing.create_environ('/v1/480924/queues/gumshoe') result = self.simulate_get(path, project_id)
result = self.app(env, self.srmock)
result_doc = json.loads(result[0]) result_doc = json.loads(result[0])
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
self.assertEquals(result_doc, json.loads(doc)) self.assertEquals(result_doc, json.loads(doc))
# Delete # Delete
env = testing.create_environ('/v1/480924/queues/gumshoe', self.simulate_delete(path, project_id)
method='DELETE')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
# Get non-existing # Get non-existing
env = testing.create_environ('/v1/480924/queues/gumshoe') self.simulate_get(path, project_id)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_404) self.assertEquals(self.srmock.status, falcon.HTTP_404)
def test_no_metadata(self): def test_no_metadata(self):
env = testing.create_environ('/v1/480924/queues/fizbat', method='PUT') self.simulate_put('/v1/queues/fizbat')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def test_bad_metadata(self): def test_bad_metadata(self):
env = testing.create_environ('/v1/480924/queues/fizbat', for document in ('{', '[]', '.', ' ', ''):
body='{', self.simulate_put('/v1/queues/fizbat', '7e55e1a7e',
method='PUT') body=document)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400)
env = testing.create_environ('/v1/480924/queues/fizbat',
body='[]',
method='PUT')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def test_too_much_metadata(self): def test_too_much_metadata(self):
doc = '{"messages": {"ttl": 600}, "padding": "%s"}' doc = '{"messages": {"ttl": 600}, "padding": "%s"}'
padding_len = transport.MAX_QUEUE_METADATA_SIZE - (len(doc) - 2) + 1 padding_len = transport.MAX_QUEUE_METADATA_SIZE - (len(doc) - 2) + 1
doc = doc % ('x' * padding_len) doc = doc % ('x' * padding_len)
env = testing.create_environ('/v1/480924/queues/fizbat',
method='PUT', body=doc)
self.app(env, self.srmock) self.simulate_put('/v1/queues/fizbat', 'deadbeef', body=doc)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def test_way_too_much_metadata(self): def test_way_too_much_metadata(self):
doc = '{"messages": {"ttl": 600}, "padding": "%s"}' doc = '{"messages": {"ttl": 600}, "padding": "%s"}'
padding_len = transport.MAX_QUEUE_METADATA_SIZE * 100 padding_len = transport.MAX_QUEUE_METADATA_SIZE * 100
doc = doc % ('x' * padding_len) doc = doc % ('x' * padding_len)
env = testing.create_environ('/v1/480924/queues/gumshoe',
method='PUT', body=doc)
self.app(env, self.srmock) self.simulate_put('/v1/queues/fizbat', 'deadbeef', body=doc)
self.assertEquals(self.srmock.status, falcon.HTTP_400) self.assertEquals(self.srmock.status, falcon.HTTP_400)
def test_custom_metadata(self): def test_custom_metadata(self):
@ -108,103 +85,84 @@ class QueueLifecycleBaseTest(base.TestBase):
doc = '{"messages": {"ttl": 600}, "padding": "%s"}' doc = '{"messages": {"ttl": 600}, "padding": "%s"}'
padding_len = transport.MAX_QUEUE_METADATA_SIZE - (len(doc) - 2) padding_len = transport.MAX_QUEUE_METADATA_SIZE - (len(doc) - 2)
doc = doc % ('x' * padding_len) doc = doc % ('x' * padding_len)
env = testing.create_environ('/v1/480924/queues/gumshoe', self.simulate_put('/v1/queues/fizbat', '480924', body=doc)
method='PUT', body=doc)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_201) self.assertEquals(self.srmock.status, falcon.HTTP_201)
# Get # Get
env = testing.create_environ('/v1/480924/queues/gumshoe') result = self.simulate_get('/v1/queues/fizbat', '480924')
result = self.app(env, self.srmock)
result_doc = json.loads(result[0]) result_doc = json.loads(result[0])
self.assertEquals(result_doc, json.loads(doc)) self.assertEquals(result_doc, json.loads(doc))
def test_update_metadata(self): def test_update_metadata(self):
path = '/v1/queues/xyz'
project_id = '480924'
# Create # Create
doc1 = '{"messages": {"ttl": 600}}' doc1 = '{"messages": {"ttl": 600}}'
env = testing.create_environ('/v1/480924/queues/xyz', self.simulate_put(path, project_id, body=doc1)
method='PUT', body=doc1)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_201) self.assertEquals(self.srmock.status, falcon.HTTP_201)
# Update # Update
doc2 = '{"messages": {"ttl": 100}}' doc2 = '{"messages": {"ttl": 100}}'
env = testing.create_environ('/v1/480924/queues/xyz', self.simulate_put(path, project_id, body=doc2)
method='PUT', body=doc2)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
# Get # Get
env = testing.create_environ('/v1/480924/queues/xyz') result = self.simulate_get(path, project_id)
result = self.app(env, self.srmock)
result_doc = json.loads(result[0]) result_doc = json.loads(result[0])
self.assertEquals(result_doc, json.loads(doc2)) self.assertEquals(result_doc, json.loads(doc2))
self.assertEquals(self.srmock.headers_dict['Content-Location'], self.assertEquals(self.srmock.headers_dict['Content-Location'],
env['PATH_INFO']) path)
def test_list(self): def test_list(self):
# List empty project_id = '644079696574693'
env = testing.create_environ('/v1/480924/queues') alt_project_id = '644079696574694'
self.app(env, self.srmock) # List empty
self.simulate_get('/v1/queues', project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
# Create some # Create some
env = testing.create_environ('/v1/480924/queues/q1', self.simulate_put('/v1/queues/q1', project_id, body='{"_ttl": 30 }')
method='PUT', self.simulate_put('/v1/queues/q2', project_id, body='{}')
body='{"_ttl": 30 }') self.simulate_put('/v1/queues/q3', project_id, body='{"_ttl": 30 }')
self.app(env, self.srmock)
env = testing.create_environ('/v1/480924/queues/q2', # List (no metadata)
method='PUT', result = self.simulate_get('/v1/queues', project_id,
body='{}')
self.app(env, self.srmock)
env = testing.create_environ('/v1/480924/queues/q3',
method='PUT',
body='{"_ttl": 30 }')
self.app(env, self.srmock)
# List
env = testing.create_environ('/v1/480924/queues',
query_string='limit=2') query_string='limit=2')
result = self.app(env, self.srmock)
result_doc = json.loads(result[0]) result_doc = json.loads(result[0])
[target, params] = result_doc['links'][0]['href'].split('?') [target, params] = result_doc['links'][0]['href'].split('?')
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
self.assertEquals(self.srmock.headers_dict['Content-Location'], self.assertEquals(self.srmock.headers_dict['Content-Location'],
env['PATH_INFO'] + '?' + env['QUERY_STRING']) '/v1/queues?limit=2')
for queue in result_doc['queues']: for queue in result_doc['queues']:
env = testing.create_environ(queue['href']) self.simulate_get(queue['href'], project_id)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_200) self.assertEquals(self.srmock.status, falcon.HTTP_200)
self.simulate_get(queue['href'], alt_project_id)
self.assertEquals(self.srmock.status, falcon.HTTP_404)
self.assertNotIn('metadata', queue) self.assertNotIn('metadata', queue)
# List with metadata # List with metadata
env = testing.create_environ(target, result = self.simulate_get('/v1/queues', project_id,
query_string=params + '&detailed=true') query_string=params + '&detailed=true')
result = self.app(env, self.srmock) self.assertEquals(self.srmock.status, falcon.HTTP_200)
result_doc = json.loads(result[0]) result_doc = json.loads(result[0])
[target, params] = result_doc['links'][0]['href'].split('?') [target, params] = result_doc['links'][0]['href'].split('?')
[queue] = result_doc['queues'] [queue] = result_doc['queues']
env = testing.create_environ(queue['href']) result = self.simulate_get(queue['href'], project_id)
result = self.app(env, self.srmock)
result_doc = json.loads(result[0]) result_doc = json.loads(result[0])
self.assertEquals(result_doc, queue['metadata']) self.assertEquals(result_doc, queue['metadata'])
# List tail # List tail
env = testing.create_environ(target, query_string=params) self.simulate_get(target, project_id, query_string=params)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_204) self.assertEquals(self.srmock.status, falcon.HTTP_204)
@ -235,36 +193,24 @@ class QueueFaultyDriverTests(base.TestBaseFaulty):
config_filename = 'wsgi_faulty.conf' config_filename = 'wsgi_faulty.conf'
def test_simple(self): def test_simple(self):
path = '/v1/queues/gumshoe'
doc = '{"messages": {"ttl": 600}}' doc = '{"messages": {"ttl": 600}}'
env = testing.create_environ('/v1/480924/queues/gumshoe', self.simulate_put(path, '480924', body=doc)
method='PUT', body=doc)
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
location = ('Location', '/v1/480924/queues/gumshoe') location = ('Location', path)
self.assertNotIn(location, self.srmock.headers) self.assertNotIn(location, self.srmock.headers)
env = testing.create_environ('/v1/480924/queues/gumshoe') result = self.simulate_get(path, '480924')
result = self.app(env, self.srmock)
result_doc = json.loads(result[0]) result_doc = json.loads(result[0])
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
self.assertNotEquals(result_doc, json.loads(doc)) self.assertNotEquals(result_doc, json.loads(doc))
env = testing.create_environ('/v1/480924/queues/gumshoe/stats') self.simulate_get(path + '/stats', '480924')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues') self.simulate_get('/v1/queues', '480924')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)
env = testing.create_environ('/v1/480924/queues/gumshoe', self.simulate_delete(path, '480924')
method='DELETE')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503)
def test_bad_document(self):
env = testing.create_environ('/v1/480924/queues/bad-doc')
self.app(env, self.srmock)
self.assertEquals(self.srmock.status, falcon.HTTP_503) self.assertEquals(self.srmock.status, falcon.HTTP_503)

View File

@ -37,12 +37,16 @@ WSGI_CFG = config.namespace('drivers:transport:wsgi').from_options(**OPTIONS)
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def _extract_project_id(req, resp, params):
params['project_id'] = req.get_header('X-PROJECT-ID')
class Driver(transport.DriverBase): class Driver(transport.DriverBase):
def __init__(self, storage): def __init__(self, storage):
super(Driver, self).__init__(storage) super(Driver, self).__init__(storage)
self.app = falcon.API() self.app = falcon.API(before=_extract_project_id)
queue_controller = self.storage.queue_controller queue_controller = self.storage.queue_controller
message_controller = self.storage.message_controller message_controller = self.storage.message_controller
@ -50,31 +54,31 @@ class Driver(transport.DriverBase):
# Queues Endpoints # Queues Endpoints
queue_collection = queues.CollectionResource(queue_controller) queue_collection = queues.CollectionResource(queue_controller)
self.app.add_route('/v1/{project_id}/queues', queue_collection) self.app.add_route('/v1/queues', queue_collection)
queue_item = queues.ItemResource(queue_controller, message_controller) queue_item = queues.ItemResource(queue_controller, message_controller)
self.app.add_route('/v1/{project_id}/queues/{queue_name}', queue_item) self.app.add_route('/v1/queues/{queue_name}', queue_item)
stats_endpoint = stats.Resource(queue_controller) stats_endpoint = stats.Resource(queue_controller)
self.app.add_route('/v1/{project_id}/queues/{queue_name}' self.app.add_route('/v1/queues/{queue_name}'
'/stats', stats_endpoint) '/stats', stats_endpoint)
# Messages Endpoints # Messages Endpoints
msg_collection = messages.CollectionResource(message_controller) msg_collection = messages.CollectionResource(message_controller)
self.app.add_route('/v1/{project_id}/queues/{queue_name}' self.app.add_route('/v1/queues/{queue_name}'
'/messages', msg_collection) '/messages', msg_collection)
msg_item = messages.ItemResource(message_controller) msg_item = messages.ItemResource(message_controller)
self.app.add_route('/v1/{project_id}/queues/{queue_name}' self.app.add_route('/v1/queues/{queue_name}'
'/messages/{message_id}', msg_item) '/messages/{message_id}', msg_item)
# Claims Endpoints # Claims Endpoints
claim_collection = claims.CollectionResource(claim_controller) claim_collection = claims.CollectionResource(claim_controller)
self.app.add_route('/v1/{project_id}/queues/{queue_name}' self.app.add_route('/v1/queues/{queue_name}'
'/claims', claim_collection) '/claims', claim_collection)
claim_item = claims.ItemResource(claim_controller) claim_item = claims.ItemResource(claim_controller)
self.app.add_route('/v1/{project_id}/queues/{queue_name}' self.app.add_route('/v1/queues/{queue_name}'
'/claims/{claim_id}', claim_item) '/claims/{claim_id}', claim_item)
# NOTE(flaper87): Install Auth # NOTE(flaper87): Install Auth

View File

@ -173,13 +173,16 @@ class ItemResource(object):
def on_get(self, req, resp, project_id, queue_name, message_id): def on_get(self, req, resp, project_id, queue_name, message_id):
try: try:
print message_id
message = self.message_controller.get( message = self.message_controller.get(
queue_name, queue_name,
message_id, message_id,
project=project_id).next() project=project_id).next()
except StopIteration: except StopIteration:
# Good project_id and queue, but no messages
raise falcon.HTTPNotFound()
except storage_exceptions.DoesNotExist:
# This can happen if the queue or project_id is invalid
raise falcon.HTTPNotFound() raise falcon.HTTPNotFound()
except Exception as ex: except Exception as ex:
LOG.exception(ex) LOG.exception(ex)

View File

@ -68,7 +68,6 @@ class ItemResource(object):
base_path += '/' base_path += '/'
for each_message in messages: for each_message in messages:
print each_message
each_message['href'] = base_path + each_message['id'] each_message['href'] = base_path + each_message['id']
del each_message['id'] del each_message['id']