From 2b63419867d232fb498c5a01b9901815d6f3a3b9 Mon Sep 17 00:00:00 2001 From: Kurt Griffiths Date: Tue, 16 Aug 2016 23:52:00 -0500 Subject: [PATCH] feat(http_error): Add HTTPUriTooLong error class for HTTP status 414 (#870) --- doc/api/errors.rst | 5 +++-- falcon/errors.py | 24 ++++++++++++++++++++++++ tests/test_httperror.py | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/doc/api/errors.rst b/doc/api/errors.rst index 4e4e9d8..463a3e7 100644 --- a/doc/api/errors.rst +++ b/doc/api/errors.rst @@ -35,7 +35,8 @@ Predefined Errors HTTPInvalidParam, HTTPMissingParam, HTTPBadRequest, HTTPUnauthorized, HTTPForbidden, HTTPNotFound, HTTPMethodNotAllowed, HTTPNotAcceptable, HTTPConflict, - HTTPLengthRequired, HTTPPreconditionFailed, HTTPUnsupportedMediaType, - HTTPRangeNotSatisfiable, HTTPUnprocessableEntity, HTTPTooManyRequests, + HTTPLengthRequired, HTTPPreconditionFailed, HTTPRequestEntityTooLarge, + HTTPUriTooLong, HTTPUnsupportedMediaType, HTTPRangeNotSatisfiable, + HTTPUnprocessableEntity, HTTPTooManyRequests, HTTPUnavailableForLegalReasons, HTTPInternalServerError, HTTPBadGateway, HTTPServiceUnavailable diff --git a/falcon/errors.py b/falcon/errors.py index 2be4eb3..90455b5 100644 --- a/falcon/errors.py +++ b/falcon/errors.py @@ -295,6 +295,30 @@ class HTTPRequestEntityTooLarge(HTTPError): **kwargs) +class HTTPUriTooLong(HTTPError): + """414 URI Too Long. + + The server is refusing to process a request because the request-target is + longer than the server is willing to interpret. + + This usually occurs when the client is sending a GET request with long + query information, when the client has descended in a redirection loop + that points to a suffix of itself or when the server is under attack by a + client. + + (RFC 7231) + + Args: + title (str): Error title (default '414 URI Too Long'). + description (str): Human-friendly description of the error, along with + a helpful suggestion or two (default ``None``). + kwargs (optional): Same as for ``HTTPError``. + """ + + def __init__(self, title=None, description=None, **kwargs): + super(HTTPUriTooLong, self).__init__(status.HTTP_414, title, description, **kwargs) + + class HTTPUnsupportedMediaType(HTTPError): """415 Unsupported Media Type. diff --git a/tests/test_httperror.py b/tests/test_httperror.py index 14f0eef..2a91b58 100644 --- a/tests/test_httperror.py +++ b/tests/test_httperror.py @@ -153,6 +153,19 @@ class TemporaryRequestEntityTooLongResource: retry_after=self.retry_after) +class UriTooLongResource: + + def __init__(self, title=None, description=None, code=None): + self.title = title + self.description = description + self.code = code + + def on_get(self, req, resp): + raise falcon.HTTPUriTooLong(self.title, + self.description, + code=self.code) + + class RangeNotSatisfiableResource: def on_get(self, req, resp): @@ -639,6 +652,32 @@ class TestHTTPError(testing.TestBase): self.assertIn(('retry-after', falcon.util.dt_to_http(date)), self.srmock.headers) + def test_414(self): + self.api.add_route('/414', UriTooLongResource()) + self.simulate_request('/414') + self.assertEqual(self.srmock.status, falcon.HTTP_414) + + def test_414_with_title(self): + title = 'Argh! Error!' + self.api.add_route('/414', UriTooLongResource(title=title)) + body = self.simulate_request('/414', headers={}) + parsed_body = json.loads(body[0].decode()) + self.assertEqual(parsed_body['title'], title) + + def test_414_with_description(self): + description = 'Be short please.' + self.api.add_route('/414', UriTooLongResource(description=description)) + body = self.simulate_request('/414', headers={}) + parsed_body = json.loads(body[0].decode()) + self.assertEqual(parsed_body['description'], description) + + def test_414_with_custom_kwargs(self): + code = 'someid' + self.api.add_route('/414', UriTooLongResource(code=code)) + body = self.simulate_request('/414', headers={}) + parsed_body = json.loads(body[0].decode()) + self.assertEqual(parsed_body['code'], code) + def test_416(self): self.api = falcon.API() self.api.add_route('/416', RangeNotSatisfiableResource())