# Middlewares

This makes middleware useful for authentication, logging, rate limiting, request checks, response modification, and other reusable request/response logic.

## What is Middleware?

A middleware function sits between the incoming request and your route handler.

It receives two arguments:

* `request` — the incoming request object
* `call_next` — a function that continues execution to the next middleware or route handler

```python
//! middleware-signature

def middleware(request, call_next):
    response = call_next(request)
    return response
```

If the middleware calls `call_next(request)`, the request continues to the route handler. If it returns a response directly, the route handler is skipped.

## Basic Middleware Example

The following middleware prints the request method and path before allowing the request to continue.

```python
//! basic-middleware

def logger_middleware(request, call_next):
    print(f"{request.method} {request.path}")
    return call_next(request)
```

You can apply it to a route using the `middlewares` argument.

```python
//! apply-basic-middleware

@app.route("/hello", methods=["GET"], middlewares=[logger_middleware])
def hello(request):
    return {"message": "Hello from Slush"}
```

When `/hello` is requested, the middleware runs first, then the route handler runs.

## Authentication Middleware

Middleware is commonly used to protect routes.

{% code title="auth-middleware.py" %}

```python
from slush.core.response import Response


def auth_middleware(request, call_next):
    token = request.headers.get("Authorization")

    if token != "Bearer secret-token":
        return Response(
            {"error": "Unauthorized"},
            status=401,
            headers=[("Content-Type", "application/json")],
        )

    return call_next(request)
```

{% endcode %}

Now you can apply this middleware only to routes that need authentication.

```python
@app.route("/profile", methods=["GET"], middlewares=[auth_middleware])
def profile(request):
    return {"message": "This is a protected route"}
```

If the request does not include the correct token, the route handler will not run.

## Public and Protected Routes

Since middleware is applied per route, you can keep some endpoints public and protect others.

```python
//! public-and-protected

@app.route("/public", methods=["GET"])
def public(request):
    return {"message": "This route is public"}


@app.route("/dashboard", methods=["GET"], middlewares=[auth_middleware])
def dashboard(request):
    return {"message": "Welcome to the dashboard"}
```

In this example:

* `/public` does not use middleware
* `/dashboard` uses `auth_middleware`

This gives you precise control over which routes are protected.

## Multiple Middleware Functions

A route can use more than one middleware.

```python
//! multiple-middlewares

def logger_middleware(request, call_next):
    print(f"Incoming request: {request.method} {request.path}")
    return call_next(request)


def auth_middleware(request, call_next):
    token = request.headers.get("Authorization")
    if token != "Bearer secret-token":
        return {"error": "Unauthorized"}
    return call_next(request)


@app.route(
    "/secure",
    methods=["GET"],
    middlewares=[logger_middleware, auth_middleware],
)
def secure(request):
    return {"message": "Secure data"}
```

Middleware runs in the order it is listed.

For the example above, the flow is:

```
//! middleware-flow

logger_middleware → auth_middleware → route handler
```

On the way back, the response returns through the middleware chain in reverse order.

## Stopping a Request Early

A middleware can stop the request before it reaches the route handler by returning a response directly.

```python
//! stop-request

from slush.core.response import Response


def block_middleware(request, call_next):
    return Response({"error": "Blocked"}, status=403)


@app.route("/blocked", methods=["GET"], middlewares=[block_middleware])
def blocked(request):
    return {"message": "This will not run"}
```

In this case, the route handler is never executed because the middleware returns a response immediately.

## Middleware with Routers

Middleware also works with modular routers.

```python
//! router-middleware

from slush.core.routing import Router
from slush.core.response import Response

user_router = Router()


def auth_middleware(request, call_next):
    token = request.headers.get("Authorization")
    if token != "Bearer secret-token":
        return Response({"error": "Unauthorized"}, status=401)
    return call_next(request)


@user_router.route("/<int:id>", methods=["GET"], middlewares=[auth_middleware])
def get_user(id, request):
    return {"user_id": id}
```

Then mount the router in your application.

```python
//! add-router

app.add_router(user_router, prefix="/users")
```

The final route becomes:

```
//! final-router-path

/users/1
```

and it will use the middleware defined on the router route.

## Modifying the Response

Middleware can also modify a response after the route handler has executed.

```python
//! modify-response

def powered_by_middleware(request, call_next):
    response = call_next(request)
    response.set_header("X-Powered-By", "Slush")
    return response


@app.route("/hello", methods=["GET"], middlewares=[powered_by_middleware])
def hello(request):
    return {"message": "Hello"}
```

This is useful for adding headers, measuring response time, or applying shared response behavior.

## Timing Middleware Example

You can measure how long a route takes to execute.

```python
//! timing-middleware

import time


def timing_middleware(request, call_next):
    start = time.time()
    response = call_next(request)
    duration = time.time() - start
    response.set_header("X-Response-Time", f"{duration:.4f}s")
    return response
```

Apply it to a route:

```python
//! timing-route

@app.route("/slow", methods=["GET"], middlewares=[timing_middleware])
def slow(request):
    return {"message": "Done"}
```

## Summary

Middleware in Slush gives you a clean way to reuse request and response logic.

You can use middleware to:

* protect routes with authentication
* log incoming requests
* block requests early
* modify response headers
* measure response time
* apply route-specific behavior
* combine multiple reusable logic layers

Middleware is applied per route, so your application remains explicit and easy to control.

## Next Steps

* Learn how to use the **Response object**


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://slush.gitbook.io/docs/documentation/basics/middlewares.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
