Examples¶
Adding POST Functionality¶
If we wanted to add a second handler to enable users to post data to our simple server, you might implement something similar to this:
Simple Web App with POST
Let's then check what happens:
% curl http://localhost:8000
Hello, Dave!
% curl http://localhost:8000/ -d '{"name": "Tim"}'
Success
% curl http://localhost:8000
Hello, Dave!
You might be confused to see that the name that is greeted hasn't changed! This is because all of the handlers are initiased with variables when the server is first launched, and so our GET at http://localhost:8000/ never looks outside its handler to see if anything has changed.
The solution to this problem is to store a variable that could change in our app's context: app.ctx.name = "..."
. If you make the changes below and then re-run the curl
statements, you should see that the app now changes the name it greets.
Simple Web App with POST...Fixed!
from sanic import Sanic
from sanic.response import text, HTTPResponse
from sanic.request import Request
app = Sanic("hello-world-app")
app.ctx.name = "Dave"
@app.get("/")
async def hello(request: Request) -> HTTPResponse:
return text(f"Hello, {app.ctx.name}!\n")
@app.route("/", methods=["POST"])
async def hello_post(request: Request) -> HTTPResponse:
app.ctx.name = request.json['name']
return text("Success\n")
Annotating Your Code¶
It is important to type-annotate your code to catch type bugs before release, and for better legibility. Here is a copy of the simple web app with type-hinting:
Simple Web App with Type Hinting
Testing Sanic Applications¶
Sanic Testing is a testing client for Sanic. It primarily powers the tests of the Sanic project itself. It can be installed running:
Once sanic-testing
is in the environment, there is nothing you need to do to use it.
Sync Test¶
Simply access the test_client
property on your application instance:
import pytest
from sanic import Sanic, response
@pytest.fixture
def app():
sanic_app = Sanic("TestSanic")
@sanic_app.get("/")
def basic(request):
return response.text("foo")
return sanic_app
def test_basic_test_client(app):
request, response = app.test_client.get("/")
assert request.method.lower() == "get"
assert response.body == b"foo"
assert response.status == 200
Async Test¶
The async test client in pytest needs to be installed:
Async tests require accessing the asgi_client
property on your application instance.
import pytest
from sanic import Sanic, response
@pytest.fixture
def app():
sanic_app = Sanic(__name__)
@sanic_app.get("/")
def basic(request):
return response.text("foo")
return sanic_app
@pytest.mark.asyncio
async def test_basic_asgi_client(app):
request, response = await app.asgi_client.get("/")
assert request.method.lower() == "get"
assert response.body == b"foo"
assert response.status == 200
Further Reading¶
For further information on Sanic, please refer to their documentation.