From 87fc73d7ac3ae4e4653cf002df75efdab91f91e6 Mon Sep 17 00:00:00 2001 From: Brandon Hurrington Date: Fri, 13 Jun 2025 15:12:02 +0000 Subject: [PATCH 1/4] refactor: Nested existing pages and added experimental & plugin pages --- docs/.config/docs.yaml | 2 +- docs/1.guide/0.index.md | 58 ++++++++++ docs/1.guide/1.basics/.navigation.yml | 2 + docs/1.guide/1.basics/0.why.md | 71 ++++++++++++ .../{2.handler.md => 1.basics/1.handler.md} | 0 .../{3.server.md => 1.basics/2.server.md} | 0 .../3.middleware.md} | 0 .../{5.options.md => 1.basics/4.options.md} | 0 .../{6.bundler.md => 1.basics/5.bundler.md} | 0 docs/1.guide/1.index.md | 102 ------------------ docs/1.guide/2.advanced/.navigation.yml | 2 + .../{7.node.md => 2.advanced/0.node.md} | 7 +- docs/1.guide/2.advanced/1.experimental.md | 72 +++++++++++++ docs/1.guide/2.advanced/2.plugins.md | 10 ++ package.json | 2 +- test/bench-node/README.md | 2 +- 16 files changed, 221 insertions(+), 109 deletions(-) create mode 100644 docs/1.guide/0.index.md create mode 100644 docs/1.guide/1.basics/.navigation.yml create mode 100644 docs/1.guide/1.basics/0.why.md rename docs/1.guide/{2.handler.md => 1.basics/1.handler.md} (100%) rename docs/1.guide/{3.server.md => 1.basics/2.server.md} (100%) rename docs/1.guide/{4.middleware.md => 1.basics/3.middleware.md} (100%) rename docs/1.guide/{5.options.md => 1.basics/4.options.md} (100%) rename docs/1.guide/{6.bundler.md => 1.basics/5.bundler.md} (100%) delete mode 100644 docs/1.guide/1.index.md create mode 100644 docs/1.guide/2.advanced/.navigation.yml rename docs/1.guide/{7.node.md => 2.advanced/0.node.md} (91%) create mode 100644 docs/1.guide/2.advanced/1.experimental.md create mode 100644 docs/1.guide/2.advanced/2.plugins.md diff --git a/docs/.config/docs.yaml b/docs/.config/docs.yaml index 21b7243..a95109a 100644 --- a/docs/.config/docs.yaml +++ b/docs/.config/docs.yaml @@ -2,7 +2,7 @@ name: srvx shortDescription: Universal Server API -description: Based on web platform standards and works seamlessly with Deno, Bun and Node.js and more. +description: Built atop web platform standards to integrate seamlessly with Deno, Bun, Node.js, and more. github: h3js/srvx themeColor: red socials: diff --git a/docs/1.guide/0.index.md b/docs/1.guide/0.index.md new file mode 100644 index 0000000..4a69624 --- /dev/null +++ b/docs/1.guide/0.index.md @@ -0,0 +1,58 @@ +--- +icon: pixel:play +--- + +# Getting Started + +> Get to know srvx and familiarize yourself with basic usage. + +Simply put, **srvx** is a compatibility layer for Node APIs. What this means is that it acts as a unified standard API to create HTTP servers based on the standard web platform primitives ([Fetch][Fetch], [Request][Request], and [Response][Response]) which integrates seamlessly with [Deno][Deno], [Bun][Bun], [Node.js][Node], and more. + +For Deno and Bun (and [others](/guide/advanced/experimental)), **srvx** provides this unified interface at zero overhead by wrapping Node in as lithe an abstraction as possible. +This abstractive wrapper then consumes any [node:IncomingMessage][IncomingMessage] as a web standard [Request][Request] object and converts its final state of a [node:ServerResponse][ServerResponse] into the web standard [Response][Response] object. +This is the lightweight compatibility layer + +## Quick Start + +First, create an HTTP server using the `serve` function from the `srvx` package. + +```js [server.mjs] +import { serve } from "srvx"; + +const server = serve({ + fetch(request) { + return new Response("👋 Hello there!"); + }, +}); +``` + +Then, install `srvx` as a dependency: + +:pm-install{name="srvx"} + +Finally, run the server using your favorite runtime: + +::code-group + +```bash [node] +node server.mjs +``` + +```bash [deno] +deno run --allow-env --allow-net server.mjs +``` + +```bash [bun] +bun run server.mjs +``` + +:: + +[Deno]: https://deno.com/ +[Bun]: https://bun.sh/ +[Node]: https://nodejs.org/ +[Fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API +[Request]: https://developer.mozilla.org/en-US/docs/Web/API/Request +[Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response +[IncomingMessage]: https://nodejs.org/api/http.html#http_class_http_incomingmessage +[ServerResponse]: https://nodejs.org/api/http.html#http_class_http_serverresponse diff --git a/docs/1.guide/1.basics/.navigation.yml b/docs/1.guide/1.basics/.navigation.yml new file mode 100644 index 0000000..290df7a --- /dev/null +++ b/docs/1.guide/1.basics/.navigation.yml @@ -0,0 +1,2 @@ +icon: ph:book-open-duotone +title: Guide diff --git a/docs/1.guide/1.basics/0.why.md b/docs/1.guide/1.basics/0.why.md new file mode 100644 index 0000000..6a702f2 --- /dev/null +++ b/docs/1.guide/1.basics/0.why.md @@ -0,0 +1,71 @@ +--- +icon: clarity:rack-server-outline-alerted +--- + +# Why srvx? + +> Why does srx exist and why would you want to use it? + +### Making the Case + +When creating a new HTTP server with [Node.js][Node], you must either use the [node:http](https://nodejs.org/api/http.html) module or a library derived from it. + +**Ex.** - Node.js HTTP server ([learn more](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)): + +```js +import { createServer } from "node:http"; + +createServer((req, res) => { + res.end("Hello, Node.js!"); +}).listen(3000); +``` + +Whenever a new request is received, the request event is called with two Node objects: + +- Request (conventionally `req`), which is of the type [node:IncomingMessage][IncomingMessage], and passed in as the first argument of the event and enables access to the HTTP request details. +- Response (conventionally `res`), which is of the type [node:ServerResponse][ServerResponse], and passed in as the second argument of the event and allows preparing and sending of an HTTP response. + +Other popular server frameworks such as [Express][Express] and [Fastify][Fastify] also leverage the Node.js server API in their internals. + +:read-more{to="/guide/advanced/node" title="Node.js support"} + +With the recent arrival of new JavaScript server runtimes, [Deno][Deno] and [Bun][Bun], we've seen them implement a different approach when defining a server, which bears more in common with the web [Fetch][Fetch] API. + +**Ex.** - Deno HTTP server ([learn more](https://docs.deno.com/api/deno/~/Deno.serve)): + +```js +Deno.serve({ port: 3000 }, (_req, info) => new Response("Hello, Deno!")); +``` + +**Ex.** - Bun HTTP server ([learn more](https://bun.sh/docs/api/http)): + +```js +Bun.serve({ port: 3000, fetch: (req) => new Response("Hello, Bun!") }); +``` + +As you may have noticed, there is a difference between Node.js and Deno/Bun. With the latter two, the incoming request is a web [Request][Request] object and the server response is a web [Response][Response] object. +Accessing headers, the request path, and preparing the response is completely different from Node's implementation. + +And while Deno and Bun servers are both based on web standards, there are differences between them as well. Some examples: how they provide options, server lifecycles, and accessing request info such as the client IP (which is not part of the web Request standard). + +**Thus, the main use-case of this library is for tools and frameworks that wish to be runtime agnostic.** +Instead of depending on idiosyncratic runtime APIs, we can use **srvx** as a standardized server layer, and help drive the JavaScript ecosystem towards web standards and greater consistency! + +### How is it Different? + +You might ask, what is the difference between **srvx** and these other HTTP frameworks? + +**srvx** provides a simple, low-level, and universal API, very similar to Deno and Bun's. It comes with **no conventions**, utilities, or router, and in most cases, introduces no overhead. + +The core of **srvx** was extracted from an early development branch of the v2 for the [h3](https://h3.dev/) server framework and released to the broader ecosystem to encourage the adoption of web platform standards without enforcing its own conventions. + +[Node]: https://nodejs.org/ +[Deno]: https://deno.com/ +[Bun]: https://bun.sh/ +[Express]: https://expressjs.com/ +[Fastify]: https://fastify.dev/ +[Fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API +[Request]: https://developer.mozilla.org/en-US/docs/Web/API/Request +[Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response +[IncomingMessage]: https://nodejs.org/api/http.html#http_class_http_incomingmessage +[ServerResponse]: https://nodejs.org/api/http.html#http_class_http_serverresponse diff --git a/docs/1.guide/2.handler.md b/docs/1.guide/1.basics/1.handler.md similarity index 100% rename from docs/1.guide/2.handler.md rename to docs/1.guide/1.basics/1.handler.md diff --git a/docs/1.guide/3.server.md b/docs/1.guide/1.basics/2.server.md similarity index 100% rename from docs/1.guide/3.server.md rename to docs/1.guide/1.basics/2.server.md diff --git a/docs/1.guide/4.middleware.md b/docs/1.guide/1.basics/3.middleware.md similarity index 100% rename from docs/1.guide/4.middleware.md rename to docs/1.guide/1.basics/3.middleware.md diff --git a/docs/1.guide/5.options.md b/docs/1.guide/1.basics/4.options.md similarity index 100% rename from docs/1.guide/5.options.md rename to docs/1.guide/1.basics/4.options.md diff --git a/docs/1.guide/6.bundler.md b/docs/1.guide/1.basics/5.bundler.md similarity index 100% rename from docs/1.guide/6.bundler.md rename to docs/1.guide/1.basics/5.bundler.md diff --git a/docs/1.guide/1.index.md b/docs/1.guide/1.index.md deleted file mode 100644 index 6536a67..0000000 --- a/docs/1.guide/1.index.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -icon: ph:book-open-duotone ---- - -# Getting Started - -> Get familiar with srvx usage and why it exists. - -srvx provides a unified standard API to create HTTP servers based on the standard web platform primitives ([fetch][fetch], [Request][Request] and [Response][Response]) and works seamlessly with [Deno][Deno], [Bun][Bun], [Node.js][Node.js] and more. - -For [Deno][Deno] and [Bun][Bun], srvx unifies interface with zero overhead and for [Node.js][Node.js], creates a lightweight compatibility layer to wrap [node:IncomingMessage][IncomingMessage] as a standard [Request][Request] object and convert final state of [node:ServerResponse][ServerResponse] to a standard [Response][Response] object. - -## Quick Start - -Create an HTTP server using the `serve` function from `srvx` package. - -```js [server.mjs] -import { serve } from "srvx"; - -const server = serve({ - fetch(request) { - return new Response("👋 Hello there!"); - }, -}); -``` - -Install `srvx` as a dependency: - -:pm-install{name="srvx"} - -Then, run the server using your favorite runtime: - -::code-group - -```bash [node] -node server.mjs -``` - -```bash [deno] -deno run --allow-env --allow-net server.mjs -``` - -```bash [bun] -bun run server.mjs -``` - -:: - -## Why using srvx? - -When you want to create a HTTP server using [Node.js][Node.js], you have to use [node:http](https://nodejs.org/api/http.html) module (or a library based on it). - -**Example:** Node.js HTTP server ([learn more](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)): - -```js -import { createServer } from "node:http"; - -createServer((req, res) => { - res.end("Hello, Node.js!"); -}).listen(3000); -``` - -Whenever a new request is received, the request event is called with two objects: a request `req` object ([node:IncomingMessage][IncomingMessage]) to access HTTP request details and a response `res` object ([node:ServerResponse][ServerResponse]) that can be used to prepare and send a HTTP response. Popular framework such as [Express](https://expressjs.com/) and [Fastify](https://fastify.dev/) are also based on Node.js server API. - -:read-more{to="/guide/node" title="Node.js support"} - -Recent JavaScript server runtimes like [Deno][Deno] and [Bun][Bun] have a different way to define a server which is similar to web [fetch][fetch] API. - -**Example:** [Deno][Deno] HTTP server ([learn more](https://docs.deno.com/api/deno/~/Deno.serve)): - -```js -Deno.serve({ port: 3000 }, (_req, info) => new Response("Hello, Deno!")); -``` - -**Example:** [Bun][Bun] HTTP server ([learn more](https://bun.sh/docs/api/http)): - -```js -Bun.serve({ port: 3000, fetch: (req) => new Response("Hello, Bun!") }); -``` - -As you probably noticed, there is a difference between [Node.js][Node.js] and [Deno][Deno] and [Bun][Bun]. The incoming request is a web [Request][Request] object and server response is a web [Response][Response] object. Accessing headers, request path, and preparing response is completely different between [Node.js][Node.js] and other runtimes. - -While [Deno][Deno] and [Bun][Bun] servers are both based on web standards, There are differences between them. The way to provide options, server lifecycle, access to request info such as client IP which is not part of [Request][Request] standard are some examples. - -Main use-case of this library is for tools and frameworks that want to be runtime agnostic. By using srvx as standard server layer, instead of depending on of the individual runtime APIs, we push JavaScript ecosystem to be more consistent and moving towards web standards! - -### How is it Different? - -You might ask, what is the difference between srvx and other HTTP frameworks. - -Srvx provides a simple, low-level, and universal API, very similar to [Deno][Deno] and [Bun][Bun]. It has **no conventions**, utilities, or router, and in most cases, using srvx introduces no overhead. - -The core of srvx was extracted from the [h3](https://h3.dev/) v2 early development branch and opened to a broader ecosystem to encourage the adoption of Web platform standards without enforcing it's own conventions. - -[Deno]: https://deno.com/ -[Bun]: https://bun.sh/ -[Node.js]: https://nodejs.org/ -[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API -[Request]: https://developer.mozilla.org/en-US/docs/Web/API/Request -[Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response -[IncomingMessage]: https://nodejs.org/api/http.html#http_class_http_incomingmessage -[ServerResponse]: https://nodejs.org/api/http.html#http_class_http_serverresponse diff --git a/docs/1.guide/2.advanced/.navigation.yml b/docs/1.guide/2.advanced/.navigation.yml new file mode 100644 index 0000000..0e2980f --- /dev/null +++ b/docs/1.guide/2.advanced/.navigation.yml @@ -0,0 +1,2 @@ +icon: gis:cube-3d +title: Advanced diff --git a/docs/1.guide/7.node.md b/docs/1.guide/2.advanced/0.node.md similarity index 91% rename from docs/1.guide/7.node.md rename to docs/1.guide/2.advanced/0.node.md index d4b6ae6..a6a2dc4 100644 --- a/docs/1.guide/7.node.md +++ b/docs/1.guide/2.advanced/0.node.md @@ -6,12 +6,11 @@ icon: akar-icons:node-fill > Learn more about Node.js support with srvx. -> [!NOTE] -> This is an advanced section, explaining internal mechanism of srvx for Node.js support. +## View from Above -As explained in the [why srvx](/guide/why) section, [Node.js][Node.js] uses different API for handling incoming http requests and sending responses. +As explained in the [Why srvx?](/guide/basics/why) page, [Node.js][Node.js] uses different APIs for handling incoming http requests and sending responses. -srvx internally uses a lightweight proxy system that wraps [node:IncomingMessage][IncomingMessage] as [Request][Request] and converts the final state of [node:ServerResponse][ServerResponse] to a [Response][Response] object. +The internal mechanisms of **srvx** use a lightweight proxy system that wraps the [node:IncomingMessage][IncomingMessage] in a [Request][Request] and converts its final state of [node:ServerResponse][ServerResponse] to a [Response][Response] object. ## How Node.js Compatibility Works diff --git a/docs/1.guide/2.advanced/1.experimental.md b/docs/1.guide/2.advanced/1.experimental.md new file mode 100644 index 0000000..e1560a6 --- /dev/null +++ b/docs/1.guide/2.advanced/1.experimental.md @@ -0,0 +1,72 @@ +--- +icon: game-icons:soap-experiment +--- + +# Experimental Support + +> See what the team is working on to improve srvx's core offering. + +## Caution! Scientists at work! + +Currently, **srvx** provides support for two experimental adapters: [Cloudflare][Cloudflare] and the web [Service Worker API][Service Worker]. +The aim is to enable engineers to leverage **srvx** in any conceivable server environment, +even those that impose specific handling of requests/responses, such as Cloudflare's Edge Network or browser-based Service Workers. +**srvx**'s lean ergonomics and middleware are maintained to ensure the same experience across adapters. + +## Cloudflare + +The Cloudflare brand has rapidly established a name that developers trust, +so it only serves to reason that their Worker runtime environment would be a desirable target for **srvx** users. +The framework provides its universal compat layer for any requests in the Worker Environment by utilizing Cloudflare's Fetch Handler API, +ensuring that Cloudflare-specific properties, environment variables, and execution context are all accommodated. +Care is taken to preserve access to critical capabilities, like `waitUntil()` for background tasks, and +runtime metadata is attached to identify the execution context. This enables any application making use of **srvx** +to be deployed as a Cloudflare Worker while maintaining the niceties of the web standard API. + +Upcoming: Handling IP addresses + +**Ex.** - Cloudflare Workers ([learn more](https://www.cloudflare.com/developer-platform/products/workers/)): +```js +import { serve } from "srvx/adapters/cloudflare"; + +export default serve({ + fetch(request) { + return new Response(`

