librelist archives

« back to archive

POST request and question about IRC vs Gitter.im

POST request and question about IRC vs Gitter.im

From:
William Hayes
Date:
2015-10-03 @ 23:39
> On Oct 3, 2015, at 7:37 PM, William Hayes <william.s.hayes@gmail.com> wrote:
> 
> Hi all,
> 
> Easier and probably more contentious question (mostly because I’ve never
figured out IRC) - what do you think about shifting to Gitter instead of 
IRC?  It has persistent chat, indicators as to who is core to the github 
project, private chats, email integration, search, …
> 
> Now my main question:
> 
> I’m having trouble getting POST data to my Resource.  I’d appreciate 
some ideas on what I’m doing wrong.  It looks like an empty return in the 
middleware is the right way to  break out of it (I want all routes 
authenticated except for two).  TIA!
> 
> My result: 
> HTTP/1.0 400 Bad Request
> Date: Sat, 03 Oct 2015 23:15:56 GMT
> Server: WSGIServer/0.2 CPython/3.4.3
> content-length: 106
> content-type: application/json
> testme: tester
> 
> {
>     "description": "Must submit email and password to create an account.",
>     "title": "Missing data"
> }
> 
> and debugging console output:
> Req:  None application/json {'USER-AGENT': 'HTTPie/0.9.2', 
'CONTENT-TYPE': 'application/json', 'HOST': 'localhost:8000', 'ACCEPT': 
'application/json', 'ACCEPT-ENCODING': 'gzip, deflate', 'CONNECTION': 
'keep-alive', 'CONTENT-LENGTH': '58’}
> 
> My httpie POST request:
> http --json POST http://localhost:8000/account/registration 
<http://localhost:8000/account/registration> \
>     'Content-Type':'application/json' \
>     email="william.s.hayes@gmail.com <mailto:william.s.hayes@gmail.com>" \
>     password=“test"
> 
> 
> My Registration resource:
> class AccountRegistrationResource(object):
>     """Accounts Resource - registration, password resets etc"""
> 
>     def on_post(self, req, resp):
>         print('Req: ', req.get_param('email'), req.content_type, req.headers)
>         try:
>             email = req.context['email']
>             plaintext_password = req.context['password']
>         except KeyError:
>             raise falcon.HTTPBadRequest(
>                 'Missing data',
>                 'Must submit email and password to create an account.')
> 
>         hashed_pw = hashpw(plaintext_password, gensalt())
> 
>         # if hashpw(password_attempt, hashed) == hashed:
>         #     print "It matches"
>         # else:
>         #     print "It does not match"
> 
>         resp.body = ''
>         resp.status = falcon.HTTP_201
> 
> My middleware:
> import falcon
> import logging
> from .json_web_token import JsonWebToken
> 
> logger = logging.getLogger('middleware')
> logger.setLevel(logging.DEBUG)
> 
> class AuthMiddleware(object):
> 
>     #
>     # TODO NOTE - think about remember me - via a cookie using 
itsdangerous for a self-describing cookie
>     #
>     # 1 Use a two-day expiration on the JWT
>     # 2 Store in secure cookie-browser only
>     # 3 for critical access - change password, etc, check that the token
was issued within
>     #      last 30 min using a password to update - e.g. not a token 
auto-refresh
>     #
> 
>     def process_request(self, req, resp):
> 
>         resp.set_header('TESTME', 'tester')
> 
>         # Don't authenticate following routes
>         skip_routes = ['/account/registration', '/account/reset-password']
>         if req.path in skip_routes:
>             print('Here')
>             return
> 
>         token = req.get_header('X-Auth-Token')
> 
>         logger.info('Path: {} Token: '.format(req.path))
>         print('Path: ', req.path)
> 
>         if token is None:
>             description = ('Please provide an auth token '
>                            'as part of the request.')
> 
>             raise falcon.HTTPUnauthorized('Auth token required',
>                                           description,
>                                           
href='http://docs.example.com/auth' <http://docs.example.com/auth'>)
> 
>         if not self._token_is_valid(token, project):
>             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' <http://docs.example.com/auth'>,
>                                           scheme='Token; UUID')
> 
>     def _token_is_valid(self, token, project):
>         return True  # Suuuuuure it's valid...
> 
> 
> class RequireJSON(object):
> 
>     def process_request(self, req, resp):
>         if not req.client_accepts_json:
>             raise falcon.HTTPNotAcceptable(
>                 'This API only supports responses encoded as JSON.',
>                 href='http://docs.examples.com/api/json' 
<http://docs.examples.com/api/json'>)
> 
>         if req.method in ('POST', 'PUT'):
>             if 'application/json' not in req.content_type:
>                 raise falcon.HTTPUnsupportedMediaType(
>                     'This API only supports requests encoded as JSON.',
>                     href='http://docs.examples.com/api/json' 
<http://docs.examples.com/api/json'>)
> My app.py:
> import falcon
> 
> from Config import config  # Application settings enabled for Dev/Test/Prod
> 
> from api_common.middleware import AuthMiddleware, RequireJSON
> from api_resources.account import AccountRegistrationResource, 
AccountPasswordResetResource
> from api_resources.users import UserProfileResource
> 
> from api_common import custom_logger
> logger = custom_logger.setup_custom_logger('root')
> logger.setLevel(config['log_level'])
> 
> logger.debug('Config: {}'.format(config))
> 
> api = application = falcon.API(middleware=[AuthMiddleware(), RequireJSON()])
> 
> # storage_path = '/usr/local/var/look'
> 
> # image_collection = images.Collection(storage_path)
> # image = images.Item(storage_path)
> 
> # Routes
> # api.add_route('/users', image_collection)
> 
> api.add_route('/account/registration', AccountRegistrationResource())
> api.add_route('/account/password-reset/{email}', AccountPasswordResetResource())
> api.add_route('/user/profile/{userid}', UserProfileResource())
> 
> 
> # Useful for debugging problems in your API; works with pdb.set_trace()
> if __name__ == '__main__':
>     from wsgiref import simple_server
> 
>     host = "127.0.0.1"
>     port = 8000
>     httpd = simple_server.make_server(host, port, api)
>     print("Serving on {}:{}".format(host, port))
>     httpd.serve_forever()
> 

Re: [falcon] POST request and question about IRC vs Gitter.im

From:
Andrew Stuart
Date:
2015-10-04 @ 00:42
A general tip is that it is easier to debug without try except - you’re 
more likely to see the actual error.

Take out the try except and run your code again.


On 4 Oct 2015, at 10:39 am, William Hayes <whayes@cekeeper.com> wrote:


> On Oct 3, 2015, at 7:37 PM, William Hayes <william.s.hayes@gmail.com> wrote:
> 
> Hi all,
> 
> Easier and probably more contentious question (mostly because I’ve never
figured out IRC) - what do you think about shifting to Gitter instead of 
IRC?  It has persistent chat, indicators as to who is core to the github 
project, private chats, email integration, search, …
> 
> Now my main question:
> 
> I’m having trouble getting POST data to my Resource.  I’d appreciate 
some ideas on what I’m doing wrong.  It looks like an empty return in the 
middleware is the right way to  break out of it (I want all routes 
authenticated except for two).  TIA!
> 
> My result: 
> HTTP/1.0 400 Bad Request
> Date: Sat, 03 Oct 2015 23:15:56 GMT
> Server: WSGIServer/0.2 CPython/3.4.3
> content-length: 106
> content-type: application/json
> testme: tester
> 
> {
>     "description": "Must submit email and password to create an account.",
>     "title": "Missing data"
> }
> 
> and debugging console output:
> Req:  None application/json {'USER-AGENT': 'HTTPie/0.9.2', 
'CONTENT-TYPE': 'application/json', 'HOST': 'localhost:8000', 'ACCEPT': 
'application/json', 'ACCEPT-ENCODING': 'gzip, deflate', 'CONNECTION': 
'keep-alive', 'CONTENT-LENGTH': '58’}
> 
> My httpie POST request:
> http --json POST http://localhost:8000/account/registration \
>     'Content-Type':'application/json' \
>     email="william.s.hayes@gmail.com" \
>     password=“test"
> 
> 
> My Registration resource:
> class AccountRegistrationResource(object):
>     """Accounts Resource - registration, password resets etc"""
> 
>     def on_post(self, req, resp):
>         print('Req: ', req.get_param('email'), req.content_type, req.headers)
>         try:
>             email = req.context['email']
>             plaintext_password = req.co
>  ntext[
> 'password']
>         except KeyError:
>             raise falcon.HTTPBadRequest(
>                 'Missing data',
>                 'Must submit email and password to create an account.')
> 
>         hashed_pw = hashpw(plaintext_password, gensalt())
> 
>         # if hashpw(password_attempt, hashed) == hashed:
>         #     pri
>  nt "It matches"
> 
>         # else:
>         #     print "It does not match"
> 
>         resp.body = ''
>         resp.status = falcon.HTTP_201
> 
> My middleware:
> import falcon
> import logging
> from .json_web_token 
> import 
>  
> JsonWebToken
> 
> logger = logging.getLogger('middleware')
> logger.setLevel(logging.DEBUG)
> 
> class AuthMiddleware(object):
> 
>     #
>     # TODO NOTE - think about remember me - via a cookie using 
itsdangerous for a self-describing cookie
>     #
>     # 1 Use a two-day expiration on the JWT
>     # 2 Store in secure cookie-brow
>  ser only
> 
>     # 3 for critical access - change password, etc, check that the token
was issued within
>     #      last 30 min using a password to update - e.g. not a token 
auto-refresh
>     #
> 
>     def process_request(self, req, resp):
> 
>         resp.set_header('TESTME', 'tester')
> 
> 
>          
> # Don't authenticate following routes
>         skip_routes = ['/account/registration', '/account/reset-password']
>         if req.path in skip_routes:
>             print('Here')
>             return
> 
>         token = req.get_header('X-Auth-Token')
> 
>         logger.info('Path: {} Token: '.format(req.path))
>         print('Path: ', req.path)
> 
>         if token is None:
>             description = ('Please provide an auth token '
>                            'as part of the request.')
> 
>             raise falcon.HTTPUnauthorized('Auth token required',
> 
>                                            
> description,
>                                           href='http://docs.example.com/auth')
> 
>         if not self._token_is_valid(token, project):
>             description = ('The provided auth token is not valid. '
>                            'Please request a new token and try again.')
> 
>             raise 
> falcon.HTTPUnauthorize
>  d(
> 'Authentication required',
>                                           description,
>                                           href='http://docs.example.com/auth',
>                                           scheme='Token; UUID')
> 
>     def _token_is_valid(self, token, project):
>         return True  # Suuuuuure it's valid...
> 
> 
> class RequireJSON(object):
> 
>     def process_request(self, req, resp):
>         if not req.client_accepts_json:
>             raise falcon.HTTPNotAcceptable(
>                 'This API only supports responses encoded as JSON.',
>                 href='http://docs.examples.com/api/json')
> 
>         if req.method in ('POST', 
> <
>  span style="color:#008080;" class="">'PUT'
> ):
>             if 'application/json' not in req.content_type:
>                 raise falcon.HTTPUnsupportedMediaType(
>                     'This API only supports requests encoded as JSON.',
>                     href='http://docs.examples.com/api/json')
> My app.py:
> import falcon
> 
> from Config import config  # Application settings enabled for Dev/Test/Prod
> 
> from api_common.middleware import AuthMiddleware, RequireJSON
> from api_resources.account import AccountRegistrationResource, 
> AccountPassword
>  ResetResource
> 
> from api_resources.users import UserProfileResource
> 
> from api_common import custom_logger
> logger = custom_logger.setup_custom_logger('root')
> logger.setLevel(config['log_level'])
> 
> logger.debug('Config: {}'.format(config))
> 
> api = application = falcon.API(middleware=[AuthMiddleware(), RequireJSON()])
> 
> # storage_path = '/usr/local/var/look'
> # image_collection = images.Collection(storage_path)
> # image = images.Item(storage_path)
> 
> # Routes
> # api.add_route('/users', image_collection)
> 
> api.add_route('/account/registration', AccountRegistrationResource())
> api.add_route('/account/password-reset/{email}', AccountPasswordResetResource())
> api.add_route('/user/profile/{userid}', UserProfileResource())
> 
> 
> # Useful for debugging problems in your API; works with pdb.set_trace()
> if __name__ == '__main__':
>     from wsgiref import simple_server
> 
>     host = "127.0.0.1"
>     port = 8000
>     httpd = simple_server.make_server(host, port, api)
>     print("Serving on {}:{}".format(host, port))
>     httpd.serve_forever()
> 

Re: [falcon] POST request and question about IRC vs Gitter.im

From:
William Hayes
Date:
2015-10-04 @ 01:19
Thanks for the tip.  I’m either not using the right API call or something 
is filtering out my req object.  I think I can use either the 
req.context[‘email’] or the reg.get_param(‘email’) but both show up as 
empty when printing them or in the debugger.  I could be doing something 
wrong in the middleware.

Hopefully sleeping on it tonight will work, and it will be blindingly 
obvious tmrw.

> On Oct 3, 2015, at 8:42 PM, Andrew Stuart 
<andrew.stuart@supercoders.com.au> wrote:
> 
> A general tip is that it is easier to debug without try except - you’re 
more likely to see the actual error.
> 
> Take out the try except and run your code again.
> 
> 
> On 4 Oct 2015, at 10:39 am, William Hayes <whayes@cekeeper.com 
<mailto:whayes@cekeeper.com>> wrote:
> 
> 
>> On Oct 3, 2015, at 7:37 PM, William Hayes <william.s.hayes@gmail.com> wrote:
>> 
>> Hi all,
>> 
>> Easier and probably more contentious question (mostly because I’ve 
never figured out IRC) - what do you think about shifting to Gitter 
instead of IRC?  It has persistent chat, indicators as to who is core to 
the github project, private chats, email integration, search, …
>> 
>> Now my main question:
>> 
>> I’m having trouble getting POST data to my Resource.  I’d appreciate 
some ideas on what I’m doing wrong.  It looks like an empty return in the 
middleware is the right way to  break out of it (I want all routes 
authenticated except for two).  TIA!
>> 
>> My result: 
>> HTTP/1.0 400 Bad Request
>> Date: Sat, 03 Oct 2015 23:15:56 GMT
>> Server: WSGIServer/0.2 CPython/3.4.3
>> content-length: 106
>> content-type: application/json
>> testme: tester
>> 
>> {
>>    "description": "Must submit email and password to create an account.",
>>    "title": "Missing data"
>> }
>> 
>> and debugging console output:
>> Req:  None application/json {'USER-AGENT': 'HTTPie/0.9.2', 
'CONTENT-TYPE': 'application/json', 'HOST': 'localhost:8000', 'ACCEPT': 
'application/json', 'ACCEPT-ENCODING': 'gzip, deflate', 'CONNECTION': 
'keep-alive', 'CONTENT-LENGTH': '58’}
>> 
>> My httpie POST request:
>> http --json POST http://localhost:8000/account/registration \
>>    'Content-Type':'application/json' \
>>    email="william.s.hayes@gmail.com" \
>>    password=“test"
>> 
>> 
>> My Registration resource:
>> class AccountRegistrationResource(object):
>>    """Accounts Resource - registration, password resets etc"""
>> 
>>    def on_post(self, req, resp):
>>        print('Req: ', req.get_param('email'), req.content_type, req.headers)
>>        try:
>>            email = req.context['email']
>>            plaintext_password = req.co
>> ntext[
>> 'password']
>>        except KeyError:
>>            raise falcon.HTTPBadRequest(
>>                'Missing data',
>>                'Must submit email and password to create an account.')
>> 
>>        hashed_pw = hashpw(plaintext_password, gensalt())
>> 
>>        # if hashpw(password_attempt, hashed) == hashed:
>>        #     pri
>> nt "It matches"
>> 
>>        # else:
>>        #     print "It does not match"
>> 
>>        resp.body = ''
>>        resp.status = falcon.HTTP_201
>> 
>> My middleware:
>> import falcon
>> import logging
>> from .json_web_token 
>> import 
>> 
>> JsonWebToken
>> 
>> logger = logging.getLogger('middleware')
>> logger.setLevel(logging.DEBUG)
>> 
>> class AuthMiddleware(object):
>> 
>>    #
>>    # TODO NOTE - think about remember me - via a cookie using 
itsdangerous for a self-describing cookie
>>    #
>>    # 1 Use a two-day expiration on the JWT
>>    # 2 Store in secure cookie-brow
>> ser only
>> 
>>    # 3 for critical access - change password, etc, check that the token
was issued within
>>    #      last 30 min using a password to update - e.g. not a token 
auto-refresh
>>    #
>> 
>>    def process_request(self, req, resp):
>> 
>>        resp.set_header('TESTME', 'tester')
>> 
>> 
>> 
>> # Don't authenticate following routes
>>        skip_routes = ['/account/registration', '/account/reset-password']
>>        if req.path in skip_routes:
>>            print('Here')
>>            return
>> 
>>        token = req.get_header('X-Auth-Token')
>> 
>>        logger.info('Path: {} Token: '.format(req.path))
>>        print('Path: ', req.path)
>> 
>>        if token is None:
>>            description = ('Please provide an auth token '
>>                           'as part of the request.')
>> 
>>            raise falcon.HTTPUnauthorized('Auth token required',
>> 
>> 
>> description,
>>                                          href='http://docs.example.com/auth')
>> 
>>        if not self._token_is_valid(token, project):
>>            description = ('The provided auth token is not valid. '
>>                           'Please request a new token and try again.')
>> 
>>            raise 
>> falcon.HTTPUnauthorize
>> d(
>> 'Authentication required',
>>                                          description,
>>                                          href='http://docs.example.com/auth',
>>                                          scheme='Token; UUID')
>> 
>>    def _token_is_valid(self, token, project):
>>        return True  # Suuuuuure it's valid...
>> 
>> 
>> class RequireJSON(object):
>> 
>>    def process_request(self, req, resp):
>>        if not req.client_accepts_json:
>>            raise falcon.HTTPNotAcceptable(
>>                'This API only supports responses encoded as JSON.',
>>                href='http://docs.examples.com/api/json')
>> 
>>        if req.method in ('POST', 
>> <
>> span style="color:#008080;" class="">'PUT'
>> ):
>>            if 'application/json' not in req.content_type:
>>                raise falcon.HTTPUnsupportedMediaType(
>>                    'This API only supports requests encoded as JSON.',
>>                    href='http://docs.examples.com/api/json')
>> My app.py:
>> import falcon
>> 
>> from Config import config  # Application settings enabled for Dev/Test/Prod
>> 
>> from api_common.middleware import AuthMiddleware, RequireJSON
>> from api_resources.account import AccountRegistrationResource, 
>> AccountPassword
>> ResetResource
>> 
>> from api_resources.users import UserProfileResource
>> 
>> from api_common import custom_logger
>> logger = custom_logger.setup_custom_logger('root')
>> logger.setLevel(config['log_level'])
>> 
>> logger.debug('Config: {}'.format(config))
>> 
>> api = application = falcon.API(middleware=[AuthMiddleware(), RequireJSON()])
>> 
>> # storage_path = '/usr/local/var/look'
>> # image_collection = images.Collection(storage_path)
>> # image = images.Item(storage_path)
>> 
>> # Routes
>> # api.add_route('/users', image_collection)
>> 
>> api.add_route('/account/registration', AccountRegistrationResource())
>> api.add_route('/account/password-reset/{email}', 
AccountPasswordResetResource())
>> api.add_route('/user/profile/{userid}', UserProfileResource())
>> 
>> 
>> # Useful for debugging problems in your API; works with pdb.set_trace()
>> if __name__ == '__main__':
>>    from wsgiref import simple_server
>> 
>>    host = "127.0.0.1"
>>    port = 8000
>>    httpd = simple_server.make_server(host, port, api)
>>    print("Serving on {}:{}".format(host, port))
>>    httpd.serve_forever()

Re: [falcon] POST request and question about IRC vs Gitter.im

From:
Andrew Stuart
Date:
2015-10-04 @ 09:17
If you are doing any web development you should learn to use ngrep.  It 
will show you traffic in real time on a given port. 

for example sudo ngrep -W byline -d lo port 80 will show what is happening
on the HTTP port and you can have a close look at your request and see 
what is inside it.




On 4 Oct 2015, at 12:19 pm, William Hayes <whayes@cekeeper.com> wrote:

Thanks for the tip.  I’m either not using the right API call or something 
is filtering out my req object.  I think I can use either the 
req.context[‘email’] or the reg.get_param(‘email’) but both show up as 
empty when printing them or in the debugger.  I could be doing something 
wrong in the middleware.

Hopefully sleeping on it tonight will work, and it will be blindingly 
obvious tmrw.

> On Oct 3, 2015, at 8:42 PM, Andrew Stuart 
<andrew.stuart@supercoders.com.au> wrote:
> 
> A general tip is that it is easier to debug without try except - you’re 
more likely to see the actual error.
> 
> Take out the try except and run your code again.
> 
> 
> On 4 Oct 2015, at 10:39 am, William Hayes <whayes@cekeeper.com> wrote:
> 
> 
>> On Oct 3, 2015, at 7:37 PM, William Hayes <william.s.hayes@gmail.com> wrote:
>> 
>> Hi all,
>> 
>> Easier and probably more contentious question (mostly because I’ve 
never figured out IRC) - what do you think about shifting to Gitter 
instead of IRC?  It has persistent chat, indicators as to who is core to 
the github project, private chats, email integration, search, …
>> 
>> Now my main question:
>> 
>> I’m having trouble getting POST data to my Resource.  I’d appreciate 
some ideas on what I’m doing wrong.  It looks like an empty return in the 
middleware is the right way to  break out of it (I want all routes 
authenticated except for two).  TIA!
>> 
>> My result: 
>> HTTP/1.0 400 Bad Request
>> Date: Sat, 03 Oct 2015 23:15:56 GMT
>> Server: WSGIServer/0.2 CPython/3.4.3
>> content-length: 106
>> content-type: application/json
>> testme: tester
>> 
>> {
>>    "description": "Must submit email and password to create an account.",
>>    "title": "Missing data"
>> }
>> 
>> and debugging console output:
>> Req:  None application/json {'USER-AGENT': 'HTTPie/0.9.2', 
'CONTENT-TYPE': 'application/json', 'HOST': 'localhost:8000', 'ACCEPT': 
'application/json', 'ACCEPT-ENCODING': 'gzip, deflate', 'CONNECTION': 
'keep-alive', 'CONTENT-LENGTH': '58’}
>> 
>> My httpie POST request:
>> http --json POST http://localhost:8000/account/registration \
>>    'Content-Type':'application/json' \
>>    email="william.s.hayes@gmail.com" \
>>    password=“test"
>> 
>> 
>> My Registration resource:
>> class AccountRegistrationResource(object):
>>    """Accounts Resource - registration, password resets etc"""
>> 
>>    def on_post(self, req, resp):
>>        print('Req: ', req.get_param('email'), req.content_type, req.headers)
>>        try:
>>            email = req.context['email']
>>            plaintext_password = req.co
>> ntext[
>> 'password']
>>        except KeyError:
>>            raise falcon.HTTPBadRequest(
>>                'Missing data',
>>                'Must submit email and password to create an account.')
>> 
>>        hashed_pw = hashpw(plaintext_password, gensalt())
>> 
>>        # if hashpw(password_attempt, hashed) == hashed:
>>        #     pri
>> nt "It matches"
>> 
>>        # else:
>>        #     print "It does not match"
>> 
>>        resp.body = ''
>>        resp.status = falcon.HTTP_201
>> 
>> My middleware:
>> import falcon
>> import logging
>> from .json_web_token 
>> import 
>> 
>> JsonWebToken
>> 
>> logger = logging.getLogger('middleware')
>> logger.setLevel(logging.DEBUG)
>> 
>> class AuthMiddleware(object):
>> 
>>    #
>>    # TODO NOTE - think about remember me - via a cookie using 
itsdangerous for a self-describing cookie
>>    #
>>    # 1 Use a two-day expiration on the JWT
>>    # 2 Store in secure cookie-brow
>> ser only
>> 
>>    # 3 for critical access - change password, etc, check that the token
was iss ued within
>>    #      last 30 min using a password to update - e.g. not a token 
auto-refresh
>>    #
>> 
>>    def process_request(self, req, resp):
>> 
>>        resp.set_header('TESTME', 'tester')
>> 
>> 
>> 
>> # Don't authenticate following routes
>>        skip_routes = ['/account/registration', '/account/reset-password']
>>        if req.path in skip_routes:
>>            print('Here')
>>            return
>> 
>>        token = req.get_header('X-Auth-Token')
>> 
>>       & nbsp;logger.info('Path: {} Token: '.format(req.path))
>>        print('Path: ', req.path)
>> 
>>        if token is None:
>>            description = ('Please provide an auth token '
>>                           'as part of the request.')
>> 
>>            raise falcon.HTTPUnauthorized('Auth token required',
>> 
>> 
>> description,
>>                                          href= 'http://docs.example.com/auth')
>> 
>>        if not self._token_is_valid(token, project):
>>            description = ('The provided auth token is not valid. '
>>                           'Please request a new token and try again.')
>> 
>>            raise 
>> falcon.HTTPUnauthorize
>> d(
>> 'Authentication required',
>>                                   &n bsp;      description,
>>                                          href='http://docs.example.com/auth',
>>                                          scheme='Token; UUID')
>> 
>>    def _token_is_valid(self, token, project):
>>        return True  # Suuuuuure it's valid...
>> 
>> 
>> class RequireJSON(object):
>> 
>>    def process_request(self , req, resp):
>>        if not req.client_accepts_json:
>>            raise falcon.HTTPNotAcceptable(
>>                'This API only supports responses encoded as JSON.',
>>                href='http://docs.examples.com/api/json')
>> 
>>        if req.method in ('POST', 
>> <
>> span style="color:#008080;" class="">'PUT'
>> ):
>>            if 'application/json' not in req.content_type:
>>           & nbsp;    raise falcon.HTTPUnsupportedMediaType(
>>                    'This API only supports requests encoded as JSON.',
>>                    href='http://docs.examples.com/api/json')
>> My app.py:
>> import falcon
>> 
>> from Config import config  # Application settings enabled for Dev/Test/Prod
>> 
>> from api_common.middleware import AuthMiddleware, RequireJSON
>> from api_resources.account import AccountRegistrationResource, 
>> AccountPassword
>> ResetResource
>> 
>> from api_resources.users import UserProfileResource
>> 
>> fro m api_common import custom_logger
>> logger = custom_logger.setup_custom_logger('root')
>> logger.setLevel(config['log_level'])
>> 
>> logger.debug('Config: {}'.format(config))
>> 
>> api = application = falcon.API(middleware=[AuthMiddleware(), RequireJSON()])
>> 
>> # storage_path = '/usr/local/var/look'
>> # image_collection = images.Collection(storage_path)
>> # image = images.Item(storage_path)
>> 
>> # Routes
>> # api.add_route('/users', image_collection)
>> 
>> api.add_route('/account/registration', AccountRegistrationResource())
>> api.add_route('/account/password-reset/{email}', 
AccountPasswordResetResource())
>> api.add_route('/user/profile/{userid}', UserProfileResource())
>> 
>> 
>> # Useful for debugging problems in your API; works with pdb.set_trace()
>> if __name__ == '__main__':
>>    from wsgiref import simple_server
>> 
>>    host = "127.0.0.1"
>>    port = 8000
>>    httpd = simple_server.make_server(host, port, api)
>>    print("Serving on {}:{}".format(host, port))
>>    httpd.serve_forever()

Re: [falcon] POST request and question about IRC vs Gitter.im

From:
William Hayes
Date:
2015-10-05 @ 13:55
Figured it out.  I mistakenly thought that the JSON body was being read 
into req.context as a dictionary data structure or maybe integrated into 
req.params.  After stepping through the tutorials vs my code, it finally 
hit me, that this is being done by JSONTranslator which I hadn’t read 
through carefully before.

I’m still not sure what req.context is for.  I see it being used in the 
JSONTranslator middleware.  

I would definitely propose adding in a dedicated req.XXX variable that 
replicates the functionality of the process_request part of 
JSONTranslator.  Not sure if dumping out JSON automatically into the 
resp.body always makes sense.  Does it make sense to make the 
process_response part of JSONTranslator a dedicated convenience function?


> On Oct 4, 2015, at 5:17 AM, Andrew Stuart 
<andrew.stuart@supercoders.com.au> wrote:
> 
> If you are doing any web development you should learn to use ngrep.  It 
will show you traffic in real time on a given port. 
> 
> for example sudo ngrep -W byline -d lo port 80 will show what is 
happening on the HTTP port and you can have a close look at your request 
and see what is inside it.
> 
> 
> 
> 
> On 4 Oct 2015, at 12:19 pm, William Hayes <whayes@cekeeper.com 
<mailto:whayes@cekeeper.com>> wrote:
> 
> Thanks for the tip.  I’m either not using the right API call or 
something is filtering out my req object.  I think I can use either the 
req.context[‘email’] or the reg.get_param(‘email’) but both show up as 
empty when printing them or in the debugger.  I could be doing something 
wrong in the middleware.
> 
> Hopefully sleeping on it tonight will work, and it will be blindingly 
obvious tmrw.
> 
>> On Oct 3, 2015, at 8:42 PM, Andrew Stuart 
<andrew.stuart@supercoders.com.au> wrote:
>> 
>> A general tip is that it is easier to debug without try except - you’re
more likely to see the actual error.
>> 
>> Take out the try except and run your code again.
>> 
>> 
>> On 4 Oct 2015, at 10:39 am, William Hayes <whayes@cekeeper.com> wrote:
>> 
>> 
>>> On Oct 3, 2015, at 7:37 PM, William Hayes <william.s.hayes@gmail.com> wrote:
>>> 
>>> Hi all,
>>> 
>>> Easier and probably more contentious question (mostly because I’ve 
never figured out IRC) - what do you think about shifting to Gitter 
instead of IRC?  It has persistent chat, indicators as to who is core to 
the github project, private chats, email integration, search, …
>>> 
>>> Now my main question:
>>> 
>>> I’m having trouble getting POST data to my Resource.  I’d appreciate 
some ideas on what I’m doing wrong.  It looks like an empty return in the 
middleware is the right way to  break out of it (I want all routes 
authenticated except for two).  TIA!
>>> 
>>> My result: 
>>> HTTP/1.0 400 Bad Request
>>> Date: Sat, 03 Oct 2015 23:15:56 GMT
>>> Server: WSGIServer/0.2 CPython/3.4.3
>>> content-length: 106
>>> content-type: application/json
>>> testme: tester
>>> 
>>> {
>>>   "description": "Must submit email and password to create an account.",
>>>   "title": "Missing data"
>>> }
>>> 
>>> and debugging console output:
>>> Req:  None application/json {'USER-AGENT': 'HTTPie/0.9.2', 
'CONTENT-TYPE': 'application/json', 'HOST': 'localhost:8000', 'ACCEPT': 
'application/json', 'ACCEPT-ENCODING': 'gzip, deflate', 'CONNECTION': 
'keep-alive', 'CONTENT-LENGTH': '58’}
>>> 
>>> My httpie POST request:
>>> http --json POST http://localhost:8000/account/registration \
>>>   'Content-Type':'application/json' \
>>>   email="william.s.hayes@gmail.com" \
>>>   password=“test"
>>> 
>>> 
>>> My Registration resource:
>>> class AccountRegistrationResource(object):
>>>   """Accounts Resource - registration, password resets etc"""
>>> 
>>>   def on_post(self, req, resp):
>>>       print('Req: ', req.get_param('email'), req.content_type, req.headers)
>>>       try:
>>>           email = req.context['email']
>>>           plaintext_password = req.co
>>> ntext[
>>> 'password']
>>>       except KeyError:
>>>           raise falcon.HTTPBadRequest(
>>>               'Missing data',
>>>               'Must submit email and password to create an account.')
>>> 
>>>       hashed_pw = hashpw(plaintext_password, gensalt())
>>> 
>>>       # if hashpw(password_attempt, hashed) == hashed:
>>>       #     pri
>>> nt "It matches"
>>> 
>>>       # else:
>>>       #     print "It does not match"
>>> 
>>>       resp.body = ''
>>>       resp.status = falcon.HTTP_201
>>> 
>>> My middleware:
>>> import falcon
>>> import logging
>>> from .json_web_token 
>>> import 
>>> 
>>> JsonWebToken
>>> 
>>> logger = logging.getLogger('middleware')
>>> logger.setLevel(logging.DEBUG)
>>> 
>>> class AuthMiddleware(object):
>>> 
>>>   #
>>>   # TODO NOTE - think about remember me - via a cookie using 
itsdangerous for a self-describing cookie
>>>   #
>>>   # 1 Use a two-day expiration on the JWT
>>>   # 2 Store in secure cookie-brow
>>> ser only
>>> 
>>>   # 3 for critical access - change password, etc, check that the token
was iss ued within
>>>   #      last 30 min using a password to update - e.g. not a token 
auto-refresh
>>>   #
>>> 
>>>   def process_request(self, req, resp):
>>> 
>>>       resp.set_header('TESTME', 'tester')
>>> 
>>> 
>>> 
>>> # Don't authenticate following routes
>>>       skip_routes = ['/account/registration', '/account/reset-password']
>>>       if req.path in skip_routes:
>>>           print('Here')
>>>           return
>>> 
>>>       token = req.get_header('X-Auth-Token')
>>> 
>>>      & nbsp;logger.info('Path: {} Token: '.format(req.path))
>>>       print('Path: ', req.path)
>>> 
>>>       if token is None:
>>>           description = ('Please provide an auth token '
>>>                          'as part of the request.')
>>> 
>>>           raise falcon.HTTPUnauthorized('Auth token required',
>>> 
>>> 
>>> description,
>>>                                         href= 
'http://docs.example.com/auth' <http://docs.example.com/auth'>)
>>> 
>>>       if not self._token_is_valid(token, project):
>>>           description = ('The provided auth token is not valid. '
>>>                          'Please request a new token and try again.')
>>> 
>>>           raise 
>>> falcon.HTTPUnauthorize
>>> d(
>>> 'Authentication required',
>>>                                  &n bsp;      description,
>>>                                         
href='http://docs.example.com/auth' <http://docs.example.com/auth'>,
>>>                                         scheme='Token; UUID')
>>> 
>>>   def _token_is_valid(self, token, project):
>>>       return True  # Suuuuuure it's valid...
>>> 
>>> 
>>> class RequireJSON(object):
>>> 
>>>   def process_request(self , req, resp):
>>>       if not req.client_accepts_json:
>>>           raise falcon.HTTPNotAcceptable(
>>>               'This API only supports responses encoded as JSON.',
>>>               href='http://docs.examples.com/api/json' 
<http://docs.examples.com/api/json'>)
>>> 
>>>       if req.method in ('POST', 
>>> <
>>> span style="color:#008080;" class="">'PUT'
>>> ):
>>>           if 'application/json' not in req.content_type:
>>>          & nbsp;    raise falcon.HTTPUnsupportedMediaType(
>>>                   'This API only supports requests encoded as JSON.',
>>>                   href='http://docs.examples.com/api/json')
>>> My app.py:
>>> import falcon
>>> 
>>> from Config import config  # Application settings enabled for Dev/Test/Prod
>>> 
>>> from api_common.middleware import AuthMiddleware, RequireJSON
>>> from api_resources.account import AccountRegistrationResource, 
>>> AccountPassword
>>> ResetResource
>>> 
>>> from api_resources.users import UserProfileResource
>>> 
>>> fro m api_common import custom_logger
>>> logger = custom_logger.setup_custom_logger('root')
>>> logger.setLevel(config['log_level'])
>>> 
>>> logger.debug('Config: {}'.format(config))
>>> 
>>> api = application = falcon.API(middleware=[AuthMiddleware(), RequireJSON()])
>>> 
>>> # storage_path = '/usr/local/var/look'
>>> # image_collection = images.Collection(storage_path)
>>> # image = images.Item(storage_path)
>>> 
>>> # Routes
>>> # api.add_route('/users', image_collection)
>>> 
>>> api.add_route('/account/registration', AccountRegistrationResource())
>>> api.add_route('/account/password-reset/{email}', 
AccountPasswordResetResource())
>>> api.add_route('/user/profile/{userid}', UserProfileResource())
>>> 
>>> 
>>> # Useful for debugging problems in your API; works with pdb.set_trace()
>>> if __name__ == '__main__':
>>>   from wsgiref import simple_server
>>> 
>>>   host = "127.0.0.1"
>>>   port = 8000
>>>   httpd = simple_server.make_server(host, port, api)
>>>   print("Serving on {}:{}".format(host, port))
>>>   httpd.serve_forever()