Sanic: support regex routes in routing

Created on 28 May 2017  Â·  4Comments  Â·  Source: sanic-org/sanic

I read sanic's docs, but didn't find a way to add regex routes. Since add_route only support simple regex like routes with parameters, which can not work in complex cases.

app.add_route(person_handler2, '/person/<name:[A-z]>', methods=['GET'])

For example, i want to add a route to match all url, this can be done easily by add a regex route /^.* in Django or Tornado.

I use below code to hack this issue, but this is not elegant. If add_route method support regex route directly would be better?

import re

from sanic import Sanic
from sanic.response import json
from sanic.router import Route


async def test(request):
    print(request.url)
    return json({"hello": "world"})


async def test_foo(request):
    print(request.url)
    return json({"foo": "bar"})


def main():
    app = Sanic()
    route = Route(
        handler=test_foo, methods=['GET', 'POST'],
        pattern=re.compile(r'^/foo/?$'),
        parameters='', name=None, uri=None)
    app.router.routes_always_check.append(route)

    route = Route(
        handler=test, methods=['GET', 'POST'],
        pattern=re.compile(r'^/.*'),
        parameters='', name=None, uri=None)
    app.router.routes_always_check.append(route)

    app.run(host="127.0.0.1", debug=True, port=8000)


if __name__ == "__main__":
    main()

Most helpful comment

Sanic does support regex.

The simplest and most common case is using <argument:path>:

from sanic import Sanic, response

app = Sanic('test')

@app.route('/static/<filename:path>')
async def static(request, filename):
    return response.text(filename)


@app.route('/slash/<path:[^/].*?>')
async def slash(request, path):
    return response.text(path)


@app.route('/noslash/<name:.*>')
async def noslash(request, name):
    return response.text(name)

Try this with
http://127.0.0.1:8000/static/js/main.js
http://127.0.0.1:8000/slash/a/s/d/f.gif
http://127.0.0.1:8000/noslash/robots.txt

All 4 comments

Sanic does support regex.

The simplest and most common case is using <argument:path>:

from sanic import Sanic, response

app = Sanic('test')

@app.route('/static/<filename:path>')
async def static(request, filename):
    return response.text(filename)


@app.route('/slash/<path:[^/].*?>')
async def slash(request, path):
    return response.text(path)


@app.route('/noslash/<name:.*>')
async def noslash(request, name):
    return response.text(name)

Try this with
http://127.0.0.1:8000/static/js/main.js
http://127.0.0.1:8000/slash/a/s/d/f.gif
http://127.0.0.1:8000/noslash/robots.txt

@pyx thanks, this works for me.

Closing thanks to @pyx!

For those also visiting this issue...
If your path contains a variable amount of / slashes then @restran solution with app.router.routes_always_check is still the only one that works if you want to match .* urls.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

1067511899 picture 1067511899  Â·  3Comments

litelife picture litelife  Â·  3Comments

davidtgq picture davidtgq  Â·  3Comments

sirex picture sirex  Â·  4Comments

vlad0337187 picture vlad0337187  Â·  3Comments