serez-http
HTTP and WebSocket server for Serez Code — Express/Flask-style API with built-in rate limiting, CORS, and middleware support.
Install
sz install serez-httpQuick start
import "serez-http"
const app = new App()
app.GET("/", fn(req, res) {
res.json({"message": "hello from serez-http"})
})
app.GET("/user/:id", fn(req, res) {
let id = req["params"]["id"]
res.json({"user_id": id})
})
app.POST("/echo", fn(req, res) {
let data = JSON.parse(req["body"])
res.json(data)
})
app.listen(3000, fn() {
out "server running on port 3000"
})Routes
Register handlers with GET, POST, PUT, and delete. Route patterns support :param segments captured in req["params"]:
app.GET("/posts/:id/comments/:cid", fn(req, res) {
let post_id = req["params"]["id"]
let comment_id = req["params"]["cid"]
res.status(200).json({"post": post_id, "comment": comment_id})
})Request object
| Field | Type | Description |
|---|---|---|
req["method"] | string | HTTP verb: GET, POST, PUT, DELETE |
req["path"] | string | URL path without query string |
req["query"] | dict | Parsed query parameters |
req["params"] | dict | Route :param captures |
req["body"] | string | Raw request body |
req["headers"] | dict | All request headers (lowercase keys) |
req["content_type"] | string | Content-Type header value |
req["authorization"] | string | Authorization header value |
req["host"] | string | Host header value |
req["ip"] | string | Client IP (from X-Forwarded-For) |
Response methods
| Method | Description |
|---|---|
res.json(obj) | Send JSON body |
res.send(text) | Send plain text body |
res.status(code) | Set HTTP status code — chainable |
res.header(key, val) | Add a response header — chainable |
res.cookie(name, val) | Set a cookie header — chainable |
res.redirect(url) | 302 redirect |
res.sendfile(path) | Send file contents |
res.download(path) | Trigger browser download |
// Chaining status + json
res.status(404).json({"error": "not found"})
// Chaining header + json
res.header("X-Request-Id", "abc123").json({"ok": true})Middleware
Register middleware with addMw. Each middleware receives req, res, and next. Call next() to pass control to the next middleware or route handler. Not calling it stops the chain.
// Logging middleware
app.addMw(fn(req, res, next) {
out req["method"] + " " + req["path"]
next()
})
// Auth middleware
app.addMw(fn(req, res, next) {
let token = req["authorization"]
if (token == "") {
res.status(401).json({"error": "unauthorized"})
} else {
next()
}
})Security
Built-in rate limiting and CORS helpers:
// Rate limiting — max 100 requests per minute per IP
app.addMw(fn(req, res, next) {
if (app.rateLimit(req["ip"], 100, 60)) {
next()
} else {
res.status(429).json({"error": "too many requests"})
}
})
// CORS middleware factory
app.addMw(corsMiddleware(
"https://my-domain.com",
"GET, POST, PUT, DELETE",
"Content-Type, Authorization"
))Error handler
app.error(fn(err, req, res) {
out "error: " + err
res.status(500).json({"error": "internal server error"})
})WebSocket
WebSocket support is included in the API and will activate once the Serez Code core adds Crypto.sha1base64 and Socket.recvWsFrame / Socket.sendWsFrame. The API is already defined:
app.ws("/ws", fn(req, ws) {
ws.on("message", fn(msg) {
ws.send("echo: " + msg)
})
ws.on("close", fn() {
out "client disconnected"
})
ws.listen()
})Notes
serez-http is single-threaded — one connection is handled at a time. The server listens on 127.0.0.1; use serez-apipack to deploy to Docker with external access.