HTTP/1.1 and HTTP/2 server framework for Pony.
- HTTP/1.1 - RFC 9112 compliant with keep-alive, chunked encoding, pipelining
- HTTP/2 - RFC 7540 compliant (91/92 h2spec tests), multiplexing, flow control, HPACK compression
- TLS + ALPN - Automatic protocol negotiation (h2 / http/1.1)
- Router - Path parameters (
:id), wildcards (*path), method-based routing - Middleware - CORS, logging, custom headers
- Static files - Directory serving with path sanitization
Add LastPoint to your Pony project:
corral add github.com/golovatskygroup/lastpoint
corral fetchuse "lastpoint"
primitive HelloHandler is AppHandler
fun apply(ctx: AppContext box): HTTPResponse =>
HTTPResponse.ok("Hello " + ctx.param("name"))
actor Main
new create(env: Env) =>
let router: RequestRouter val = recover val
let app1 = HttpApp.with_middleware(ServerHeaderMiddleware)
let app2 = app1.get("/hello/:name", HelloHandler)
app2.build()
end
HTTPServer(env, router, Logger(env), "0.0.0.0", "8080")# Clone the repository
git clone https://github.com/golovatskygroup/lastpoint.git
cd lastpoint
# Fetch dependencies
corral fetch
# Build and run the example server
make build
./build/http_serverlet router: RequestRouter val = recover val
let app1 = HttpApp
let app2 = app1.get("/", IndexHandler)
let app3 = app2.get("/users/:id", GetUserHandler)
let app4 = app3.post("/users", CreateUserHandler)
let app5 = app4.get("/assets/*path", StaticHandler)
let app6 = app5.with_middleware(CORSMiddleware)
app6.build()
endAccess parameters in handlers:
let user_id = ctx.param("id") // path parameter
let query = ctx.query("search") // query string
let body = ctx.body_json() // parsed JSON body./http_server --host 0.0.0.0 --port 8443 --tls-enabledEnvironment variables: HTTP_SERVER_HOST, HTTP_SERVER_PORT, HTTP_SERVER_TLS_ENABLED
lastpoint/
├── lastpoint/ # Library package
│ ├── http_app.pony # Framework builder, AppContext, middleware chain
│ ├── flex_router.pony # Router with path parameters and wildcards
│ ├── middleware.pony # CORS, logging, server header middleware
│ ├── server.pony # HTTPServer actor
│ ├── connection.pony # HTTP/1.1 connection handler
│ ├── http2.pony # HTTP/2 protocol implementation
│ ├── hpack.pony # HPACK header compression (RFC 7541)
│ ├── tls.pony # TLS/ALPN protocol negotiation
│ ├── request.pony # HTTPRequest
│ ├── response.pony # HTTPResponse
│ ├── logger.pony # Structured logger
│ ├── config.pony # Configuration loader
│ └── ... # Other modules
├── examples/
│ └── server/
│ ├── main.pony # Example server entry point
│ └── handlers.pony # Example request handlers
├── corral.json
├── Makefile
└── README.md
- Pony compiler 0.60+
- OpenSSL 3.0+
On macOS with Homebrew: brew install openssl
Performance comparison with Go (Apple Silicon M4 Max, macOS):
| Protocol | Pony | Go | vs Go |
|---|---|---|---|
HTTP/1.1 (wrk -t4 -c100 -d10s) |
117,129 req/s | 93,770 req/s | 125% |
HTTP/2 (h2load -n100000 -c50 -m100) |
174,993 req/s | 132,189 req/s | 132% |
| Metric | Pony | Go |
|---|---|---|
| Avg | 0.96 ms | 1.05 ms |
| StdDev | 1.59 ms | 0.15 ms |
| Max | 72.96 ms | 3.73 ms |
| Metric | Pony | Go |
|---|---|---|
| Mean | 23.52 ms | 35.27 ms |
| StdDev | 15.21 ms | 90.84 ms |
| Metric | Pony | Go |
|---|---|---|
| Header space savings | 95.36% | 94.96% |
Pony outperforms Go in both protocols: HTTP/1.1 by 25% and HTTP/2 by 32%. HTTP/1.1 latency is 9% lower than Go (0.96ms vs 1.05ms).
Key HTTP/1.1 optimizations: TCP_NODELAY, zero-allocation fast-path with pre-rendered responses, optimized request boundary scanning, pre-computed response sizes.
# Start server
make run
# In another terminal
curl http://localhost:8080/ping # PONG
curl http://localhost:8080/time # Unix timestamp
curl http://localhost:8080/echo/hello # helloMIT