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 as dream
pub fn main() {
dream.new()
|> dream.services(initialize_services())
|> dream.router(create_router())
|> dream.listen(3000)
}
The builder pattern lets you configure your server step by step. Start with new(),
add your services and router, optionally set a custom context, then listen() to start.
Custom Context
By default, Dream uses AppContext with just a request_id field. For most apps,
you’ll want to define your own context type to hold user auth, session data, etc:
pub type MyContext {
MyContext(request_id: String, user: Option(User), session: Session)
}
dream.new()
|> dream.context(MyContext(request_id: "", user: None, session: empty_session()))
|> dream.services(initialize_services())
|> dream.router(create_router())
|> dream.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.AppContext,
router.EmptyServices,
)
Create a new Dream server with defaults
Returns a server configured with AppContext (just a request_id field) and
EmptyServices (no dependencies). You’ll typically chain this with context(),
services(), and router() before calling listen().
Example
dream.new()
|> dream.services(my_services)
|> dream.router(my_router)
|> dream.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)