Production-ready HTTP client, server, router, and middleware toolkit for the Alya language ecosystem.
- ⚡ High Performance: Optimized protocol parsing, header serialization, and fast routing. Micro-benchmarks demonstrate >100,000 ops in hundreds of milliseconds.
- 🌐 Full HTTP Client: Supports GET, POST, PUT, DELETE, PATCH, HEAD, and OPTIONS with custom headers, query params, timeout handling, and automatic redirect following.
- 🚀 HTTP Server & Context: Built on low-level TCP sockets (
std/net), offering intuitive request context (HttpContext), JSON responses, text responses, file serving, and status helpers. - 🛣️ Parametric Router & Route Groups: Fast URL pattern matching with wildcard (
*path) and named parameters (:id), plus subrouter groups with shared path prefixes and middleware chains. - 🛡️ Extensible Middleware: Out-of-the-box middleware for CORS (
cors_middleware), request logging (logger_middleware), panic recovery (recovery_middleware), and static file serving (static_middleware). - 🍪 Cookie & Header Management: RFC-compliant Cookie serialization/parsing (
Set-CookieandCookieheaders) and case-insensitive HTTP header operations.
http/
├── alya.toml # Package manifest
├── src/
│ ├── lib.alya # Public API facade & high-level constructors
│ ├── types.alya # Core struct definitions (HttpRequest, HttpResponse, Route, etc.)
│ ├── core/
│ │ ├── status.alya # HTTP status codes & standard status messages
│ │ ├── headers.alya # Case-insensitive header dictionary helpers
│ │ ├── cookies.alya # Cookie parsing, serialization, and Set-Cookie generation
│ │ └── protocol.alya # HTTP/1.1 request & response parsing and serialization
│ ├── router/
│ │ ├── route.alya # Route definition and parameter extractor
│ │ ├── router.alya # HTTP router and route registry
│ │ └── group.alya # Route grouping with prefix and sub-middlewares
│ ├── server/
│ │ ├── context.alya # HttpContext request/response lifecycle helpers
│ │ └── server.alya # TCP socket server, request loop, and connection handler
│ ├── client/
│ │ ├── client.alya # HttpClient implementation with socket IO and redirect loop
│ │ └── methods.alya # Convenience functions (http_get, http_post, etc.)
│ └── middleware/
│ ├── cors.alya # Cross-Origin Resource Sharing (CORS) handler
│ ├── logger.alya # Request/response logging middleware
│ ├── recovery.alya # Crash and exception recovery middleware
│ └── static.alya # Static file serving middleware with MIME detection
├── examples/
│ └── demo.alya # Comprehensive usage demo
├── tests/ # 9 comprehensive test suites
│ ├── test_client.alya
│ ├── test_context.alya
│ ├── test_cookies.alya
│ ├── test_headers.alya
│ ├── test_middleware.alya
│ ├── test_protocol.alya
│ ├── test_router.alya
│ ├── test_server.alya
│ └── test_status.alya
└── benches/
└── bench_basic.alya # Performance micro-benchmarks
Add http to your project's alya.toml:
[dependencies]
http = { git = "https://github.com/alya-lang/http", branch = "main" }Or install it directly via the alyac CLI:
alyac add http --git https://github.com/alya-lang/http --branch main
alyac installimport "http" as http
function main()
let app = http::router()
# Route with path parameter
app.get("/users/:id", "get_user")
# JSON API response route
app.post("/api/echo", "post_echo")
# Start listening on port 8080
let srv = http::server(8080, "127.0.0.1", app)
say "Server running on http://127.0.0.1:8080"
# srv.listen()
end
main()
import "http" as http
function main()
# Simple GET request
let res = http::http_get("http://httpbin.org/get")
say "Status: " + str(res.status_code)
say "Body: " + res.body
# Client instance with custom options
let client = http::client(5000, 1, 3) # 5s timeout, follow redirects
let post_res = client.post("http://httpbin.org/post", "{\"hello\":\"world\"}", "application/json")
say "Response: " + post_res.body
end
main()
import "http" as http
function main()
# Create and serialize a secure cookie
let c = http::cookie("session_id", "xyz123", "/", 3600, 1, 1, "Strict")
let cookie_hdr = http::cookie_format(c)
say "Set-Cookie: " + cookie_hdr
# Parse cookies from incoming request header
let parsed = http::cookie_parse_all("theme=dark; session_id=xyz123")
say "Theme: " + parsed["theme"]
end
main()
| Function | Parameters | Description |
|---|---|---|
http_get(url, headers) |
url: string, headers: map |
Performs an HTTP GET request |
http_post(url, body, content_type, headers) |
url: string, body: string, ... |
Performs an HTTP POST request |
http_put(url, body, content_type, headers) |
url: string, body: string, ... |
Performs an HTTP PUT request |
http_patch(url, body, content_type, headers) |
url: string, body: string, ... |
Performs an HTTP PATCH request |
http_delete(url, headers) |
url: string, headers: map |
Performs an HTTP DELETE request |
http_query(url, body, content_type, headers) |
url: string, body: string, ... |
Performs an HTTP QUERY request (IETF safe method with body) |
client_new(timeout_ms, follow_redirects, max_redirects) |
timeout_ms: int, ... |
Instantiates a configured HttpClient |
| Function | Parameters | Description |
|---|---|---|
server_new(port, host, router) |
port: int, host: string, router: HttpRouter |
Creates a new HttpServer instance |
http_listen(srv) |
srv: HttpServer |
Starts the socket listening loop |
context_json(ctx, status_code, json_str) |
ctx: HttpContext, status: int, json: string |
Sends a JSON response with proper header |
context_text(ctx, status_code, text_str) |
ctx: HttpContext, status: int, text: string |
Sends a plain text response |
context_file(ctx, file_path) |
ctx: HttpContext, file_path: string |
Reads and serves a local file with MIME type |
| Method | Parameters | Description |
|---|---|---|
router_new(not_found_action) |
not_found: string |
Instantiates a new route registry |
router_get(r, pattern, handler) |
pattern: string, handler: string |
Registers a GET route handler |
router_post(r, pattern, handler) |
pattern: string, handler: string |
Registers a POST route handler |
router_put(r, pattern, handler) |
pattern: string, handler: string |
Registers a PUT route handler |
router_delete(r, pattern, handler) |
pattern: string, handler: string |
Registers a DELETE route handler |
router_patch(r, pattern, handler) |
pattern: string, handler: string |
Registers a PATCH route handler |
router_query(r, pattern, handler) |
pattern: string, handler: string |
Registers a QUERY route handler |
router_group_add(r, prefix, ...) |
prefix: string, ... |
Registers a route under a group prefix |
Run all 9 test suites using alyac:
alyac testRun individual test files:
alyac run tests/test_protocol.alya
alyac run tests/test_router.alya
alyac run tests/test_cookies.alyaRun benchmarks:
alyac run benches/bench_basic.alyaRun the demo example:
alyac run examples/demo.alyaContributions are welcome! Please follow these steps:
- Fork the repository and clone it locally
- Install the package tools:
alyac install
- Create your feature branch:
git checkout -b feature/my-feature
- Verify tests and code formatting before opening a PR:
alyac test alyac fmt . --check
- Commit your changes:
git commit -m "feat: add feature description" - Open a Pull Request on GitHub.
This project is licensed under the MIT License - see the LICENSE file for details.