Hello from Cloudflare!

`, { + headers: { "Content-Type": "text/html; charset=UTF-8" }, + }); + } +}); +``` + +## Service Workers + +Anytime a Browser application has need for a proxy server to act in the absence of network availability, Service Workers are turned to. Whether completing computationally intensive tasks, +intercepting network requests, creating offline experiences, sending push notifications, or running background sync APIs, these are the purview of the +Service Worker. Retaining this core functionality is of crucial importance as any dev reaching for a Service Worker solution will expect consistency. +To this end, **srvx** smartly detects if it's running in a Browser or Service Worker context and delivers the commensurate behavior for each environment. +The entire Service Worker lifecycle is supported and managed as **srvx** self-registers, activates, and unregisters automatically. Critical features, +such as `waitUntil` capability for background operations, "claim immediately" behavior, and per-update page reloads so that new clients can be claimed. +During self-registration scenarios, any heavier application logic should be lazy loaded when performance implications are a concern (but when aren't they...? :smirk:). + +> [!NOTE] +> As a safety measure, 404 responses and requests for static assets (i.e. URLs with file extensions) are skipped to avoid breaking normal browser behaviors. + +Upcoming: An option for 404 handling will be explored + +**Ex.** - Service Workers ([learn more](https://stackblitz.com/github/h3js/srvx/tree/main/playground?file=app.mjs)): +```js +import { serve } from "../node_modules/srvx/dist/adapters/service-worker.mjs"; + +// Internally the service worker is implemented by passing it as an option to the `serve()` function alongside `fetch()` +serve({ + serviceWorker: { url: import.meta.url }, + fetch(_request) { + return new Response(`

