Skip to content

Core Server (http/server)

While most users will build APIs with the http/fiber framework, http/server gives you direct access to the the raw accept loop, request parser, and response builder.

Minimal Hello World

rust
import { Server, Request, Response } from "http";

fn main(): i32 {
    let! srv = Server.new("0.0.0.0", 8080);
    srv.serve(handler);
    return 0;
}

fn handler(req: &Request, res: &Response!) {
    res.sendString(req.fd, "Hello, Vex!");
}

Request Parsing

Every incoming connection is consumed by the zero-copy parseRequest(fd) function. It reads up to 8KB from the socket and extracts the full request in a single pass using a byte-level scanner—no regex, no intermediate string allocations.

Request Struct

FieldTypeDescription
methodstring"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"
pathstringURL path without query string (e.g. /api/users)
querystringRaw query string (e.g. page=1&sort=name)
versionstring"HTTP/1.1" or "HTTP/1.0"
headersHeadersParsed header collection (case-insensitive)
bodystringRequest body (for POST/PUT/PATCH)
fdi32Socket file descriptor
streamIdi32HTTP/2 stream ID (0 for HTTP/1.1)
validbooltrue if parsing succeeded
contentLengthi64Parsed Content-Length value (-1 if absent)
keepAlivebooltrue if Connection != close

Request Accessor Methods

rust
req.header("Authorization")    // Get header value (case-insensitive)
req.hasHeader("X-Custom")      // Check if header exists
req.isMethod("POST")           // Match method (case-sensitive)
req.hasBody()                  // true if body.len() > 0
req.contentType()              // Get Content-Type header value
req.isJSON()                   // true if Content-Type == "application/json"

Async Variant

For goroutine-per-connection servers, use the non-blocking parser:

rust
let req = parseRequestAsync(fd);  // yields to scheduler on EAGAIN

Headers (Headers Collection)

Headers are stored as parallel Vec<string> arrays (names + values) with byte-level case-insensitive comparison. No Map overhead, no hash computation—just linear scan optimized for the typical 5–15 header count.

MethodDescription
Headers.new()Create empty collection
hdrs.get(name): stringGet value (case-insensitive), returns "" if not found
hdrs.has(name): boolCheck existence
hdrs.set(name, value)Set/replace (removes existing, then appends)
hdrs.add(name, value)Append (allows duplicates, e.g. Set-Cookie)
hdrs.del(name)Remove all matching (in-place, zero-alloc)
hdrs.clear()Remove all headers
hdrs.shrinkToFit()Release excess capacity
hdrs.len(): i32Count of headers

Cookies

The cookie.vx module provides full HTTP cookie parsing and Set-Cookie header serialization.

Building Cookies

rust
import { Cookie } from "http";

// Simple session cookie
let session = Cookie.new("session_id", "abc123");
// → "session_id=abc123; Path=/; HttpOnly; SameSite=Lax"

// Persistent cookie (expires in 1 hour)
let remember = Cookie.persistent("remember", "yes", 3600);
// → "remember=yes; Max-Age=3600; Path=/; HttpOnly; SameSite=Lax"

// Deletion cookie
let logout = Cookie.delete("session_id");
// → "session_id=; Max-Age=0; Path=/"

// Set on response
res.header("Set-Cookie", session.toString());

Parsing Incoming Cookies

rust
import { parseCookies } from "http";

let pairs = parseCookies(req.header("Cookie"));
// "session_id=abc123; theme=dark"
// → [CookiePair{name:"session_id", value:"abc123"}, CookiePair{name:"theme", value:"dark"}]
FieldTypeDescription
namestringCookie name
valuestringCookie value
pathstringPath attribute (default "/")
domainstringDomain attribute (empty = current)
maxAgei32Max-Age in seconds (-1 = session, 0 = delete)
secureboolHTTPS only flag
httpOnlyboolNo JS access flag
sameSitestring"Strict", "Lax", "None", or ""

Response Builder

rust
import { Response, respondText, respondJSON, respondError, respondRedirect } from "http";

// Builder pattern
let! res = Response.new();
res.status(201)
   .header("X-Request-ID", "req-001")
   .contentType("application/json");
res.sendJSON(req.fd, "{\"created\": true}");

// One-liner convenience functions
respondText(fd, "Hello!");                    // 200 text/plain
respondJSON(fd, "{\"ok\":true}");             // 200 application/json
respondError(fd, 404, "Not Found");           // 404 with message
respondRedirect(fd, "/login");                // 302 redirect

Internal Parser Architecture

Underneath, request parsing is handled by a dedicated parser/ subsystem:

FilePurpose
parser/scanner.vxLow-level byte scanner with position tracking
parser/request.vxHTTP/1.1 request line + header parser
parser/fiber_request.vxOptimized Fiber-compatible incremental parser
parser/headers.vxHeader-specific parsing logic
parser/body.vxBody extraction with Content-Length validation
parser/chunked.vxTransfer-Encoding: chunked decoder
parser/response.vxClient-side response parser
parser/h2.vxHTTP/2 frame parser
parser/hpack.vxHPACK header compression (RFC 7541)
parser/huffman.vxHuffman coding tables for HPACK
parser/ws.vxWebSocket frame parser
parser/stream.vxStreaming parser for large payloads

Released under the MIT License.