Commit 4101131b authored by Sofia Papagiannaki's avatar Sofia Papagiannaki
Browse files

Merge branch 'feature-allowed-methods' into develop

parents ff55e946 30d093db
......@@ -268,7 +268,7 @@ def projects(request):
return get_projects(request)
elif method == "POST":
return create_project(request)
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
@api.api_method(http_method="GET", token_required=True, user_required=False)
......@@ -316,7 +316,7 @@ def project(request, project_id):
return get_project(request, project_id)
if method == "POST":
return modify_project(request, project_id)
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
@api.api_method(http_method="GET", token_required=True, user_required=False)
......@@ -485,7 +485,7 @@ def applications(request):
method = request.method
if method == "GET":
return get_applications(request)
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET'])
def make_application_query(input_data):
......@@ -569,7 +569,7 @@ def memberships(request):
return get_memberships(request)
elif method == "POST":
return post_memberships(request)
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
def make_membership_query(input_data):
......
......@@ -96,7 +96,7 @@ def commissions(request):
return get_pending_commissions(request)
elif method == 'POST':
return issue_commission(request)
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET', 'POST'])
@api.api_method(http_method='GET', token_required=True, user_required=False)
......
......@@ -401,7 +401,8 @@ class QuotaAPITest(TestCase):
# Bad Request
r = client.head(u('commissions'))
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
class TokensApiTest(TestCase):
......@@ -451,7 +452,9 @@ class TokensApiTest(TestCase):
# Check not allowed method
r = client.get(url, post_data={})
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'POST')
# check public mode
r = client.post(url, CONTENT_LENGTH=0)
......
......@@ -487,17 +487,21 @@ class ProjectAPITest(TestCase):
# Bad requests
r = client.head(reverse("api_projects"), **h_admin)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
r = client.head(reverse("api_project",
kwargs={"project_id": 1}), **h_admin)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
r = client.head(reverse("api_applications"), **h_admin)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
r = client.head(reverse("api_memberships"), **h_admin)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
status = self.project_action(1, "nonex", h_owner)
self.assertEqual(status, 400)
......
......@@ -52,14 +52,14 @@ def demux(request):
if request.method == 'GET':
return list_extensions(request)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET'])
def demux_extension(request, extension_alias):
if request.method == 'GET':
return get_extension(request, extension_alias)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET'])
@api.api_method(http_method='GET', user_required=True, logger=log)
......
......@@ -71,7 +71,8 @@ def demux(request):
elif request.method == 'POST':
return allocate_floating_ip(request)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'POST'])
def floating_ip_demux(request, floating_ip_id):
......@@ -82,7 +83,8 @@ def floating_ip_demux(request, floating_ip_id):
elif request.method == 'PUT':
return update_floating_ip(request, floating_ip_id)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'DELETE'])
def ip_to_dict(floating_ip):
......
......@@ -65,7 +65,8 @@ def demux(request):
elif request.method == 'POST':
return create_image(request)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'POST'])
def image_demux(request, image_id):
......@@ -74,7 +75,8 @@ def image_demux(request, image_id):
elif request.method == 'DELETE':
return delete_image(request, image_id)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'DELETE'])
def metadata_demux(request, image_id):
......@@ -83,7 +85,8 @@ def metadata_demux(request, image_id):
elif request.method == 'POST':
return update_metadata(request, image_id)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'POST'])
def metadata_item_demux(request, image_id, key):
......@@ -94,7 +97,10 @@ def metadata_item_demux(request, image_id, key):
elif request.method == 'DELETE':
return delete_metadata_item(request, image_id, key)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET',
'PUT',
'DELETE'])
def image_to_dict(image, detail=True):
......
......@@ -62,7 +62,8 @@ def demux(request):
elif request.method == 'POST':
return create_network(request)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'POST'])
def network_demux(request, network_id):
......@@ -74,7 +75,10 @@ def network_demux(request, network_id):
elif request.method == 'PUT':
return update_network(request, network_id)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET',
'PUT',
'DELETE'])
@api.api_method(http_method='GET', user_required=True, logger=log)
......
......@@ -70,7 +70,8 @@ def demux(request):
elif request.method == 'POST':
return create_server(request)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'POST'])
def server_demux(request, server_id):
......@@ -81,7 +82,10 @@ def server_demux(request, server_id):
elif request.method == 'DELETE':
return delete_server(request, server_id)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET',
'PUT',
'DELETE'])
def metadata_demux(request, server_id):
......@@ -90,7 +94,8 @@ def metadata_demux(request, server_id):
elif request.method == 'POST':
return update_metadata(request, server_id)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET', 'POST'])
def metadata_item_demux(request, server_id, key):
......@@ -101,7 +106,10 @@ def metadata_item_demux(request, server_id, key):
elif request.method == 'DELETE':
return delete_metadata_item(request, server_id, key)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['GET',
'PUT',
'DELETE'])
def nic_to_attachments(nic):
......
......@@ -91,7 +91,8 @@ def api_method(http_method=None, token_required=True, user_required=True,
# Check HTTP method
if http_method and request.method != http_method:
raise faults.BadRequest("Method not allowed")
raise faults.NotAllowed("Method not allowed",
allowed_methods=[http_method])
# Get authentication token
request.x_auth_token = None
......@@ -246,6 +247,8 @@ def render_fault(request, fault):
data = json.dumps(d)
response = HttpResponse(data, status=fault.code)
if response.status_code == 405 and hasattr(fault, 'allowed_methods'):
response['Allow'] = ','.join(fault.allowed_methods)
update_response_headers(request, response)
return response
......@@ -256,8 +259,9 @@ def api_endpoint_not_found(request):
@api_method(token_required=False, user_required=False)
def api_method_not_allowed(request):
raise faults.BadRequest('Method not allowed')
def api_method_not_allowed(request, allowed_methods):
raise faults.NotAllowed("Method not allowed",
allowed_methods=allowed_methods)
def allow_jsonp(key='callback'):
......
......@@ -71,6 +71,18 @@ class ResizeNotAllowed(Forbidden):
pass
class NotAllowed(Fault):
code = 405
def __init__(self, message='', details='', name='', code=500,
allowed_methods=None):
"""
:param allowed_methods: (list) the valid methods
"""
super(NotAllowed, self).__init__(message, details, name, code)
self.allowed_methods = allowed_methods or []
class ItemNotFound(Fault):
code = 404
......
......@@ -268,12 +268,13 @@ class BaseAPITest(TestCase):
self.assertFault(response, 409, "conflict")
def assertMethodNotAllowed(self, response):
self.assertFault(response, 400, 'badRequest')
self.assertFault(response, 405, 'notAllowed')
self.assertTrue('Allow' in response)
try:
error = json.loads(response.content)
except ValueError:
self.assertTrue(False)
self.assertEqual(error['badRequest']['message'], 'Method not allowed')
self.assertEqual(error['notAllowed']['message'], 'Method not allowed')
# Imitate unittest assertions new in Python 2.7
......
......@@ -98,7 +98,7 @@ def top_demux(request):
return authenticate(request)
return account_list(request)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['GET'])
@csrf_exempt
......@@ -117,7 +117,10 @@ def account_demux(request, v_account):
elif request.method == 'GET':
return container_list(request, v_account)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['HEAD',
'POST',
'GET'])
@csrf_exempt
......@@ -140,7 +143,12 @@ def container_demux(request, v_account, v_container):
elif request.method == 'GET':
return object_list(request, v_account, v_container)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request,
allowed_methods=['HEAD',
'PUT',
'POST',
'DELETE',
'GET'])
@csrf_exempt
......@@ -172,7 +180,13 @@ def object_demux(request, v_account, v_container, v_object):
elif request.method == 'DELETE':
return object_delete(request, v_account, v_container, v_object)
else:
return api.api_method_not_allowed(request)
return api.api_method_not_allowed(request, allowed_methods=['HEAD',
'GET',
'PUT',
'COPY',
'MOVE',
'POST',
'DELETE'])
@api_method('GET', token_required=False, user_required=False, logger=logger)
......
......@@ -42,13 +42,22 @@ class TopLevel(PithosAPITest):
def test_not_allowed_method(self):
url = join_urls(self.pithos_path, '/')
r = self.head(url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.put(url, data='')
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.post(url, data='')
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.delete(url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
def test_authenticate(self):
url = join_urls(self.pithos_path, '/')
......
......@@ -92,22 +92,34 @@ class NotAllowedView(PithosAPITest):
get_random_name())
r = self.head(self.view_url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.delete(self.view_url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.post(self.view_url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.put(self.view_url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.copy(self.view_url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
r = self.move(self.view_url)
self.assertEqual(r.status_code, 400)
self.assertEqual(r.status_code, 405)
self.assertTrue('Allow' in r)
self.assertEqual(r['Allow'], 'GET')
class ObjectGetView(PithosAPITest):
......
......@@ -66,7 +66,7 @@ pithos_api_patterns = api_patterns(
pithos_view_patterns = patterns(
'pithos.api.views',
(r'^view/(?P<v_account>.+?)/(?P<v_container>.+?)/(?P<v_object>.+?)$',
'object_read'))
'object_demux'))
pithos_patterns = patterns(
'',
......
......@@ -31,6 +31,10 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from django.views.decorators.csrf import csrf_exempt
from snf_django.lib import api
from pithos.api.functions import _object_read
from pithos.api.util import api_method, view_method
......@@ -38,6 +42,14 @@ import logging
logger = logging.getLogger(__name__)
@csrf_exempt
def object_demux(request, v_account, v_container, v_object):
if request.method == 'GET':
return object_read(request, v_account, v_container, v_object)
else:
return api.api_method_not_allowed(request, allowed_methods=['GET'])
@view_method()
@api_method('GET', format_allowed=True, user_required=True, logger=logger)
def object_read(request, v_account, v_container, v_object):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment