Skip to content

Applications

Lilya brings a class called Lilya which wraps all the functionality of the application.

from lilya.apps import Lilya

There are many ways of creating a Lilya application but:

from lilya.apps import Lilya
from lilya.requests import Request
from lilya.responses import Ok
from lilya.routing import Path, WebSocketPath
from lilya.websockets import WebSocket


async def homepage():
    return Ok({"message": "Hello, world!"})


async def me():
    username = "John Doe"
    return Ok({"message": f"Hello, {username}!"})


def user(request: Request):
    username = request.path_params["username"]
    return Ok({"message": f"Hello, {username}!"})


async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    await websocket.send_text("Hello, websocket!")
    await websocket.close()


def startup():
    print("Up up we go!")


routes = [
    Path("/home", handler=homepage),
    Path("/me", handler=me),
    Path("/user/{username}", handler=user),
    WebSocketPath("/ws", handler=websocket_endpoint),
]

app = Lilya(routes=routes, on_startup=[startup])
from lilya.apps import Lilya
from lilya.requests import Request
from lilya.responses import Ok
from lilya.routing import Include, Path, WebSocketPath
from lilya.websockets import WebSocket


async def homepage():
    return Ok({"message": "Hello, world!"})


async def me():
    username = "John Doe"
    return Ok({"message": f"Hello, {username}!"})


def user(request: Request):
    username = request.path_params["username"]
    return Ok({"message": f"Hello, {username}!"})


async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    await websocket.send_text("Hello, websocket!")
    await websocket.close()


def startup():
    print("Up up we go!")


routes = [
    Include(
        "/",
        routes=[
            Path("/home", handler=homepage),
            Path("/me", handler=me),
            Path("/user/{username}", handler=user),
            WebSocketPath("/ws", handler=websocket_endpoint),
        ],
    )
]

app = Lilya(routes=routes, on_startup=[startup])

Testing using curl

$ curl -X GET http://localhost:8000/user/lilya

Create an instance of an application

Creating an appliation instance can be done in different ways and with a great plus of using the settings for a cleaner approach.

Parameters:

  • debug - Boolean indicating if a debug tracebacks should be returns on errors. Basically, debug mode, very useful for development.
  • settings_module - A settings instance or class definition from where the settings values will be read.
  • routes - A list of routes to serve incoming HTTP and WebSocket requests. A list of Path, WebSocketPath, Include and Host. requests (HTTP and Websockets).
  • permissions - A list of permissions to serve the application incoming requests (HTTP and Websockets).
  • middleware - A list of middleware to run for every request. The middlewares can be subclasses of the MiddlewareProtocol.
  • exception_handlers - A dictionary of exception types (or custom exceptions) and the handler functions on an application top level. Exception handler callables should be of the form of handler(request, exc) -> response and may be be either standard functions, or async functions.
  • on_shutdown - A list of callables to run on application shutdown. Shutdown handler callables do not take any arguments, and may be be either standard functions, or async functions.
  • on_startup - A list of callables to run on application startup. Startup handler callables do not take any arguments, and may be be either standard functions, or async functions.
  • lifepan - The lifespan context function is a newer style that replaces on_startup / on_shutdown handlers. Use one or the other, not both.
  • include_in_schema - Boolean flag to indicate if should be schema included or not. This can be useful if you are depracating a whole Included Lilya application in favour of a new one. The flag should indicate that all the paths should be considered deprecated.
  • redirect_slashes - Flag to enable/disable redirect slashes for the handlers. It is enabled by default.

Application settings

Settings are another way of controlling the parameters passed to the Lilya object when instantiating. Check out the settings for more details and how to use it to power up your application.

To access the application settings there are different ways:

from lilya.apps import Lilya
from lilya.requests import Request
from lilya.routing import Path


async def app_debug(request: Request):
    settings = request.app.settings
    return {"debug": settings.debug}


app = Lilya(routes=[Path("/", app_debug)])
from lilya.apps import Lilya
from lilya.conf import settings
from lilya.routing import Path


async def app_debug():
    return {"debug": settings.debug}


app = Lilya(routes=[Path("/", app_debug)])

State and application instance

You can store arbitraty extra state on the application instance using the state attribute.

Example:

from lilya.apps import Lilya

app = Lilya()

app.state.ADMIN = "admin@lilya.dev"

Accessing the application instance

The application instance is always available via request or via context.

Example

from lilya.apps import Lilya
from lilya.requests import Request
from lilya.context import Context
from lilya.routing import Path


# For request
def home_request(request: Request):
    app = request.app
    return {"message": "Welcome home"}


# For context
def home_context(context: Context):
    app = context.app
    return {"message": "Welcome home"}


app = Lilya(routes=[
        Path("/request", home_request),
        Path("/context", home_context),
    ]
)