dream/servers/mist/server
Your Dream app’s entry point
This module is where your web application starts. It provides a builder pattern for configuring and starting a Dream server using Mist (the BEAM’s HTTP server).
Quick Start
import dream/servers/mist/server.{listen, router}
pub fn main() {
server.new()
|> router(create_router())
|> listen(3000)
}
The builder pattern lets you configure your server step by step. Start with new(),
add your router, and optionally set custom context and services before calling listen().
Custom Context and Services
By default, Dream uses EmptyContext (no per-request data) and EmptyServices (no shared
dependencies). For most production apps, you’ll want to define your own types:
import dream/servers/mist/server.{context, listen, router, services}
import gleam/option.{None}
pub type MyContext {
MyContext(request_id: String, user: option.Option(User), session: Session)
}
server.new()
|> context(MyContext(request_id: "", user: None, session: empty_session()))
|> services(initialize_services())
|> router(create_router())
|> listen(3000)
The type system ensures your controllers receive the correct context type.
Values
pub fn bind(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
),
interface: String,
) -> dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
)
Set the network interface to bind to
Defaults to binding to all interfaces. Use “localhost” or “127.0.0.1” to only accept local connections, or “0.0.0.0” to accept connections from any network interface.
Example
// Only accept local connections
dream.new()
|> dream.services(my_services)
|> dream.router(my_router)
|> dream.bind("localhost")
|> dream.listen(3000)
pub fn context(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
a,
old_services,
),
new_context: context,
) -> dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
old_services,
)
Set a custom context type for your application
Use this to replace AppContext with your own context type that holds
user authentication, session data, or any other per-request information.
The type system tracks your context through middleware and controllers.
Example
pub type MyContext {
MyContext(request_id: String, user: Option(User))
}
dream.new()
|> dream.context(MyContext(request_id: "", user: None))
|> dream.services(my_services)
|> dream.router(my_router)
|> dream.listen(3000)
pub fn listen(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
),
port: Int,
) -> Nil
Start the server and listen for requests
Starts the server on the specified port and blocks forever. This is what you call
in your main() function. If the server fails to start, it returns Nil immediately.
This function will panic if you haven’t called router() and services() first—
you can’t run a web server without defining what it does.
Example
pub fn main() {
dream.new()
|> dream.services(initialize_services())
|> dream.router(create_router())
|> dream.listen(3000)
}
pub fn listen_without_blocking(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
),
port: Int,
) -> Nil
Start the server without blocking
Like listen(), but returns immediately instead of blocking forever. Useful for
tests where you need the server running in the background so you can make requests to it.
Example
pub fn test_server() {
// Start server in background
dream.new()
|> dream.services(test_services())
|> dream.router(test_router())
|> dream.listen_without_blocking(8080)
// Make test requests
let response = http_client.get("http://localhost:8080/test")
// ... assertions ...
}
pub fn max_body_size(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
),
size: Int,
) -> dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
)
Set maximum request body size in bytes
Requests with bodies larger than this will be rejected. Default is effectively unlimited (max 64-bit int). Set a reasonable limit to protect against memory exhaustion.
Example
// Limit request bodies to 10MB
dream.new()
|> dream.services(my_services)
|> dream.router(my_router)
|> dream.max_body_size(10_000_000)
|> dream.listen(3000)
pub fn new() -> dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context.EmptyContext,
router.EmptyServices,
)
Create a new Dream server with defaults
Returns a server configured with EmptyContext (no per-request data) and
EmptyServices (no dependencies). For simple applications, you only need to add
a router. For more complex apps, use context() and services() to provide your
own types before calling listen().
Simple Example (no context or services)
import dream/servers/mist/server.{listen, router}
server.new()
|> router(my_router)
|> listen(3000)
With Custom Context and Services
import dream/servers/mist/server.{context, listen, router, services}
import gleam/option.{None}
server.new()
|> context(MyContext(request_id: "", user: None))
|> services(my_services)
|> router(my_router)
|> listen(3000)
pub fn router(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
),
router_instance: router.Router(context, services),
) -> dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
)
Provide your application’s router
The router defines which controllers handle which requests. It must be configured with the same context and services types you’ve set up, which the type system enforces.
Example
pub fn create_router() -> Router(MyContext, Services) {
router.new
|> router.get("/", controllers.index)
|> router.get("/users/:id", controllers.show_user)
}
dream.new()
|> dream.services(initialize_services())
|> dream.router(create_router())
|> dream.listen(3000)
pub fn services(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
old_context,
router.EmptyServices,
),
services_instance: services,
) -> dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
old_context,
services,
)
Provide your application’s services
Services are shared dependencies available to all requests—database connections, HTTP clients, caches, etc. Define a type that holds all your services and pass it here.
Example
pub type Services {
Services(db: Connection, cache: Cache)
}
pub fn initialize_services() -> Services {
let db = connect_to_database()
let cache = create_cache()
Services(db: db, cache: cache)
}
dream.new()
|> dream.services(initialize_services())
|> dream.router(my_router)
|> dream.listen(3000)