dream/context

Request context for your application

Context holds per-request data that changes with every request—user authentication, session info, request IDs, etc. It’s passed to every middleware and controller.

Empty Context

For simple applications that don’t need per-request context, Dream defaults to EmptyContext. You don’t need to set it explicitly:

import dream/servers/mist/server.{listen, router}

server.new()
|> router(my_router)
|> listen(3000)

If you need to explicitly set EmptyContext (e.g., replacing a previously set context):

import dream/context.{type EmptyContext, EmptyContext}
import dream/servers/mist/server.{context, listen, router}

server.new()
|> context(EmptyContext)
|> router(my_router)
|> listen(3000)

App Context

Dream also provides AppContext with a request_id field. Use this if you want basic request tracking but don’t need custom context yet:

import dream/context.{type AppContext, AppContext}
import dream/servers/mist/server.{context, listen, router}

server.new()
|> context(AppContext(request_id: ""))
|> router(my_router)
|> listen(3000)

Most applications will eventually want their own custom context type.

Custom Context

Define your own context type to hold whatever per-request data you need:

import gleam/option.{None}

pub type MyContext {
  MyContext(
    request_id: String,
    user: option.Option(User),
    session: Session,
    permissions: List(String),
  )
}

Then pass it to your server:

import dream/servers/mist/server.{context, listen, router, services}

server.new()
|> context(MyContext(
     request_id: "",
     user: None,
     session: empty_session(),
     permissions: [],
   ))
|> services(my_services)
|> router(my_router)
|> listen(3000)

Enriching Context in Middleware

Middleware can update the context as requests flow through:

import dream/http/request.{type Request}
import dream/http/response.{type Response, text_response}
import dream/http/status.{unauthorized}
import gleam/option.{Some}

pub fn auth_middleware(
  request: Request,
  context: MyContext,
  services: Services,
  next: fn(Request, MyContext, Services) -> Response,
) -> Response {
  case extract_token(request) {
    Ok(token) -> {
      let user = verify_token(services.db, token)
      let new_context = MyContext(..context, user: Some(user))
      next(request, new_context, services)
    }
    Error(_) -> text_response(unauthorized, "Authentication required")
  }
}

The type system ensures your controllers receive the right context type.

Types

Default context with just a request ID

Use this for simple applications or replace it with your own context type. Most real applications will want custom context for user data, sessions, etc.

pub type AppContext {
  AppContext(request_id: String)
}

Constructors

  • AppContext(request_id: String)

Placeholder for when you don’t need context

Use this when you’re building a simple application that doesn’t need per-request context like user sessions or authentication. For anything more complex, define your own context type.

pub type EmptyContext {
  EmptyContext
}

Constructors

  • EmptyContext

Values

pub fn new_context(request_id: String) -> AppContext

Create a new AppContext

Helper for creating the default context. If you’re using a custom context, you’ll create it directly without this function.

Search Document