HTTP Server
Build a simple HTTP server with effect-tracked I/O. The type signature tells you exactly what side effects this code performs.
server.lux
// A simple HTTP server in Lux
// Notice the effect signature: {HttpServer, Console}
fn handleRequest(req: Request): Response = {
match req.path {
"/" => Response {
status: 200,
body: "Welcome to Lux!"
},
"/api/hello" => Response {
status: 200,
body: Json.stringify({ message: "Hello, World!" })
},
_ => Response {
status: 404,
body: "Not Found"
}
}
}
fn main(): Unit with {HttpServer, Console} = {
HttpServer.listen(8080)
Console.print("Server listening on http://localhost:8080")
loop {
let req = HttpServer.accept()
Console.print(req.method + " " + req.path)
let response = handleRequest(req)
HttpServer.respond(response.status, response.body)
}
}
run main() with {}
Key Concepts
with {HttpServer, Console}- The function signature declares exactly which effects this code usesHttpServer.listen(port)- Start listening on a portHttpServer.accept()- Wait for and return the next requestHttpServer.respond(status, body)- Send a response- Pattern matching on
req.pathfor routing
Why Effects Matter Here
- The type signature
with {HttpServer, Console}tells you this function does network I/O and console output - Pure functions like
handleRequesthave no effects - they're easy to test - For testing, you can swap the
HttpServerhandler to simulate requests without a real network
Run It
$ lux run server.lux
Server listening on http://localhost:8080
# In another terminal:
$ curl http://localhost:8080/
Welcome to Lux!
$ curl http://localhost:8080/api/hello
{"message":"Hello, World!"}