sanic-jwt icon indicating copy to clipboard operation
sanic-jwt copied to clipboard

Is there an option to set strict_slashes=True to the sanic JWT blueprint?

Open gbnk0 opened this issue 7 years ago • 12 comments

Is there an option to set strict_slashes=True to the sanic JWT endpoints?

gbnk0 avatar Nov 28 '17 16:11 gbnk0

I tried to implement it to class_views in this pull request: https://github.com/ahopkins/sanic-jwt/pull/36

But i don't know how to implement it to the entire blueprint .

gbnk0 avatar Nov 29 '17 10:11 gbnk0

To do it, we would need to carry down a similar implementation to the routes in blueprint.py. I like the idea for sure to grab the settings.

I am pretty sure that it is a route by route implementation inside Sanic and not system wide configurable. I could be wrong though.

Something like this:

@bp.route('/', methods=['POST', 'OPTIONS'], strict_slashes=False)

Perhaps a nicer implementation would be to wrap the decorators into a new decorator that declares strict_slashes=app.config.SANIC_JWT_STRICT_SLASHES only one time.

ahopkins avatar Dec 06 '17 02:12 ahopkins

Yes there is a route by route implementation inside sanic, you think i can put directly in all blueprint.py routes like this?

@bp.route('/', methods=['POST', 'OPTIONS'], strict_slashes=app.config.SANIC_JWT_STRICT_SLASHES)

or like this:

bp_routes_config = {
    "strict_slashes": app.config.SANIC_JWT_STRICT_SLASHES
}

...

@bp.route('/', methods=['POST', 'OPTIONS'], **bp_routes_config)

And i see there is some strict_slashes changes in the latest sanic release:

https://github.com/channelcat/sanic/pull/1005

gbnk0 avatar Dec 06 '17 10:12 gbnk0

I confirm, in sanic v0.7 we can put a global strict_slashes=True, like this:

app = Sanic(strict_slashes=True)

But apparently it does not apply to blueprints

gbnk0 avatar Dec 06 '17 10:12 gbnk0

But apparently it does not apply to blueprints

Looks like the PR you referenced was merged into Sanic already. While your above approach would work (and was precisely what I was suggesting), it seems much more practical to manage this functionality app-wide and not just within this one module.

If adding strict_slashes inside Sanic() does not trickle down to the blueprints, then I suppose we need to also add it to blueprint.py

bp = Blueprint('auth_bp', strict_slashes=True)

ahopkins avatar Dec 06 '17 14:12 ahopkins

I merged your PR #36 in. I still think this is an open issue because:

  1. We need to add it into the documentation.
  2. There is still not a 100% elegant solution that applies consistently to all views.

ahopkins avatar Jan 02 '18 08:01 ahopkins

Ok thanks, i know it's not a pretty solution, i'll look at it when i 'll have more time.

gbnk0 avatar Jan 03 '18 10:01 gbnk0

Do you think we can do some modifications for initializing the auth blueprint like in the sanic-openapi library:

from sanic_jwt import auth_bp
app.blueprint(auth_bp)

?

gbnk0 avatar Jan 04 '18 16:01 gbnk0

What is the motivation for this? Not saying it isn't possible, just wanting to know what the reason would be.

Its hidden inside the initialize method just to control the order in which things are attached to the module. You certainly do not NEED to use it. And, you could replicate some of the logic there. Maybe this should be a separate issue thread.

ahopkins avatar Jan 04 '18 18:01 ahopkins

Please, add sanic-openapi to blueprint.

affmaker avatar Jan 14 '18 14:01 affmaker

@ahopkins I've been working in getting sanic-jwt to work with sanic-openapi, as requested by @affmaker also. I was able to make the protected decorator work with the provided example from sanic-openapi, but some of the sanic-jwt tests fails to run (function vs coroutine objects).

I was able to isolate the problem in this simple sanic + sanic-jwt example:

from sanic import Sanic
from sanic.blueprints import Blueprint
from sanic.response import json
from sanic_jwt import initialize
from sanic_jwt.decorators import protected

blueprint = Blueprint('Test', '/test')


@blueprint.get("/", strict_slashes=True)
@protected()
def protected_hello_world(request):
    return json({'message': 'hello world'})


async def authenticate(request, *args, **kwargs):
    return {'user_id': 1}


app = Sanic()

app.blueprint(blueprint)

initialize(
    app,
    authenticate=authenticate,
)

app.run(host="0.0.0.0", debug=True)

Calling up:

$ curl -X POST -H "Content-Type: application/json" -d '{"username": "a", "password": "b"}' http://localhost:8000/auth
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1MTY0ODQ1MjF9.NGtDF18RTXPOkvK56XssmqnGcRIF3Yj37q0K-tCxbLc"}

$ curl -X GET "http://localhost:8000/test/" -H  "accept: application/json" -H  "content-type: application/json" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1MTY0ODQ1MjF9.NGtDF18RTXPOkvK56XssmqnGcRIF3Yj37q0K-tCxbLc"

    <html>
        <head>

[...]

Server output [truncated]:

[2018-01-20 19:12:12 -0200] [5355] [ERROR] Traceback (most recent call last):
  File "/opt/pyenv/versions/sanic-test-3.6.4/lib/python3.6/site-packages/sanic/app.py", line 556, in handle_request
    response = await response
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 110, in __next__
    return self.gen.send(None)
  File "/home/richard/work/personal/sanic-jwt/sanic_jwt/decorators.py", line 46, in decorated_function
    return await f(request, *args, **kwargs)
TypeError: object HTTPResponse can't be used in 'await' expression

[2018-01-20 19:12:12 -0200] [5355] [ERROR] Exception occurred while handling uri: "http://localhost:8000/test/"
Traceback (most recent call last):
  File "/opt/pyenv/versions/sanic-test-3.6.4/lib/python3.6/site-packages/sanic/app.py", line 556, in handle_request
    response = await response
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 110, in __next__
    return self.gen.send(None)
  File "/home/richard/work/personal/sanic-jwt/sanic_jwt/decorators.py", line 46, in decorated_function
    return await f(request, *args, **kwargs)
TypeError: object HTTPResponse can't be used in 'await' expression

[2018-01-20 19:12:12 -0200] - (sanic.access)[INFO][1:2]: GET http://localhost:8000/test/  500 2521

Basically, removing await from callback responses from the protected decorator seems to partially solve this problem, but it breaks the tests and is not elegant or a solution. I'm no sanic expert, but I'll look deeper into since I think there should be a simple solution for that (and because I'm also stubborn, lol).

vltr avatar Jan 20 '18 21:01 vltr

Ha! I think the situation described above is fixed, check my latest push. It worked in the example given and with sanic-openapi :wink: Also, all unit tests worked like a charm!

vltr avatar Jan 20 '18 21:01 vltr