Skip to content

Latest commit

Β 

History

31 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

http

CI License Alya Package Version

Production-ready HTTP client, server, router, compression, and middleware toolkit for the Alya language ecosystem.


🌟 Features

  • ⚑ High Performance & Reactive I/O: Fast protocol parsing and routing. Seamlessly binds to event::EventLoop for non-blocking reactive concurrency (reactive_server), handling thousands of concurrent connections with zero thread overhead.
  • πŸ”Œ RFC 6455 WebSockets: Full-duplex WebSocket server and client connections. Automatic handshake negotiation (101 Switching Protocols), RFC test-vector verified framing (text, binary, ping, pong, close), and callback-driven protocol drivers (ws_on_message, ws_send, etc.).
  • πŸ—œοΈ Web Compression Toolkit: Native integration with compress supporting Brotli (br), Zstandard (zstd), Gzip (gzip), and Deflate (deflate). Automatic Accept-Encoding negotiation, server response compression middleware, pre-compressed static asset serving (.br and .gz), and client decompression.
  • 🌐 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) or non-blocking event loops, 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 Compression (mw_apply_compression), 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-Cookie and Cookie headers) and case-insensitive HTTP header operations.

πŸ“ Project Architecture

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
β”‚   β”‚   β”œβ”€β”€ compression.alya# HTTP content encoding, negotiation, and compression engine
β”‚   β”‚   └── 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
β”‚   β”‚   └── reactive.alya   # Event-loop driven non-blocking reactive HTTP server adapter
β”‚   β”œβ”€β”€ websocket/
β”‚   β”‚   β”œβ”€β”€ handshake.alya  # RFC 6455 WebSocket upgrade & SHA-1 handshake accept token
β”‚   β”‚   β”œβ”€β”€ frame.alya      # RFC 6455 frame serializer, deserializer, and masking
β”‚   β”‚   └── connection.alya # High-level WebSocket bidirectional connection driver
β”‚   β”œβ”€β”€ client/
β”‚   β”‚   β”œβ”€β”€ client.alya     # HttpClient implementation with socket IO and redirect loop
β”‚   β”‚   └── methods.alya    # Convenience functions (http_get, http_post, etc.)
β”‚   └── middleware/
β”‚       β”œβ”€β”€ compress.alya   # HTTP response compression middleware (Brotli, Zstd, Gzip, Deflate)
β”‚       β”œβ”€β”€ 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 with MIME detection & pre-compressed assets
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ compression_demo.alya # Dedicated HTTP compression showcase
β”‚   └── demo.alya           # Comprehensive usage demo
β”œβ”€β”€ tests/                  # 14 comprehensive test suites (100% passing)
β”‚   β”œβ”€β”€ test_client.alya
β”‚   β”œβ”€β”€ test_compression.alya
β”‚   β”œβ”€β”€ test_context.alya
β”‚   β”œβ”€β”€ test_cookies.alya
β”‚   β”œβ”€β”€ test_headers.alya
β”‚   β”œβ”€β”€ test_middleware.alya
β”‚   β”œβ”€β”€ test_protocol.alya
β”‚   β”œβ”€β”€ test_reactive_server.alya
β”‚   β”œβ”€β”€ test_router.alya
β”‚   β”œβ”€β”€ test_server.alya
β”‚   β”œβ”€β”€ test_status.alya
β”‚   β”œβ”€β”€ test_websocket_conn.alya
β”‚   β”œβ”€β”€ test_websocket_frame.alya
β”‚   └── test_websocket_handshake.alya
└── benches/
    └── bench_basic.alya    # Performance micro-benchmarks

πŸ“¦ Installation

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 install

πŸš€ Quick Start

1. HTTP Server & Router

import "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 with compression enabled
    let srv = http::server(8080, "127.0.0.1", app)
    http::server_enable_compression(srv, 256)
    say "Server running on http://127.0.0.1:8080"
end

main()

2. Response Compression & Pre-compressed Static Assets

import "http" as http

