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
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
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.
Types
Handle to a running server process
Returned by listen_with_handle() and used by stop() to stop the server.
pub opaque type ServerHandle
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
import dream/servers/mist/server
import dream/servers/mist/server.{bind, listen, router, services}
// Only accept local connections
server.new()
|> services(my_services)
|> router(my_router)
|> bind("localhost")
|> 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
import dream/servers/mist/server
import dream/servers/mist/server.{context, listen, router, services}
pub type MyContext {
MyContext(request_id: String, user: Option(User))
}
server.new()
|> context(MyContext(request_id: "", user: None))
|> services(my_services)
|> router(my_router)
|> 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
import dream/servers/mist/server
import dream/servers/mist/server.{listen, router, services}
pub fn main() {
server.new()
|> services(initialize_services())
|> router(create_router())
|> listen(3000)
}
pub fn listen_with_handle(
dream_instance: dream.Dream(
mist.Builder(mist.Connection, mist.ResponseData),
context,
services,
),
port: Int,
) -> Result(ServerHandle, actor.StartError)
Start the server and return a handle for stopping it
Like listen(), but returns immediately with a ServerHandle that can be used
to stop the server programmatically. Useful for tests and programmatic server control.
Example
import dream/servers/mist/server
import dream/servers/mist/server.{listen_with_handle, router, stop}
pub fn test_server() {
// Start server and get handle
let assert Ok(handle) =
server.new()
|> router(test_router())
|> listen_with_handle(8080)
// Make test requests
let response = http_client.get("http://localhost:8080/test")
// ... assertions ...
// Stop the server
stop(handle)
}
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. The default is 10_000_000 bytes (10MB), which is a safe limit for typical JSON and form payloads. Streaming routes are not affected by this limit.
Example
import dream/servers/mist/server
import dream/servers/mist/server.{listen, max_body_size, router, services}
// Limit request bodies to 10MB
server.new()
|> services(my_services)
|> router(my_router)
|> max_body_size(10_000_000)
|> 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
import dream/servers/mist/server.{listen, router}
server.new()
|> router(my_router)
|> listen(3000)
With Custom Context and Services
import dream/servers/mist/server
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
import dream/servers/mist/server
import dream/servers/mist/server.{listen, router, services}
pub fn create_router() -> Router(MyContext, Services) {
router()
|> route(method: Get, path: "/", controller: controllers.index, middleware: [])
|> route(method: Get, path: "/users/:id", controller: controllers.show_user, middleware: [])
}
server.new()
|> services(initialize_services())
|> router(create_router())
|> 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
import dream/servers/mist/server
import dream/servers/mist/server.{listen, router, services}
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)
}
server.new()
|> services(initialize_services())
|> router(my_router)
|> listen(3000)
pub fn stop(handle: ServerHandle) -> Nil
Stop a server that was started with listen_with_handle()
Stops the server process. This sends a shutdown signal to the supervisor. Note: In tests, you typically don’t need to call this - the server will be cleaned up automatically when the test process exits.
Example
import dream/servers/mist/server
import dream/servers/mist/server.{listen_with_handle, router, stop}
pub fn test_server() {
let assert Ok(handle) =
server.new()
|> router(test_router())
|> listen_with_handle(8080)
// ... use server ...
// Optional - server will be cleaned up automatically when test exits
stop(handle)
}