sanic-org / sanic

Accelerate your web app development | Build fast. Run fast.

Home Page:https://sanic.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Sanic 22.12.0 Unable to use Blueprint

x-haose opened this issue · comments

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I use sanic 22.12.0 version, but Unable to use Blueprint, 404 appeared when accessing the blueprint url. this is code:

from sanic import Sanic, Blueprint, text

app = Sanic(name="test")

test_bp = Blueprint('test', url_prefix='/test')


@app.get('/')
def index(r):
    return text("server")


@test_bp.get("/hello")
def hello(r):
    return text("xxx")


def main():
    api_blueprint = Blueprint.group(url_prefix="/api")
    api_blueprint.append(test_bp)
    app.blueprint(api_blueprint)
    app.run(port=5277, debug=True)


if __name__ == '__main__':
    main()

output:

/home/haose/codes/sanic_test/.venv/bin/python /opt/apps/pycharm-2022.2.2/plugins/python/helpers/pydev/pydevd.py --multiprocess --qt-support=auto --client 127.0.0.1 --port 38525 --file /home/haose/codes/sanic_test/server.py 
Connected to pydev debugger (build 222.4345.23)
[2023-01-06 10:38:18 +0800] [5678] [DEBUG] 
                 Sanic
         Build Fast. Run Fast.
[2023-01-06 10:38:18 +0800] [5678] [INFO] Sanic v22.12.0
[2023-01-06 10:38:18 +0800] [5678] [INFO] Goin' Fast @ http://127.0.0.1:5277
[2023-01-06 10:38:18 +0800] [5678] [INFO] mode: debug, single worker
[2023-01-06 10:38:18 +0800] [5678] [INFO] server: sanic, HTTP/1.1
[2023-01-06 10:38:18 +0800] [5678] [INFO] python: 3.10.7
[2023-01-06 10:38:18 +0800] [5678] [INFO] platform: Linux-5.10.0-amd64-desktop-x86_64-with-glibc2.28
[2023-01-06 10:38:18 +0800] [5678] [INFO] packages: sanic-routing==22.8.0
[2023-01-06 10:38:19 +0800] [5678] [DEBUG] Creating multiprocessing context using 'spawn'
[2023-01-06 10:38:19 +0800] [5678] [DEBUG] Starting a process: Sanic-Server-0-0
[2023-01-06 10:38:19 +0800] [5708] [DEBUG] Process ack: Sanic-Server-0-0 [5708]
[2023-01-06 10:38:19 +0800] [5708] [INFO] Starting worker [5708]
[2023-01-06 10:38:21 +0800] - (sanic.access)[INFO][127.0.0.1:39886]: GET http://127.0.0.1:5277/api/test/hello  404 740
[2023-01-06 10:38:22 +0800] - (sanic.access)[INFO][127.0.0.1:39886]: GET http://127.0.0.1:5277/api/test/hello  404 740
[2023-01-06 10:38:26 +0800] [5708] [DEBUG] KeepAlive Timeout. Closing connection.
[2023-01-06 10:38:29 +0800] [5708] [DEBUG] KeepAlive Timeout. Closing connection.
[2023-01-06 10:38:54 +0800] - (sanic.access)[INFO][127.0.0.1:40512]: GET http://127.0.0.1:5277/  200 6
[2023-01-06 10:38:59 +0800] [5708] [DEBUG] KeepAlive Timeout. Closing connection.
[2023-01-06 10:38:59 +0800] [5708] [DEBUG] KeepAlive Timeout. Closing connection.

package:

╭───────────────┬─────────┬──────────╮
│ name          │ version │ location │
├───────────────┼─────────┼──────────┤
│ aiofiles      │ 22.1.0  │          │
│ httptools     │ 0.5.0   │          │
│ uvloop        │ 0.17.0  │          │
│ websockets    │ 10.4    │          │
│ multidict     │ 6.0.4   │          │
│ ujson         │ 5.6.0   │          │
│ sanic-routing │ 22.8.0  │          │
│ sanic         │ 22.12.0 │          │
╰───────────────┴─────────┴──────────╯

Code snippet

No response

Expected Behavior

No response

How do you run Sanic?

As a script (app.run or Sanic.serve)

Operating System

Linux

Sanic Version

22.12.0

Additional context

No response

When I add the parameter single_process=True in app.run(...), I found that the URL of the blueprint can be accessed. Is this caused by Worker Manager? how do i use it

It is because the "if" block only runs in the main process. So none of your sub processes know that it is attaching. The main block should ONLY be used for running the server.

It is because the "if" block only runs in the main process. So none of your sub processes know that it is attaching. The main block should ONLY be used for running the server.

Thank you very much for your reply, but if I want to run it without adding single_process=True parameter, what is the correct way to do it?

You have a couple options. I'd suggest you make main a proper factory. With minimal changes to your code:

from sanic import Blueprint, Sanic, text

app = Sanic(name="test")

test_bp = Blueprint("test", url_prefix="/test")


@app.get("/")
def index(r):
    return text("server")


@test_bp.get("/hello")
def hello(r):
    return text("xxx")


def main():
    api_blueprint = Blueprint.group(url_prefix="/api")
    api_blueprint.append(test_bp)
    app.blueprint(api_blueprint)
    return app

Of course, to make it a TRUE factory, then main would also create the app instance too.

Once you have that, you should be able to run this from the CLI.

sanic path.to.server:main --factory --debug --port=5277

If you want to run it as a script, and do the attaching of the blueprint in a function, then you need to use an AppLoader.

from sanic.worker.loader import AppLoader

if __name__ == "__main__":
    loader = AppLoader(factory=main)
    app = loader.load()
    app.prepare(port=5277, debug=True)
    Sanic.serve(app, app_loader=loader)

You have a couple options. I'd suggest you make main a proper factory. With minimal changes to your code:

from sanic import Blueprint, Sanic, text

app = Sanic(name="test")

test_bp = Blueprint("test", url_prefix="/test")


@app.get("/")
def index(r):
    return text("server")


@test_bp.get("/hello")
def hello(r):
    return text("xxx")


def main():
    api_blueprint = Blueprint.group(url_prefix="/api")
    api_blueprint.append(test_bp)
    app.blueprint(api_blueprint)
    return app

Of course, to make it a TRUE factory, then main would also create the app instance too.

Once you have that, you should be able to run this from the CLI.

sanic path.to.server:main --factory --debug --port=5277

If you want to run it as a script, and do the attaching of the blueprint in a function, then you need to use an AppLoader.

from sanic.worker.loader import AppLoader

if __name__ == "__main__":
    loader = AppLoader(factory=main)
    app = loader.load()
    app.prepare(port=5277, debug=True)
    Sanic.serve(app, app_loader=loader)

Thank you very much for your help, it solved my problem perfectly