function main()
    let srv = http::server(8080)

    # Enable automatic response compression (Brotli > Zstandard > Gzip > Deflate)
    # Responses >= 256 bytes will be compressed according to client's Accept-Encoding
    http::server_enable_compression(srv, 256)

    # Serve static directory with automatic .br / .gz pre-compressed asset detection
    http::server_enable_static(srv, "/static", "./public")
end

main()

3. HTTP Client

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()

4. Cookies and Headers

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()

πŸ“– API Reference

Client API

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

Server & Context API

Function Parameters Description
server_new(port, host, router) port: int, host: string, router: HttpRouter Creates a new HttpServer instance
server_enable_compression(server, min_length) server: HttpServer, min_length: int Enables response compression middleware
server_enable_static(server, prefix, dir) server: HttpServer, prefix: string, dir: string Enables static file serving with .br/.gz pre-compressed support
server_enable_cors(server, origin, methods, headers) server: HttpServer, ... Enables CORS middleware
server_enable_logger(server, enabled) server: HttpServer, enabled: int Enables request logger middleware
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

Compression API

Function Parameters Description
http_compress(data, encoding) data: string, encoding: string Compresses string with gzip, br, deflate, zstd
http_decompress(bytes, encoding) bytes: list, encoding: string Decompresses byte array back into UTF-8 string
http_negotiate_encoding(accept_header) accept_header: string Negotiates best algorithm (br > zstd > gzip > deflate)
http_is_encoding_supported(encoding) encoding: string Returns 1 if encoding is supported, 0 otherwise
compression(min_length) min_length: int Creates a new CompressionConfig struct (default 256 bytes)

Router API

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

Reactive Server API

Function Parameters Description
reactive_server(loop, port, host, router, on_req, on_ws) loop: EventLoop, ... Spawns an event-loop bound reactive HTTP/WS server
server_use_event_loop(srv, loop, on_req, on_ws) srv: HttpServer, loop: EventLoop Binds an existing HttpServer to a non-blocking reactor
server_close_reactive(srv) srv: HttpServer Unregisters server watchers and closes all client streams

WebSocket API (RFC 6455)

Function Parameters Description
websocket(stream, is_server) stream: TcpStream, is_server: int Wraps a non-blocking stream into a WebSocketConnection
ws_send(ws, text) ws: WebSocketConnection, text: string Sends a UTF-8 text message frame
ws_send_binary(ws, data) ws: WebSocketConnection, data: string Sends a binary message frame
ws_ping(ws, data) ws: WebSocketConnection, data: string Sends an RFC 6455 ping heartbeat frame
ws_pong(ws, data) ws: WebSocketConnection, data: string Sends an RFC 6455 pong heartbeat frame
ws_close(ws, code, reason) ws: WebSocketConnection, code: int, reason: string Performs clean close handshake
ws_on_message(ws, callback) ws: WebSocketConnection, cb: fn(ws, msg, is_bin) Registers message handler callback
ws_on_close(ws, callback) ws: WebSocketConnection, cb: fn(ws, code, reason) Registers connection close callback
ws_on_ping(ws, callback) ws: WebSocketConnection, cb: fn(ws, data) Registers incoming ping callback
ws_on_pong(ws, callback) ws: WebSocketConnection, cb: fn(ws, data) Registers incoming pong callback

πŸ§ͺ Running Tests & Benchmarks

Run all 14 test suites using alyac:

alyac test

Run individual test files:

alyac run tests/test_compression.alya
alyac run tests/test_protocol.alya
alyac run tests/test_router.alya
alyac run tests/test_cookies.alya

Run benchmarks:

alyac run benches/bench_basic.alya

Run the demo examples:

alyac run examples/demo.alya
alyac run examples/compression_demo.alya

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository and clone it locally
  2. Install the package tools:
    alyac install
  3. Create your feature branch:
    git checkout -b feature/my-feature
  4. Verify tests and code formatting before opening a PR:
    alyac test
    alyac fmt . --check
  5. Commit your changes:
    git commit -m "feat: add feature description"
  6. Open a Pull Request on GitHub.

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Production-ready HTTP and WebSocket client, server, router, reactive event loop, and middleware toolkit for Alya

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors