doc(quickstart): Sync HTTPUnauthorized example with post-0.3 changes (#760)
Update the complex example given in the quickstart and README so that it now works in light of a breaking change to the HTTPUnauthorized class. Note this breaking change in the changelog. Closes #757
This commit is contained in:
committed by
Fran Fitzpatrick
parent
9b2b00a8e1
commit
f44fba57ef
@@ -29,6 +29,10 @@ Breaking Changes
|
||||
app = falcon.API()
|
||||
app.req_options.auto_parse_form_urlencoded = True
|
||||
|
||||
- The ``HTTPUnauthorized`` initializer now requires an
|
||||
additional argument, `challenges`. Per RFC 7235, a server returning a
|
||||
401 must include a WWW-Authenticate header field containing at least
|
||||
one challenge.
|
||||
- The performance of composing the response body was
|
||||
improved. As part of this work, the ``Response.body_encoded``
|
||||
attribute was removed. This property was only intended to be used by
|
||||
|
||||
29
README.rst
29
README.rst
@@ -152,14 +152,14 @@ API.
|
||||
|
||||
# things.py
|
||||
|
||||
# Let's get this party started
|
||||
# Let's get this party started!
|
||||
import falcon
|
||||
|
||||
|
||||
# Falcon follows the REST architectural style, meaning (among
|
||||
# other things) that you think in terms of resources and state
|
||||
# transitions, which map to HTTP verbs.
|
||||
class ThingsResource:
|
||||
class ThingsResource(object):
|
||||
def on_get(self, req, resp):
|
||||
"""Handles GET requests"""
|
||||
resp.status = falcon.HTTP_200 # This is the default status
|
||||
@@ -251,8 +251,10 @@ bodies.
|
||||
class AuthMiddleware(object):
|
||||
|
||||
def process_request(self, req, resp):
|
||||
token = req.get_header('X-Auth-Token')
|
||||
project = req.get_header('X-Project-ID')
|
||||
token = req.get_header('Authorization')
|
||||
account_id = req.get_header('Account-ID')
|
||||
|
||||
challenges = ['Token type="Fernet"']
|
||||
|
||||
if token is None:
|
||||
description = ('Please provide an auth token '
|
||||
@@ -260,18 +262,19 @@ bodies.
|
||||
|
||||
raise falcon.HTTPUnauthorized('Auth token required',
|
||||
description,
|
||||
challenges,
|
||||
href='http://docs.example.com/auth')
|
||||
|
||||
if not self._token_is_valid(token, project):
|
||||
if not self._token_is_valid(token, account_id):
|
||||
description = ('The provided auth token is not valid. '
|
||||
'Please request a new token and try again.')
|
||||
|
||||
raise falcon.HTTPUnauthorized('Authentication required',
|
||||
description,
|
||||
href='http://docs.example.com/auth',
|
||||
scheme='Token; UUID')
|
||||
challenges,
|
||||
href='http://docs.example.com/auth')
|
||||
|
||||
def _token_is_valid(self, token, project):
|
||||
def _token_is_valid(self, token, account_id):
|
||||
return True # Suuuuuure it's valid...
|
||||
|
||||
|
||||
@@ -337,7 +340,7 @@ bodies.
|
||||
return hook
|
||||
|
||||
|
||||
class ThingsResource:
|
||||
class ThingsResource(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self.db = db
|
||||
@@ -367,7 +370,7 @@ bodies.
|
||||
# that would serialize to JSON under the covers.
|
||||
req.context['result'] = result
|
||||
|
||||
resp.set_header('X-Powered-By', 'Small Furry Creatures')
|
||||
resp.set_header('Powered-By', 'Falcon')
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
@falcon.before(max_body(64 * 1024))
|
||||
@@ -406,11 +409,15 @@ bodies.
|
||||
sink = SinkAdapter()
|
||||
app.add_sink(sink, r'/search/(?P<engine>ddg|y)\Z')
|
||||
|
||||
# Useful for debugging problems in your API; works with pdb.set_trace()
|
||||
# Useful for debugging problems in your API; works with pdb.set_trace(). You
|
||||
# can also use Gunicorn to host your app. Gunicorn can be configured to
|
||||
# auto-restart workers when it detects a code change, and it also works
|
||||
# with pdb.
|
||||
if __name__ == '__main__':
|
||||
httpd = simple_server.make_server('127.0.0.1', 8000, app)
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
Community
|
||||
---------
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ Breaking Changes
|
||||
app = falcon.API()
|
||||
app.req_options.auto_parse_form_urlencoded = True
|
||||
|
||||
- The :class:`~falcon.HTTPUnauthorized` initializer now requires an
|
||||
additional argument, `challenges`. Per RFC 7235, a server returning a
|
||||
401 must include a WWW-Authenticate header field containing at least
|
||||
one challenge.
|
||||
- The performance of composing the response body was
|
||||
improved. As part of this work, the :attr:`Response.body_encoded`
|
||||
attribute was removed. This property was only intended to be used by
|
||||
|
||||
@@ -21,7 +21,7 @@ started writing an API:
|
||||
|
||||
# things.py
|
||||
|
||||
# Let's get this party started
|
||||
# Let's get this party started!
|
||||
import falcon
|
||||
|
||||
|
||||
@@ -121,8 +121,10 @@ parameters, handling errors, and working with request and response bodies.
|
||||
class AuthMiddleware(object):
|
||||
|
||||
def process_request(self, req, resp):
|
||||
token = req.get_header('X-Auth-Token')
|
||||
project = req.get_header('X-Project-ID')
|
||||
token = req.get_header('Authorization')
|
||||
account_id = req.get_header('Account-ID')
|
||||
|
||||
challenges = ['Token type="Fernet"']
|
||||
|
||||
if token is None:
|
||||
description = ('Please provide an auth token '
|
||||
@@ -130,18 +132,19 @@ parameters, handling errors, and working with request and response bodies.
|
||||
|
||||
raise falcon.HTTPUnauthorized('Auth token required',
|
||||
description,
|
||||
challenges,
|
||||
href='http://docs.example.com/auth')
|
||||
|
||||
if not self._token_is_valid(token, project):
|
||||
if not self._token_is_valid(token, account_id):
|
||||
description = ('The provided auth token is not valid. '
|
||||
'Please request a new token and try again.')
|
||||
|
||||
raise falcon.HTTPUnauthorized('Authentication required',
|
||||
description,
|
||||
href='http://docs.example.com/auth',
|
||||
scheme='Token; UUID')
|
||||
challenges,
|
||||
href='http://docs.example.com/auth')
|
||||
|
||||
def _token_is_valid(self, token, project):
|
||||
def _token_is_valid(self, token, account_id):
|
||||
return True # Suuuuuure it's valid...
|
||||
|
||||
|
||||
@@ -237,7 +240,7 @@ parameters, handling errors, and working with request and response bodies.
|
||||
# that would serialize to JSON under the covers.
|
||||
req.context['result'] = result
|
||||
|
||||
resp.set_header('X-Powered-By', 'Small Furry Creatures')
|
||||
resp.set_header('Powered-By', 'Falcon')
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
@falcon.before(max_body(64 * 1024))
|
||||
@@ -276,7 +279,10 @@ parameters, handling errors, and working with request and response bodies.
|
||||
sink = SinkAdapter()
|
||||
app.add_sink(sink, r'/search/(?P<engine>ddg|y)\Z')
|
||||
|
||||
# Useful for debugging problems in your API; works with pdb.set_trace()
|
||||
# Useful for debugging problems in your API; works with pdb.set_trace(). You
|
||||
# can also use Gunicorn to host your app. Gunicorn can be configured to
|
||||
# auto-restart workers when it detects a code change, and it also works
|
||||
# with pdb.
|
||||
if __name__ == '__main__':
|
||||
httpd = simple_server.make_server('127.0.0.1', 8000, app)
|
||||
httpd.serve_forever()
|
||||
|
||||
@@ -52,7 +52,8 @@ class HTTPUnauthorized(HTTPError):
|
||||
a helpful suggestion or two.
|
||||
challenges (iterable of str): One or more authentication
|
||||
challenges to use as the value of the WWW-Authenticate header in
|
||||
the response.
|
||||
the response. See also:
|
||||
http://tools.ietf.org/html/rfc7235#section-2.1
|
||||
kwargs (optional): Same as for ``HTTPError``.
|
||||
|
||||
"""
|
||||
|
||||
@@ -49,8 +49,10 @@ class SinkAdapter(object):
|
||||
class AuthMiddleware(object):
|
||||
|
||||
def process_request(self, req, resp):
|
||||
token = req.get_header('X-Auth-Token')
|
||||
project = req.get_header('X-Project-ID')
|
||||
token = req.get_header('Authorization')
|
||||
account_id = req.get_header('Account-ID')
|
||||
|
||||
challenges = ['Token type="Fernet"']
|
||||
|
||||
if token is None:
|
||||
description = ('Please provide an auth token '
|
||||
@@ -58,18 +60,19 @@ class AuthMiddleware(object):
|
||||
|
||||
raise falcon.HTTPUnauthorized('Auth token required',
|
||||
description,
|
||||
challenges,
|
||||
href='http://docs.example.com/auth')
|
||||
|
||||
if not self._token_is_valid(token, project):
|
||||
if not self._token_is_valid(token, account_id):
|
||||
description = ('The provided auth token is not valid. '
|
||||
'Please request a new token and try again.')
|
||||
|
||||
raise falcon.HTTPUnauthorized('Authentication required',
|
||||
description,
|
||||
href='http://docs.example.com/auth',
|
||||
scheme='Token; UUID')
|
||||
challenges,
|
||||
href='http://docs.example.com/auth')
|
||||
|
||||
def _token_is_valid(self, token, project):
|
||||
def _token_is_valid(self, token, account_id):
|
||||
return True # Suuuuuure it's valid...
|
||||
|
||||
|
||||
@@ -135,7 +138,7 @@ def max_body(limit):
|
||||
return hook
|
||||
|
||||
|
||||
class ThingsResource:
|
||||
class ThingsResource(object):
|
||||
|
||||
def __init__(self, db):
|
||||
self.db = db
|
||||
@@ -165,7 +168,7 @@ class ThingsResource:
|
||||
# that would serialize to JSON under the covers.
|
||||
req.context['result'] = result
|
||||
|
||||
resp.set_header('X-Powered-By', 'Small Furry Creatures')
|
||||
resp.set_header('Powered-By', 'Falcon')
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
@falcon.before(max_body(64 * 1024))
|
||||
@@ -204,7 +207,10 @@ app.add_error_handler(StorageError, StorageError.handle)
|
||||
sink = SinkAdapter()
|
||||
app.add_sink(sink, r'/search/(?P<engine>ddg|y)\Z')
|
||||
|
||||
# Useful for debugging problems in your API; works with pdb.set_trace()
|
||||
# Useful for debugging problems in your API; works with pdb.set_trace(). You
|
||||
# can also use Gunicorn to host your app. Gunicorn can be configured to
|
||||
# auto-restart workers when it detects a code change, and it also works
|
||||
# with pdb.
|
||||
if __name__ == '__main__':
|
||||
httpd = simple_server.make_server('127.0.0.1', 8000, app)
|
||||
httpd.serve_forever()
|
||||
|
||||
@@ -73,18 +73,18 @@ class UnauthorizedResource:
|
||||
|
||||
def on_get(self, req, resp):
|
||||
raise falcon.HTTPUnauthorized('Authentication Required',
|
||||
'Missing or invalid token header.',
|
||||
'Missing or invalid authorization.',
|
||||
['Basic realm="simple"'])
|
||||
|
||||
def on_post(self, req, resp):
|
||||
raise falcon.HTTPUnauthorized('Authentication Required',
|
||||
'Missing or invalid token header.',
|
||||
'Missing or invalid authorization.',
|
||||
['Newauth realm="apps"',
|
||||
'Basic realm="simple"'])
|
||||
|
||||
def on_put(self, req, resp):
|
||||
raise falcon.HTTPUnauthorized('Authentication Required',
|
||||
'Missing or invalid token header.', [])
|
||||
'Missing or invalid authorization.', [])
|
||||
|
||||
|
||||
class NotFoundResource:
|
||||
|
||||
Reference in New Issue
Block a user