Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@whatwg-node/server
Advanced tools
Fetch API compliant HTTP Server adapter
@whatwg-node/server is an npm package that provides a server implementation based on the WHATWG (Web Hypertext Application Technology Working Group) standards. It aims to offer a modern, standards-compliant server environment for Node.js applications, making it easier to build web servers that adhere to web standards.
Basic HTTP Server
This code demonstrates how to create a basic HTTP server using @whatwg-node/server. The server listens on port 3000 and responds with 'Hello, world!' to any incoming request.
const { createServer } = require('@whatwg-node/server');
const server = createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, world!');
});
server.listen(3000, () => {
console.log('Server is listening on port 3000');
});
Routing
This code demonstrates basic routing with @whatwg-node/server. It handles GET requests to the root ('/') and '/about' paths, responding with 'Home Page' and 'About Page' respectively. Any other request results in a 404 'Not Found' response.
const { createServer } = require('@whatwg-node/server');
const server = createServer((req, res) => {
if (req.url === '/' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Home Page');
} else if (req.url === '/about' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('About Page');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});
server.listen(3000, () => {
console.log('Server is listening on port 3000');
});
Middleware Support
This code demonstrates how to use middleware with @whatwg-node/server. A simple logger middleware logs the request method and URL before passing control to the next function, which sends a 'Hello, world!' response.
const { createServer } = require('@whatwg-node/server');
const logger = (req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
};
const server = createServer((req, res) => {
logger(req, res, () => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, world!');
});
});
server.listen(3000, () => {
console.log('Server is listening on port 3000');
});
Express is a fast, unopinionated, minimalist web framework for Node.js. It provides a robust set of features for web and mobile applications, including routing, middleware support, and template engines. Compared to @whatwg-node/server, Express is more mature and widely used, with a larger ecosystem of middleware and plugins.
Koa is a new web framework designed by the team behind Express, aiming to be a smaller, more expressive, and more robust foundation for web applications and APIs. Koa leverages async functions to eliminate callback hell and improve error handling. Compared to @whatwg-node/server, Koa offers a more modern approach to middleware and request handling.
Hapi is a rich framework for building applications and services. It enables developers to focus on writing reusable application logic instead of spending time building infrastructure. Hapi is known for its powerful plugin system and configuration-driven approach. Compared to @whatwg-node/server, Hapi provides more built-in features and a more structured approach to building applications.
@whatwg-node/server
helps you to create a generic server implementation by using WHATWG Fetch API
for Node.js, AWS Lambda, Cloudflare Workers, Deno, Express, Fastify, Koa, Next.js and Sveltekit.
Once you create an adapter with createServerAdapter
, you don't need to install any other platform
specific package since the generic adapter will handle it automatically.
Let's create a basic Hello World server adapter.
// myServerAdapter.ts
import { createServerAdapter } from '@whatwg-node/server'
export default createServerAdapter((request: Request) => {
return new Response(`Hello World!`, { status: 200 })
})
You can use your server adapter with the following integrations:
Node.js is the most popular server side JavaScript runtime.
import { createServer } from 'http'
import myServerAdapter from './myServerAdapter'
// You can create your Node server instance by using our adapter
const nodeServer = createServer(myServerAdapter)
// Then start listening on some port
nodeServer.listen(4000)
AWS Lambda is a serverless computing platform that makes it easy to build applications that run on the AWS cloud. Our adapter is platform agnostic so they can fit together easily. In order to reduce the boilerplate we prefer to use Serverless Express from Vendia.
import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda'
import type { Handler } from '@aws-cdk/aws-lambda'
import myServerAdapter from './myServerAdapter'
interface ServerContext {
event: APIGatewayEvent
lambdaContext: Context
}
export async function handler(
event: APIGatewayEvent,
lambdaContext: Context
): Promise<APIGatewayProxyResult> {
const url = new URL(event.path, 'http://localhost')
if (event.queryStringParameters != null) {
for (const name in event.queryStringParameters) {
const value = event.queryStringParameters[name]
if (value != null) {
url.searchParams.set(name, value)
}
}
}
const response = await myServerAdapter.fetch(
url,
{
// For v1.0 you should use event.httpMethod
method: event.requestContext.http.method,
headers: event.headers as HeadersInit,
body: event.body
? Buffer.from(event.body, event.isBase64Encoded ? 'base64' : 'utf8')
: undefined
},
{
event,
lambdaContext
}
)
const responseHeaders: Record<string, string> = {}
response.headers.forEach((value, name) => {
responseHeaders[name] = value
})
return {
statusCode: response.status,
headers: responseHeaders,
body: await response.text(),
isBase64Encoded: false
}
}
Cloudflare Workers provides a serverless execution environment that allows you to create entirely new applications or augment existing ones without configuring or maintaining infrastructure. It uses Fetch API already so we can use our adapter as an event listener like below;
import myServerAdapter from './myServerAdapter'
self.addEventListener('fetch', myServerAdapter)
Deno is a simple, modern and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust. You can use our adapter as a Deno request handler like below;
import myServerAdapter from './myServerAdapter.ts'
Deno.serve(myServerAdapter)
Express is the most popular web framework for Node.js. It is a minimalist framework that provides a robust set of features to handle HTTP on Node.js applications.
You can easily integrate your adapter into your Express application with a few lines of code.
import express from 'express'
import myServerAdapter from './myServerAdapter'
const app = express()
// Bind our adapter to `/mypath` endpoint
app.use('/mypath', myServerAdapter)
app.listen(4000, () => {
console.log('Running the server at http://localhost:4000/mypath')
})
Fastify is one of the popular HTTP server frameworks for Node.js.. You can use your adapter easily with Fastify.
So you can benefit from the powerful plugins of Fastify ecosystem. See the ecosystem
import fastify, { FastifyReply, FastifyRequest } from 'fastify'
import myServerAdapter from './myServerAdapter'
// This is the fastify instance you have created
const app = fastify({ logger: true })
/**
* We pass the incoming HTTP request to our adapter
* and handle the response using Fastify's `reply` API
* Learn more about `reply` https://www.fastify.io/docs/latest/Reply/
**/
app.route({
url: '/mypath',
method: ['GET', 'POST', 'OPTIONS'],
handler: async (req, reply) => {
const response = await myServerAdapter.handleNodeRequestAndResponse(req, reply, {
req,
reply
})
response.headers.forEach((value, key) => {
reply.header(key, value)
})
reply.status(response.status)
// Fastify doesn't accept `null` as a response body
reply.send(response.body || undefined)
return reply
}
})
app.listen(4000)
Koa is another Node.js server framework designed by the team behind Express, which aims to be a smaller, more expressive. You can add your adapter to your Koa application with a few lines of code then benefit middlewares written for Koa.
import Koa from 'koa'
import myServerAdapter from './myServerAdapter'
const app = new Koa()
app.use(async ctx => {
const response = await myServerAdapter.handleNodeRequest(ctx.req)
// Set status code
ctx.status = response.status
// Set headers
response.headers.forEach((value, key) => {
ctx.append(key, value)
})
ctx.body = response.body
})
app.listen(4000, () => {
console.log('Running the server at http://localhost:4000')
})
Next.js is a web framework that allows you to build websites very quickly and our new server adapter can be integrated with Next.js easily as an API Route.
// pages/api/myEndpoint.ts
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
import myServerAdapter from './myServerAdapter'
export const config = {
api: {
// Disable body parsing if you expect a request other than JSON
bodyParser: false
}
}
export default myServerAdapter
SvelteKit is the fastest way to build svelte apps. It is very simple, and let you build frontend & backend in a single place
import myServerAdapter from './myServerAdapter'
export { myServerAdapter as get, myServerAdapter as post }
Bun is a modern JavaScript runtime like Node or Deno, and it supports Fetch API as a first class citizen. So the configuration is really simple like any other JS runtime;
import myServerAdapter from './myServerAdapter'
Bun.serve(myServerAdapter)
const server = Bun.serve(yoga)
console.info(`Server is running on ${server.hostname}`)
Multipart requests are a type of HTTP request that allows you to send blobs together with regular
text data which has a mime-type multipart/form-data
.
For example, if you send a multipart request from a browser with FormData
, you can get the same
FormData
object in your request handler.
import { createServerAdapter } from '@whatwg-node/server'
const myServerAdapter = createServerAdapter(async request => {
// Parse the request as `FormData`
const formData = await request.formData()
// Select the file
const file = formData.get('file')
// Process it as a string
const fileTextContent = await file.text()
// Select the other text parameter
const regularTextData = formData.get('additionalStuff')
// ...
return Response.json({ message: 'ok' })
})
You can learn more about File API on MDN documentation.
We'd recommend to use fets
to handle routing and middleware approach. It uses
@whatwg-node/server
under the hood.
Learn more about
fets
here
FAQs
Fetch API compliant HTTP Server adapter
The npm package @whatwg-node/server receives a total of 406,508 weekly downloads. As such, @whatwg-node/server popularity was classified as popular.
We found that @whatwg-node/server demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.