# HTTP servers
`std::net::http::server` turns accepted HTTP requests into values. A server owns
its listening socket; each Incoming request owns its request/response lifecycle.
## Define a handler
Defining this function does not start a service. A caller can invoke it with an
explicit port when ready to listen.
```shy
import std::net::http::server
fn serve_status($port: Integer): () | ErrorValue
{
let $server = std::net::http::server::listen "127.0.0.1" $port
try
{
$server.serve fn ($request: std::net::http::server::Incoming): () | ErrorValue
{
$request.respond (std::net::http::server::text_response "available")
} 1
}
finally { $server.close }
}
```
The second argument to `serve` bounds the number of handled requests here.
`accept` offers manual control instead. `address` reports the selected endpoint,
including an operating-system-assigned port when listening on zero.
Incoming requests expose `method`, `path`, and headers. Read a request body once
through a byte Reader, an exact document, or `read_as Type`. Respond with a
Response, or helpers such as `text_response` and `json_response`.
Close an incoming operation if abandoning it before completion. Keep handler
errors explicit: a transport failure and a deliberately chosen HTTP error status
are different decisions.
Shelly's server and client share [Bytes and I/O](Bytes-and-IO) ownership rules.
For a reusable service, define request limits, error policy, and shutdown behavior
alongside the handler rather than hiding those choices in example defaults.
---
Related: [HTTP clients](HTTP) · [Networking](Networking) · [JSON](JSON)