Skip to content

Nebula - 3.2.0

Choose a tag to compare

@VxidDev VxidDev released this 01 Apr 16:37

Nebula 3.2.0 - Release Notes

What’s New

⚠️ Middleware System Update (Major)

Nebula now supports composable middleware at two levels:

  • Global ASGI Middleware - wraps the entire application
  • Route-level Middleware - applied per route or RouteGroup

This enables fine-grained control over request handling while maintaining full ASGI compatibility.


Middleware

Middleware in Nebula follows the ASGI pattern:

class BaseMiddleware:
    def __init__(self, app):
        self.app = app

    async def __call__(self, scope, receive, send):
        await self.app(scope, receive, send)

Middleware is applied using the Middleware wrapper:

class Middleware:
    def __init__(self, middleware_cls: type, **options):
        self.middleware_cls = middleware_cls
        self.options = options

    def build(self, app):
        return self.middleware_cls(app, **self.options)

🌍 Global Middleware

Global middleware wraps the entire application:

app = Nebula(
    middlewares=[
        Middleware(LoggingMiddleware)
    ]
)

🧩 Route & Group Middleware

Middleware can now be applied per route or route group:

api = app.group(
    "/api",
    middlewares=[
        Middleware(APILoggerMiddleware)
    ]
)

Route-level middleware can also be passed directly:

@api.get("/greet/{name}", route_middlewares=[...])
async def greet(name: str):
    return {"greeting": f"Hi, {name}!"}

⚠️ Important Behavior

  • Middleware is applied in stacked order
  • Global middleware runs before group middleware
  • Route-specific middleware runs last
  • Middleware is composed per request, not statically wrapped at the app level

RouteGroup

RouteGroup is now a first-class abstraction for organizing routes and applying scoped middleware.

It allows you to:

  • Group routes under a shared prefix
  • Attach middleware to a logical section of your app
  • Keep code modular and maintainable

Example

api = app.group(
    "/api",
    middlewares=[
        Middleware(APILoggerMiddleware)
    ]
)

@api.get("/greet/{name}")
async def greet(name: str):
    return {"greeting": f"Hi, {name}!"}

⚠️ Behavior Note

  • RouteGroup does not wrap the ASGI app directly

  • Instead, its middleware is composed into the request pipeline

  • This ensures:

    • correct routing behavior
    • full compatibility with ASGI
    • no unintended global side effects

Middleware Execution Order

For a request, middleware is executed in this order:

  1. Global middleware (outermost)
  2. Group middleware
  3. Route middleware
  4. Route handler

This creates a predictable and composable execution pipeline.