Open-Source Framework

noServer

A zero-dependency Node.js web framework built from scratch on raw TCP sockets — a custom HTTP/1.1 parser and WebSocket implementation with config-driven routing, CRUD, CORS, rate limiting, and static file serving. A from-first-principles study of how web servers really work.

Overview

I built noServer to understand what actually happens when a web server handles a request — not through a framework's abstraction, but at the raw socket level. Zero dependencies: no npm packages, no http module. It implements HTTP/1.1 parsing, a hybrid router, WebSocket, rate limiting, CRUD generation, and static file serving — all in a single file, from first principles.

What I built

  • Sole author — built every layer from scratch: TCP socket handling, HTTP parsing, routing engine, WebSocket protocol, and the config API that developers use.

  • Benchmarked three different routing strategies to justify the final design — the benchmark results are committed alongside the code so the decision is always traceable.

  • Wrote a raw-TCP test client that hand-crafts HTTP/1.1 request strings to verify server behavior end-to-end — no testing library, just raw sockets.

Architecture

The server opens a raw TCP socket and buffers incoming data until a complete HTTP request arrives — detected by the blank line after headers plus the Content-Length for the body. Routes are stored in two structures: a plain object hash map for static paths (constant-time lookup) and a single compiled regex for parameterized paths, so one match call captures the route and extracts all parameters at once. WebSocket upgrades switch the socket from text to binary frame mode for the rest of its life.

Under the hood

  • WebSocket implemented from the RFC spec by hand — the handshake, frame decoding, and frame encoding, including all three payload length encodings and XOR unmasking. Ping is automatically answered with Pong. Nothing borrowed from npm.

  • Hybrid router benchmarked against two alternatives: static paths use a hash map for constant-time lookup, dynamic paths use a single compiled regex where each route's capture-group offset is pre-computed — so one match call does both routing and parameter extraction. Benchmark confirmed it beats linear scan and the Hono-style approach at 500k iterations.

  • HTTP body completeness guard: the server buffers incoming data and only dispatches a request once all bytes promised by Content-Length have arrived — preventing partial-body processing bugs that are notoriously hard to reproduce.

What I learned

  • Implementing HTTP from scratch gave me a clear picture of what frameworks hide — and made me appreciate why they exist. The boundary between 'educational' and 'production-ready' is real.

  • Benchmarking routing algorithms before committing to one saved time later — having the numbers in the repo means I never had to re-argue the decision.

Built with

Runtime

  • Node.js
  • net (TCP)
  • crypto
  • fs
  • path

Built from Scratch (Zero Dependencies)

  • HTTP/1.1 parser
  • RFC 6455 WebSocket
  • Hybrid router
  • Rate limiter
  • Auto-CRUD store
  • ETag caching
  • Static file server

Tooling

  • node --watch
  • bench.js (router benchmark)
  • test.js (raw-TCP test client)