👋 Hello there!

`, { + headers: { "Content-Type": "text/html; charset=UTF-8" }, + }); + }, +}); +``` + +[Cloudflare]: https://www.cloudflare.com/ +[Service Worker]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API diff --git a/docs/1.guide/2.advanced/2.plugins.md b/docs/1.guide/2.advanced/2.plugins.md new file mode 100644 index 0000000..40457f4 --- /dev/null +++ b/docs/1.guide/2.advanced/2.plugins.md @@ -0,0 +1,10 @@ +--- +icon: bi:plugin +--- + +# Plugins + +> Learn more about how we leverage plugins to extend the srvx foundation with new functionalities. + +> [!NOTE] +> More to come!! Keep watching this space... diff --git a/package.json b/package.json index c45fb4f..635ad5f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "srvx", "version": "0.8.0", - "description": "Universal Server API based on web platform standards. Works seamlessly with Deno, Bun and Node.js.", + "description": "Universal Server API built atop web platform standards to integrate seamlessly with Deno, Bun, Node.js, and more.", "homepage": "https://srvx.h3.dev", "repository": "h3js/srvx", "license": "MIT", diff --git a/test/bench-node/README.md b/test/bench-node/README.md index 8f488d9..42faf8d 100644 --- a/test/bench-node/README.md +++ b/test/bench-node/README.md @@ -1,4 +1,4 @@ -# Node.js Cmpatibility Benchmarks +# Node.js Compatibility Benchmarks Simple benchmarks primarily focus on how closely we can approach native `node:http` performance while using a web standards compatibility layer. From 3c8984dbc215b84707c8d6e607ee29bc1581077c Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 10:16:20 +0000 Subject: [PATCH 2/4] chore: apply automated updates --- docs/1.guide/2.advanced/1.experimental.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/1.guide/2.advanced/1.experimental.md b/docs/1.guide/2.advanced/1.experimental.md index e1560a6..48427ba 100644 --- a/docs/1.guide/2.advanced/1.experimental.md +++ b/docs/1.guide/2.advanced/1.experimental.md @@ -26,6 +26,7 @@ to be deployed as a Cloudflare Worker while maintaining the niceties of the web Upcoming: Handling IP addresses **Ex.** - Cloudflare Workers ([learn more](https://www.cloudflare.com/developer-platform/products/workers/)): + ```js import { serve } from "srvx/adapters/cloudflare"; @@ -34,7 +35,7 @@ export default serve({ return new Response(`

