You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`node-fetch-server` allows you to build servers for Node.js that use the [web Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) primitives (namely [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)) instead of the traditional `req`/`res` API used in libraries like [Express](https://expressjs.com/).
3
+
Build portable Node.js servers using web-standard Fetch API primitives 🚀
4
4
5
-
This web standard API is already used in many places across the JavaScript ecosystem:
5
+
`node-fetch-server` brings the simplicity and familiarity of the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to Node.js server development. Instead of dealing with Node's traditional `req`/`res` objects, you work with web-standard [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects—the same APIs you already use in the browser and modern JavaScript runtimes.
6
+
7
+
## Why node-fetch-server?
8
+
9
+
-**Write once, run anywhere**: Your server code becomes portable across Node.js, Deno, Bun, Cloudflare Workers, and other platforms
10
+
-**Familiar API**: Use the same Request/Response APIs you already know from client-side development
11
+
-**Future-proof**: Align with web standards that are here to stay
12
+
-**TypeScript-friendly**: Full type safety with standard web APIs
13
+
-**Lightweight**: Minimal overhead while providing a cleaner, more intuitive API
14
+
15
+
The Fetch API is already the standard for server development in:
When you write servers using the `Request` and `Response` APIs, you maximize the chances that your code will be portable across these different JavaScript runtimes.
22
+
Now you can use the same pattern in Node.js!
13
23
14
24
## Features
15
25
16
-
- Use web standard [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) APIs for building servers, instead of node-specific API
17
-
- Seamless integration with `node:http` and `node:https` modules
18
-
- Supports custom hostnames (e.g. using `process.env.HOST` on a VPS to set the host portion of incoming request URLs)
19
-
- Supports streaming responses using `new Response(stream)`
20
-
- Exposes remote client address info
26
+
- ✅ Web-standard [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) APIs
27
+
- ✅ Drop-in integration with `node:http` and `node:https` modules
28
+
- ✅ Streaming response support with `ReadableStream`
29
+
- ✅ Custom hostname configuration for deployment flexibility
30
+
- ✅ Access to client connection info (IP address, port)
// Your request handler uses standard Request/Response objects
48
+
asyncfunction handler(request:Request) {
49
+
let url =newURL(request.url);
50
+
51
+
// Route based on pathname
52
+
if (url.pathname==='/') {
53
+
returnnewResponse('Welcome to the home page!');
54
+
}
55
+
56
+
if (url.pathname==='/api/users') {
57
+
let users =awaitgetUsers(); // Your async logic here
58
+
returnResponse.json(users);
59
+
}
60
+
61
+
returnnewResponse('Not Found', { status: 404 });
36
62
}
37
63
64
+
// Create a standard Node.js server
38
65
let server =http.createServer(createRequestListener(handler));
39
66
40
-
server.listen(3000);
67
+
server.listen(3000, () => {
68
+
console.log('Server running at http://localhost:3000');
69
+
});
41
70
```
42
71
43
-
By default `request.url` is derived from the value of the `Host` HTTP header and the connection protocol being used. To support custom hostnames using e.g. a `HOST` environment variable, you can use the `host` option:
72
+
### Working with Request Data
73
+
74
+
```ts
75
+
asyncfunction handler(request:Request) {
76
+
// Access request method, headers, and body just like in the browser
77
+
if (request.method==='POST'&&request.url.endsWith('/api/users')) {
78
+
// Parse JSON body
79
+
let userData =awaitrequest.json();
80
+
81
+
// Validate and process...
82
+
let newUser =awaitcreateUser(userData);
83
+
84
+
// Return JSON response
85
+
returnResponse.json(newUser, {
86
+
status: 201,
87
+
headers: { 'Content-Type': 'application/json' },
88
+
});
89
+
}
90
+
91
+
returnnewResponse('Method not allowed', { status: 405 });
92
+
}
93
+
```
94
+
95
+
### Streaming Responses
96
+
97
+
Take advantage of web-standard streaming with `ReadableStream`:
let server =https.createServer(options, createRequestListener(handler));
186
+
187
+
server.listen(443, () => {
188
+
console.log('HTTPS Server running on port 443');
189
+
});
190
+
```
72
191
73
-
In addition to the high-level `createRequestListener()` API, this package also provides 2 low-level APIs that are useful when building custom `fetch`-based servers in Node.js:
These two functions serve as an efficient, minimal translation layer between Node.js `req`/`res` objects and fetch `Request`/`Response` objects. You could build your own custom server like this:
196
+
For more control over request/response handling, use the low-level API:
@@ -97,58 +219,56 @@ let server = http.createServer(async (req, res) => {
97
219
server.listen(3000);
98
220
```
99
221
100
-
## Related Packages
222
+
The low-level API provides:
101
223
102
-
-[`fetch-proxy`](https://github.com/mjackson/remix-the-web/tree/main/packages/fetch-proxy) - Build HTTP proxy servers using the web fetch API
224
+
-`createRequest(req, res, options)` - Converts Node.js IncomingMessage to web Request
225
+
-`sendResponse(res, response)` - Sends web Response using Node.js ServerResponse
103
226
104
-
## Benchmark
227
+
This is useful for:
105
228
106
-
A basic "hello world" benchmark shows `node-fetch-server` introduces considerable overhead on top of a vanilla `node:http` server. However, it is still able to serve more requests per second (and has higher overall throughput) than Express v4, so the slowdown should be acceptable for most applications.
229
+
- Building custom middleware systems
230
+
- Integrating with existing Node.js code
231
+
- Implementing custom error handling
232
+
- Performance-critical applications
107
233
234
+
## Migration from Express
235
+
236
+
Transitioning from Express? Here's a quick comparison:
237
+
238
+
```ts
239
+
// Express way
240
+
app.get('/users/:id', async (req, res) => {
241
+
let user =awaitgetUser(req.params.id);
242
+
res.json(user);
243
+
});
244
+
245
+
// node-fetch-server way
246
+
asyncfunction handler(request:Request) {
247
+
let url =newURL(request.url);
248
+
let match =url.pathname.match(/^\/users\/(\w+)$/);
0 commit comments