node-fetch-server
Build Node.js servers with web-standard Fetch API primitives. node-fetch-server converts Node’s HTTP server interfaces into Request /Response flows that match modern runtimes.
Installation
Core Functions
createRequestListener
Wraps a fetch handler in a Node.js request listener that can be used with http.createServer(), https.createServer(), http2.createServer(), or http2.createSecureServer().
import * as http from 'node:http'
import { createRequestListener } from 'remix/node-fetch-server'
async function handler ( request ) {
return new Response ( 'Hello, world!' )
}
let server = http . createServer (
createRequestListener ( handler )
)
server . listen ( 3000 )
The fetch handler to use for processing incoming requests
Optional configuration options Overrides the host portion of the incoming request URL. By default the request URL host is derived from the HTTP Host header. createRequestListener ( handler , { host: process . env . HOST })
Overrides the protocol of the incoming request URL. By default the request URL protocol is derived from the connection protocol (e.g., https: for HTTPS connections).
An error handler that determines the response when the request handler throws an error. By default a 500 Internal Server Error response will be sent.
A Node.js request listener function
createRequest
Creates a Request object from a Node.js http.IncomingMessage/http.ServerResponse pair or http2.Http2ServerRequest/http2.Http2ServerResponse pair.
import * as http from 'node:http'
import { createRequest , sendResponse } from 'remix/node-fetch-server'
let server = http . createServer ( async ( req , res ) => {
let request = createRequest ( req , res , { host: process . env . HOST })
let response = await handler ( request )
await sendResponse ( res , response )
})
server . listen ( 3000 )
req
http.IncomingMessage | http2.Http2ServerRequest
required
The incoming request object
res
http.ServerResponse | http2.Http2ServerResponse
required
The server response object
Options for creating the request Overrides the host portion of the incoming request URL
Overrides the protocol of the incoming request URL
A web-standard Request object
Creates a Headers object from the headers in a Node.js http.IncomingMessage or http2.Http2ServerRequest.
import { createHeaders } from 'remix/node-fetch-server'
let headers = createHeaders ( req )
console . log ( headers . get ( 'Content-Type' ))
req
http.IncomingMessage | http2.Http2ServerRequest
required
The incoming request object
A web-standard Headers object
sendResponse
Sends a Response to the client using a Node.js http.ServerResponse or http2.Http2ServerResponse object.
import { sendResponse } from 'remix/node-fetch-server'
await sendResponse ( res , new Response ( 'Hello, world!' ))
res
http.ServerResponse | http2.Http2ServerResponse
required
The server response object
A promise that resolves when the response has been sent
Types
FetchHandler
A function that handles an incoming request and returns a response.
interface FetchHandler {
( request : Request , client : ClientAddress ) : Response | Promise < Response >
}
Information about the client that sent the request
return
Response | Promise<Response>
A response to send to the client
ClientAddress
Information about the client that sent a request.
interface ClientAddress {
address : string
family : 'IPv4' | 'IPv6'
port : number
}
The IP address of the client that sent the request
The family of the client IP address
The remote port of the client that sent the request
ErrorHandler
A function that handles an error that occurred during request handling. May return a response to send to the client, or undefined to allow the server to send a default error response.
interface ErrorHandler {
( error : unknown ) : void | Response | Promise < void | Response >
}
The error that was thrown
return
void | Response | Promise<void | Response>
A response to send to the client, or undefined for the default error response
Examples
Basic Server
import * as http from 'node:http'
import { createRequestListener } from 'remix/node-fetch-server'
let users = new Map ([
[ '1' , { id: '1' , name: 'Alice' , email: '[email protected] ' }],
[ '2' , { id: '2' , name: 'Bob' , email: '[email protected] ' }],
])
async function handler ( request : Request ) {
let url = new URL ( request . url )
if ( url . pathname === '/' && request . method === 'GET' ) {
return new Response ( 'Welcome to the User API!' )
}
if ( url . pathname === '/api/users' && request . method === 'GET' ) {
return Response . json ( Array . from ( users . values ()))
}
let userMatch = url . pathname . match ( / ^ \/ api \/ users \/ ( \w + ) $ / )
if ( userMatch && request . method === 'GET' ) {
let user = users . get ( userMatch [ 1 ])
if ( user ) {
return Response . json ( user )
}
return new Response ( 'User not found' , { status: 404 })
}
return new Response ( 'Not Found' , { status: 404 })
}
let server = http . createServer ( createRequestListener ( handler ))
server . listen ( 3000 , () => {
console . log ( 'Server running at http://localhost:3000' )
})
import { type FetchHandler } from 'remix/node-fetch-server'
let handler : FetchHandler = async ( request , client ) => {
console . log ( `Request from ${ client . address } : ${ client . port } ` )
if ( isRateLimited ( client . address )) {
return new Response ( 'Too Many Requests' , { status: 429 })
}
return Response . json ({
message: 'Hello!' ,
yourIp: client . address ,
})
}
Streaming Responses
async function handler ( request : Request ) {
if ( request . url . endsWith ( '/stream' )) {
let stream = new ReadableStream ({
async start ( controller ) {
for ( let i = 0 ; i < 5 ; i ++ ) {
controller . enqueue ( new TextEncoder (). encode ( `Chunk ${ i } \n ` ))
await new Promise (( resolve ) => setTimeout ( resolve , 1000 ))
}
controller . close ()
},
})
return new Response ( stream , {
headers: { 'Content-Type' : 'text/plain' },
})
}
return new Response ( 'Not Found' , { status: 404 })
}
HTTPS Support
import * as https from 'node:https'
import * as fs from 'node:fs'
import { createRequestListener } from 'remix/node-fetch-server'
let options = {
key: fs . readFileSync ( 'private-key.pem' ),
cert: fs . readFileSync ( 'certificate.pem' ),
}
let server = https . createServer ( options , createRequestListener ( handler ))
server . listen ( 443 , () => {
console . log ( 'HTTPS Server running on port 443' )
})
Custom Error Handling
import { createRequestListener } from 'remix/node-fetch-server'
async function errorHandler ( error : unknown ) : Promise < Response > {
console . error ( 'Server error:' , error )
if ( error instanceof Error && error . message === 'Unauthorized' ) {
return new Response ( 'Unauthorized' , { status: 401 })
}
return new Response ( 'Internal Server Error' , { status: 500 })
}
let server = http . createServer (
createRequestListener ( handler , { onError: errorHandler })
)