Hello from Cloudflare!

`, { headers: { "Content-Type": "text/html; charset=UTF-8" }, }); - } + }, }); ``` @@ -54,6 +55,7 @@ During self-registration scenarios, any heavier application logic should be lazy Upcoming: An option for 404 handling will be explored **Ex.** - Service Workers ([learn more](https://stackblitz.com/github/h3js/srvx/tree/main/playground?file=app.mjs)): + ```js import { serve } from "../node_modules/srvx/dist/adapters/service-worker.mjs"; From 47bcc753d8e00ed41cf794307881b82e4a857558 Mon Sep 17 00:00:00 2001 From: Brandon Hurrington Date: Thu, 19 Jun 2025 17:42:05 +0000 Subject: [PATCH 3/4] fix: Add missing icon for top level guide page button --- docs/1.guide/.navigation.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/1.guide/.navigation.yml diff --git a/docs/1.guide/.navigation.yml b/docs/1.guide/.navigation.yml new file mode 100644 index 0000000..a542600 --- /dev/null +++ b/docs/1.guide/.navigation.yml @@ -0,0 +1,2 @@ +icon: i-ph:book-open-duotone +title: Guide From 9ff6a17044931647276661a216887df1fab6cc5b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 19 Jun 2025 22:43:44 +0200 Subject: [PATCH 4/4] update --- docs/1.guide/0.index.md | 8 ++-- docs/1.guide/1.basics/0.why.md | 79 +++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/docs/1.guide/0.index.md b/docs/1.guide/0.index.md index 4a69624..cd4ad11 100644 --- a/docs/1.guide/0.index.md +++ b/docs/1.guide/0.index.md @@ -6,11 +6,9 @@ icon: pixel:play > Get to know srvx and familiarize yourself with basic usage. -Simply put, **srvx** is a compatibility layer for Node APIs. What this means is that it acts as a unified standard API to create HTTP servers based on the standard web platform primitives ([Fetch][Fetch], [Request][Request], and [Response][Response]) which integrates seamlessly with [Deno][Deno], [Bun][Bun], [Node.js][Node], and more. +Srvx provides a unified API for creating HTTP servers based on web standard primitives such as [fetch][fetch], [Request][Request], and [Response][Response], working seamlessly with [Deno][Deno], [Bun][Bun], [Node.js][Node.js], and more. -For Deno and Bun (and [others](/guide/advanced/experimental)), **srvx** provides this unified interface at zero overhead by wrapping Node in as lithe an abstraction as possible. -This abstractive wrapper then consumes any [node:IncomingMessage][IncomingMessage] as a web standard [Request][Request] object and converts its final state of a [node:ServerResponse][ServerResponse] into the web standard [Response][Response] object. -This is the lightweight compatibility layer +:read-more{to="/guide/basics/why" title="Why srvx?"} ## Quick Start @@ -50,7 +48,7 @@ bun run server.mjs [Deno]: https://deno.com/ [Bun]: https://bun.sh/ -[Node]: https://nodejs.org/ +[Node.js]: https://nodejs.org/ [Fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API [Request]: https://developer.mozilla.org/en-US/docs/Web/API/Request [Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response diff --git a/docs/1.guide/1.basics/0.why.md b/docs/1.guide/1.basics/0.why.md index 6a702f2..8cdc159 100644 --- a/docs/1.guide/1.basics/0.why.md +++ b/docs/1.guide/1.basics/0.why.md @@ -6,60 +6,79 @@ icon: clarity:rack-server-outline-alerted > Why does srx exist and why would you want to use it? -### Making the Case +Srvx provides a unified API for creating HTTP servers based on web standard primitives such as [fetch][fetch], [Request][Request], and [Response][Response], working seamlessly with [Deno][Deno], [Bun][Bun], [Node.js][Node.js], and more. -When creating a new HTTP server with [Node.js][Node], you must either use the [node:http](https://nodejs.org/api/http.html) module or a library derived from it. +Usage is simple, low-level, and universal, and in most cases, introduces no or minimum overhead. -**Ex.** - Node.js HTTP server ([learn more](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)): +The main use-case of srvx is for tools and frameworks that wish to be runtime agnostic. Instead of depending on idiosyncratic runtime APIs, and introducing adapters, using srvx as unified building block. -```js -import { createServer } from "node:http"; +**Example:** Same code working regardless of runtime. -createServer((req, res) => { - res.end("Hello, Node.js!"); -}).listen(3000); +```js +import { serve } from "srvx"; + +const server = serve({ + port: 3000, + // tls: {} + fetch(request) { + return new Response(`👋 Your IP address is ${request.ip}`); + }, +}); ``` -Whenever a new request is received, the request event is called with two Node objects: - -- Request (conventionally `req`), which is of the type [node:IncomingMessage][IncomingMessage], and passed in as the first argument of the event and enables access to the HTTP request details. -- Response (conventionally `res`), which is of the type [node:ServerResponse][ServerResponse], and passed in as the second argument of the event and allows preparing and sending of an HTTP response. - -Other popular server frameworks such as [Express][Express] and [Fastify][Fastify] also leverage the Node.js server API in their internals. +## Runtime APIs -:read-more{to="/guide/advanced/node" title="Node.js support"} +### Deno and Bun -With the recent arrival of new JavaScript server runtimes, [Deno][Deno] and [Bun][Bun], we've seen them implement a different approach when defining a server, which bears more in common with the web [Fetch][Fetch] API. +[Deno][Deno] and [Bun][Bun] use web standard APIs for HTTP servers, with slight differences and extensions on top of the standard. -**Ex.** - Deno HTTP server ([learn more](https://docs.deno.com/api/deno/~/Deno.serve)): +**Example:** [Deno][Deno] server ([learn more](https://docs.deno.com/api/deno/~/Deno.serve)): ```js -Deno.serve({ port: 3000 }, (_req, info) => new Response("Hello, Deno!")); +Deno.serve( + { port: 3000 }, + (request, info) => + new Response(`👋 Your IP address is ${info.remoteAddr.hostname}`), +); ``` -**Ex.** - Bun HTTP server ([learn more](https://bun.sh/docs/api/http)): +**Example:** [Bun][Bun] server ([learn more](https://bun.sh/docs/api/http)): ```js -Bun.serve({ port: 3000, fetch: (req) => new Response("Hello, Bun!") }); +Bun.serve({ + port: 3000, + fetch: (request, server) => + new Response(`👋 Your IP address is ${server.requestIP(request).address}`), +}); ``` -As you may have noticed, there is a difference between Node.js and Deno/Bun. With the latter two, the incoming request is a web [Request][Request] object and the server response is a web [Response][Response] object. -Accessing headers, the request path, and preparing the response is completely different from Node's implementation. +> [!TIP] +> Srvx unifies usage by adding [extensions directly to request](/guide/basics/handler#extended-request-serverrequest) and unified [options](/guide/basics/options). -And while Deno and Bun servers are both based on web standards, there are differences between them as well. Some examples: how they provide options, server lifecycles, and accessing request info such as the client IP (which is not part of the web Request standard). +### Node.js -**Thus, the main use-case of this library is for tools and frameworks that wish to be runtime agnostic.** -Instead of depending on idiosyncratic runtime APIs, we can use **srvx** as a standardized server layer, and help drive the JavaScript ecosystem towards web standards and greater consistency! +[Node.js][Node.js], provides [`node:http`](https://nodejs.org/api/http.html), [`node:https`](https://nodejs.org/api/https.html) and [`node:http2`](https://nodejs.org/api/http2.html) to create HTTP servers. -### How is it Different? +**Example:** Node.js HTTP server ([learn more](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)): -You might ask, what is the difference between **srvx** and these other HTTP frameworks? +```js +import { createServer } from "node:http"; + +createServer((req, res) => { + res.end(`👋 Your IP address is ${req.socket.remoteAddress}`); +}).listen(3000); +``` -**srvx** provides a simple, low-level, and universal API, very similar to Deno and Bun's. It comes with **no conventions**, utilities, or router, and in most cases, introduces no overhead. +Whenever a new request is received, the request event is called with two Node objects: -The core of **srvx** was extracted from an early development branch of the v2 for the [h3](https://h3.dev/) server framework and released to the broader ecosystem to encourage the adoption of web platform standards without enforcing its own conventions. +- Request (conventionally `req`), which is of the type [node:IncomingMessage][IncomingMessage], and passed in as the first argument of the event and enables access to the HTTP request details. +- Response (conventionally `res`), which is of the type [node:ServerResponse][ServerResponse], and passed in as the second argument of the event and allows preparing and sending of an HTTP response. + +Srvx uses a lightweight proxy layer to emulate web standard APIs for Node.js. + +:read-more{to="/guide/advanced/node" title="Node.js support"} -[Node]: https://nodejs.org/ +[Node.js]: https://nodejs.org/ [Deno]: https://deno.com/ [Bun]: https://bun.sh/ [Express]: https://expressjs.com/