Anatomy of an HTTP Transaction
The purpose of this guide is to impart a solid understanding of the process of
Node.js HTTP handling. We'll assume that you know, in a general sense, how HTTP
requests work, regardless of language or programming environment. We'll also
assume a bit of familiarity with Node.js EventEmitters
and Streams
.
If you're not quite familiar with them, it's worth taking a quick read through
the API docs for each of those.
Create the Server
Any node web server application will at some point have to create a web server
object. This is done by using createServer
.
const module "node:http"
http = var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.require('node:http');
const const server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>
server = module "node:http"
http.function createServer<typeof http.IncomingMessage, typeof http.ServerResponse>(requestListener?: http.RequestListener<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined): http.Server<...> (+1 overload)
Returns a new instance of
{@link
Server
}
.
The `requestListener` is a function which is automatically
added to the `'request'` event.
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer();
// Listen to the request event
server.on('request', (request, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```createServer((request: http.IncomingMessage
request, response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response) => {
// magic happens here!
});
The function that's passed in to createServer
is called once for every
HTTP request that's made against that server, so it's called the request
handler. In fact, the Server
object returned by createServer
is an
EventEmitter
, and what we have here is just shorthand for creating a
server
object and then adding the listener later.
const const server: any
server = http.createServer();
const server: any
server.on('request', (request: any
request, response: any
response) => {
// the same kind of magic happens here!
});
When an HTTP request hits the server, Node calls the request handler function
with a few handy objects for dealing with the transaction, request
and
response
. We'll get to those shortly.
In order to actually serve requests, the listen
method needs to be called
on the server
object. In most cases, all you'll need to pass to listen
is
the port number you want the server to listen on. There are some other options
too, so consult the API reference.
Method, URL and Headers
When handling a request, the first thing you'll probably want to do is look at
the method and URL, so that appropriate actions can be taken. Node.js makes this
relatively painless by putting handy properties onto the request
object.
const { const method: any
method, const url: any
url } = request;
The
request
object is an instance ofIncomingMessage
.
The method
here will always be a normal HTTP method/verb. The url
is the
full URL without the server, protocol or port. For a typical URL, this means
everything after and including the third forward slash.
Headers are also not far away. They're in their own object on request
called
headers
.
const { const headers: any
headers } = request;
const const userAgent: any
userAgent = const headers: any
headers['user-agent'];
It's important to note here that all headers are represented in lower-case only, regardless of how the client actually sent them. This simplifies the task of parsing headers for whatever purpose.
If some headers are repeated, then their values are overwritten or joined
together as comma-separated strings, depending on the header. In some cases,
this can be problematic, so rawHeaders
is also available.
Request Body
When receiving a POST
or PUT
request, the request body might be important to
your application. Getting at the body data is a little more involved than
accessing request headers. The request
object that's passed in to a handler
implements the ReadableStream
interface. This stream can be listened to or
piped elsewhere just like any other stream. We can grab the data right out of
the stream by listening to the stream's 'data'
and 'end'
events.
The chunk emitted in each 'data'
event is a Buffer
. If you know it's
going to be string data, the best thing to do is collect the data in an array,
then at the 'end'
, concatenate and stringify it.
let let body: any[]
body = [];
request
.on('data', chunk: any
chunk => {
let body: any[]
body.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.push(chunk: any
chunk);
})
.on('end', () => {
let body: any[]
body = var Buffer: BufferConstructor
Buffer.BufferConstructor.concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>
Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together.
If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned.
If `totalLength` is not provided, it is calculated from the `Buffer` instances
in `list` by adding their lengths.
If `totalLength` is provided, it is coerced to an unsigned integer. If the
combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is
truncated to `totalLength`. If the combined length of the `Buffer`s in `list` is
less than `totalLength`, the remaining space is filled with zeros.
```js
import { Buffer } from 'node:buffer';
// Create a single `Buffer` from a list of three `Buffer` instances.
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;
console.log(totalLength);
// Prints: 42
const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
console.log(bufA);
// Prints: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42
```
`Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.concat(let body: any[]
body).Buffer<ArrayBuffer>.toString(encoding?: BufferEncoding, start?: number, end?: number): string
Decodes `buf` to a string according to the specified character encoding in`encoding`. `start` and `end` may be passed to decode only a subset of `buf`.
If `encoding` is `'utf8'` and a byte sequence in the input is not valid UTF-8,
then each invalid byte is replaced with the replacement character `U+FFFD`.
The maximum length of a string instance (in UTF-16 code units) is available
as
{@link
constants.MAX_STRING_LENGTH
}
.
```js
import { Buffer } from 'node:buffer';
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 is the decimal ASCII value for 'a'.
buf1[i] = i + 97;
}
console.log(buf1.toString('utf8'));
// Prints: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('utf8', 0, 5));
// Prints: abcde
const buf2 = Buffer.from('tést');
console.log(buf2.toString('hex'));
// Prints: 74c3a97374
console.log(buf2.toString('utf8', 0, 3));
// Prints: té
console.log(buf2.toString(undefined, 0, 3));
// Prints: té
```toString();
// at this point, `body` has the entire request body stored in it as a string
});
This may seem a tad tedious, and in many cases, it is. Luckily, there are modules like
concat-stream
andbody
onnpm
which can help hide away some of this logic. It's important to have a good understanding of what's going on before going down that road, and that's why you're here!
A Quick Thing About Errors
Since the request
object is a ReadableStream
, it's also an
EventEmitter
and behaves like one when an error happens.
An error in the request
stream presents itself by emitting an 'error'
event
on the stream. If you don't have a listener for that event, the error will be
thrown, which could crash your Node.js program. You should therefore add an
'error'
listener on your request streams, even if you just log it and
continue on your way. (Though it's probably best to send some kind of HTTP error
response. More on that later.)
request.on('error', err: any
err => {
// This prints the error message and stack trace to `stderr`.
var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```console.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr
```
If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the
resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
for more information.error(err: any
err.stack);
});
There are other ways of handling these errors such as other abstractions and tools, but always be aware that errors can and do happen, and you're going to have to deal with them.
What We've Got so Far
At this point, we've covered creating a server, and grabbing the method, URL, headers and body out of requests. When we put that all together, it might look something like this:
const module "node:http"
http = var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.require('node:http');
module "node:http"
http
.function createServer<typeof http.IncomingMessage, typeof http.ServerResponse>(requestListener?: http.RequestListener<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined): http.Server<...> (+1 overload)
Returns a new instance of
{@link
Server
}
.
The `requestListener` is a function which is automatically
added to the `'request'` event.
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer();
// Listen to the request event
server.on('request', (request, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```createServer((request: http.IncomingMessage
request, response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response) => {
const { const headers: http.IncomingHttpHeaders
The request/response headers object.
Key-value pairs of header names and values. Header names are lower-cased.
```js
// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*' }
console.log(request.headers);
```
Duplicates in raw headers are handled in the following ways, depending on the
header name:
* Duplicates of `age`, `authorization`, `content-length`, `content-type`, `etag`, `expires`, `from`, `host`, `if-modified-since`, `if-unmodified-since`, `last-modified`, `location`,
`max-forwards`, `proxy-authorization`, `referer`, `retry-after`, `server`, or `user-agent` are discarded.
To allow duplicate values of the headers listed above to be joined,
use the option `joinDuplicateHeaders` in
{@link
request
}
and
{@link
createServer
}
. See RFC 9110 Section 5.3 for more
information.
* `set-cookie` is always an array. Duplicates are added to the array.
* For duplicate `cookie` headers, the values are joined together with `; `.
* For all other headers, the values are joined together with `, `.headers, const method: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
The request method as a string. Read only. Examples: `'GET'`, `'DELETE'`.method, const url: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
Request URL string. This contains only the URL that is present in the actual
HTTP request. Take the following request:
```http
GET /status?name=ryan HTTP/1.1
Accept: text/plain
```
To parse the URL into its parts:
```js
new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
```
When `request.url` is `'/status?name=ryan'` and `process.env.HOST` is undefined:
```console
$ node
> new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
URL {
href: 'http://localhost/status?name=ryan',
origin: 'http://localhost',
protocol: 'http:',
username: '',
password: '',
host: 'localhost',
hostname: 'localhost',
port: '',
pathname: '/status',
search: '?name=ryan',
searchParams: URLSearchParams { 'name' => 'ryan' },
hash: ''
}
```
Ensure that you set `process.env.HOST` to the server's host name, or consider replacing this part entirely. If using `req.headers.host`, ensure proper
validation is used, as clients may specify a custom `Host` header.url } = request: http.IncomingMessage
request;
let let body: any[]
body = [];
request: http.IncomingMessage
request
.Stream.Readable.on(event: "error", listener: (err: Error) => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('error', err: Error
err => {
var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```console.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr
```
If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the
resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
for more information.error(err: Error
err);
})
.Stream.Readable.on(event: "data", listener: (chunk: any) => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('data', chunk: any
chunk => {
let body: any[]
body.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.push(chunk: any
chunk);
})
.Stream.Readable.on(event: "end", listener: () => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('end', () => {
let body: any[]
body = var Buffer: BufferConstructor
Buffer.BufferConstructor.concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>
Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together.
If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned.
If `totalLength` is not provided, it is calculated from the `Buffer` instances
in `list` by adding their lengths.
If `totalLength` is provided, it is coerced to an unsigned integer. If the
combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is
truncated to `totalLength`. If the combined length of the `Buffer`s in `list` is
less than `totalLength`, the remaining space is filled with zeros.
```js
import { Buffer } from 'node:buffer';
// Create a single `Buffer` from a list of three `Buffer` instances.
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;
console.log(totalLength);
// Prints: 42
const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
console.log(bufA);
// Prints: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42
```
`Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.concat(let body: any[]
body).Buffer<ArrayBuffer>.toString(encoding?: BufferEncoding, start?: number, end?: number): string
Decodes `buf` to a string according to the specified character encoding in`encoding`. `start` and `end` may be passed to decode only a subset of `buf`.
If `encoding` is `'utf8'` and a byte sequence in the input is not valid UTF-8,
then each invalid byte is replaced with the replacement character `U+FFFD`.
The maximum length of a string instance (in UTF-16 code units) is available
as
{@link
constants.MAX_STRING_LENGTH
}
.
```js
import { Buffer } from 'node:buffer';
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 is the decimal ASCII value for 'a'.
buf1[i] = i + 97;
}
console.log(buf1.toString('utf8'));
// Prints: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('utf8', 0, 5));
// Prints: abcde
const buf2 = Buffer.from('tést');
console.log(buf2.toString('hex'));
// Prints: 74c3a97374
console.log(buf2.toString('utf8', 0, 3));
// Prints: té
console.log(buf2.toString(undefined, 0, 3));
// Prints: té
```toString();
// At this point, we have the headers, method, url and body, and can now
// do whatever we need to in order to respond to this request.
});
})
.Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or
an `IPC` server depending on what it listens to.
Possible signatures:
* `server.listen(handle[, backlog][, callback])`
* `server.listen(options[, callback])`
* `server.listen(path[, backlog][, callback])` for `IPC` servers
* `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
event.
All `listen()` methods can take a `backlog` parameter to specify the maximum
length of the queue of pending connections. The actual length will be determined
by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512).
All
{@link
Socket
}
are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
details).
The `server.listen()` method can be called again if and only if there was an
error during the first `server.listen()` call or `server.close()` has been
called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
One of the most common errors raised when listening is `EADDRINUSE`.
This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
after a certain amount of time:
```js
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
console.error('Address in use, retrying...');
setTimeout(() => {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
```listen(8080); // Activates this server, listening on port 8080.
If we run this example, we'll be able to receive requests, but not respond to them. In fact, if you hit this example in a web browser, your request would time out, as nothing is being sent back to the client.
So far we haven't touched on the response
object at all, which is an instance
of ServerResponse
, which is a WritableStream
. It contains many
useful methods for sending data back to the client. We'll cover that next.
HTTP Status Code
If you don't bother setting it, the HTTP status code on a response will always
be 200. Of course, not every HTTP response warrants this, and at some point
you'll definitely want to send a different status code. To do that, you can set
the statusCode
property.
module response
response.response.statusCode: number
statusCode = 404; // Tell the client that the resource wasn't found.
There are some other shortcuts to this, as we'll see soon.
Setting Response Headers
Headers are set through a convenient method called setHeader
.
response.setHeader('Content-Type', 'application/json');
response.setHeader('X-Powered-By', 'bacon');
When setting the headers on a response, the case is insensitive on their names. If you set a header repeatedly, the last value you set is the value that gets sent.
Explicitly Sending Header Data
The methods of setting the headers and status code that we've already discussed assume that you're using "implicit headers". This means you're counting on node to send the headers for you at the correct time before you start sending body data.
If you want, you can explicitly write the headers to the response stream.
To do this, there's a method called writeHead
, which writes the status
code and the headers to the stream.
response.writeHead(200, {
'Content-Type': 'application/json',
'X-Powered-By': 'bacon',
});
Once you've set the headers (either implicitly or explicitly), you're ready to start sending response data.
Sending Response Body
Since the response
object is a WritableStream
, writing a response body
out to the client is just a matter of using the usual stream methods.
response.write('<html>');
response.write('<body>');
response.write('<h1>Hello, World!</h1>');
response.write('</body>');
response.write('</html>');
response.end();
The end
function on streams can also take in some optional data to send as the
last bit of data on the stream, so we can simplify the example above as follows.
response.end('<html><body><h1>Hello, World!</h1></body></html>');
It's important to set the status and headers before you start writing chunks of data to the body. This makes sense, since headers come before the body in HTTP responses.
Another Quick Thing About Errors
The response
stream can also emit 'error'
events, and at some point you're
going to have to deal with that as well. All of the advice for request
stream
errors still applies here.
Put It All Together
Now that we've learned about making HTTP responses, let's put it all together.
Building on the earlier example, we're going to make a server that sends back
all of the data that was sent to us by the user. We'll format that data as JSON
using JSON.stringify
.
const module "node:http"
http = var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.require('node:http');
module "node:http"
http
.function createServer<typeof http.IncomingMessage, typeof http.ServerResponse>(requestListener?: http.RequestListener<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined): http.Server<...> (+1 overload)
Returns a new instance of
{@link
Server
}
.
The `requestListener` is a function which is automatically
added to the `'request'` event.
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer();
// Listen to the request event
server.on('request', (request, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```createServer((request: http.IncomingMessage
request, response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response) => {
const { const headers: http.IncomingHttpHeaders
The request/response headers object.
Key-value pairs of header names and values. Header names are lower-cased.
```js
// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*' }
console.log(request.headers);
```
Duplicates in raw headers are handled in the following ways, depending on the
header name:
* Duplicates of `age`, `authorization`, `content-length`, `content-type`, `etag`, `expires`, `from`, `host`, `if-modified-since`, `if-unmodified-since`, `last-modified`, `location`,
`max-forwards`, `proxy-authorization`, `referer`, `retry-after`, `server`, or `user-agent` are discarded.
To allow duplicate values of the headers listed above to be joined,
use the option `joinDuplicateHeaders` in
{@link
request
}
and
{@link
createServer
}
. See RFC 9110 Section 5.3 for more
information.
* `set-cookie` is always an array. Duplicates are added to the array.
* For duplicate `cookie` headers, the values are joined together with `; `.
* For all other headers, the values are joined together with `, `.headers, const method: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
The request method as a string. Read only. Examples: `'GET'`, `'DELETE'`.method, const url: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
Request URL string. This contains only the URL that is present in the actual
HTTP request. Take the following request:
```http
GET /status?name=ryan HTTP/1.1
Accept: text/plain
```
To parse the URL into its parts:
```js
new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
```
When `request.url` is `'/status?name=ryan'` and `process.env.HOST` is undefined:
```console
$ node
> new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
URL {
href: 'http://localhost/status?name=ryan',
origin: 'http://localhost',
protocol: 'http:',
username: '',
password: '',
host: 'localhost',
hostname: 'localhost',
port: '',
pathname: '/status',
search: '?name=ryan',
searchParams: URLSearchParams { 'name' => 'ryan' },
hash: ''
}
```
Ensure that you set `process.env.HOST` to the server's host name, or consider replacing this part entirely. If using `req.headers.host`, ensure proper
validation is used, as clients may specify a custom `Host` header.url } = request: http.IncomingMessage
request;
let let body: any[]
body = [];
request: http.IncomingMessage
request
.Stream.Readable.on(event: "error", listener: (err: Error) => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('error', err: Error
err => {
var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```console.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr
```
If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the
resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
for more information.error(err: Error
err);
})
.Stream.Readable.on(event: "data", listener: (chunk: any) => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('data', chunk: any
chunk => {
let body: any[]
body.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.push(chunk: any
chunk);
})
.Stream.Readable.on(event: "end", listener: () => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('end', () => {
let body: any[]
body = var Buffer: BufferConstructor
Buffer.BufferConstructor.concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>
Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together.
If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned.
If `totalLength` is not provided, it is calculated from the `Buffer` instances
in `list` by adding their lengths.
If `totalLength` is provided, it is coerced to an unsigned integer. If the
combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is
truncated to `totalLength`. If the combined length of the `Buffer`s in `list` is
less than `totalLength`, the remaining space is filled with zeros.
```js
import { Buffer } from 'node:buffer';
// Create a single `Buffer` from a list of three `Buffer` instances.
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;
console.log(totalLength);
// Prints: 42
const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
console.log(bufA);
// Prints: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42
```
`Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.concat(let body: any[]
body).Buffer<ArrayBuffer>.toString(encoding?: BufferEncoding, start?: number, end?: number): string
Decodes `buf` to a string according to the specified character encoding in`encoding`. `start` and `end` may be passed to decode only a subset of `buf`.
If `encoding` is `'utf8'` and a byte sequence in the input is not valid UTF-8,
then each invalid byte is replaced with the replacement character `U+FFFD`.
The maximum length of a string instance (in UTF-16 code units) is available
as
{@link
constants.MAX_STRING_LENGTH
}
.
```js
import { Buffer } from 'node:buffer';
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 is the decimal ASCII value for 'a'.
buf1[i] = i + 97;
}
console.log(buf1.toString('utf8'));
// Prints: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('utf8', 0, 5));
// Prints: abcde
const buf2 = Buffer.from('tést');
console.log(buf2.toString('hex'));
// Prints: 74c3a97374
console.log(buf2.toString('utf8', 0, 3));
// Prints: té
console.log(buf2.toString(undefined, 0, 3));
// Prints: té
```toString();
// BEGINNING OF NEW STUFF
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.on(event: "error", listener: (err: Error) => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+6 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('error', err: Error
err => {
var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```console.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr
```
If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the
resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
for more information.error(err: Error
err);
});
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.ServerResponse<Request extends IncomingMessage = IncomingMessage>.statusCode: number
When using implicit headers (not calling `response.writeHead()` explicitly),
this property controls the status code that will be sent to the client when
the headers get flushed.
```js
response.statusCode = 404;
```
After response header was sent to the client, this property indicates the
status code which was sent out.statusCode = 200;
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.OutgoingMessage<IncomingMessage>.setHeader(name: string, value: number | string | readonly string[]): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
Sets a single header value. If the header already exists in the to-be-sent
headers, its value will be replaced. Use an array of strings to send multiple
headers with the same name.setHeader('Content-Type', 'application/json');
// Note: the 2 lines above could be replaced with this next one:
// response.writeHead(200, {'Content-Type': 'application/json'})
const const responseBody: {
headers: http.IncomingHttpHeaders;
method: string | undefined;
url: string | undefined;
body: any[];
}
responseBody = { headers: http.IncomingHttpHeaders
headers, method: string | undefined
method, url: string | undefined
url, body: any[]
body };
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.write(chunk: any, callback?: (error: Error | null | undefined) => void): boolean (+1 overload)
The `writable.write()` method writes some data to the stream, and calls the
supplied `callback` once the data has been fully handled. If an error
occurs, the `callback` will be called with the error as its
first argument. The `callback` is called asynchronously and before `'error'` is
emitted.
The return value is `true` if the internal buffer is less than the `highWaterMark` configured when the stream was created after admitting `chunk`.
If `false` is returned, further attempts to write data to the stream should
stop until the `'drain'` event is emitted.
While a stream is not draining, calls to `write()` will buffer `chunk`, and
return false. Once all currently buffered chunks are drained (accepted for
delivery by the operating system), the `'drain'` event will be emitted.
Once `write()` returns false, do not write more chunks
until the `'drain'` event is emitted. While calling `write()` on a stream that
is not draining is allowed, Node.js will buffer all written chunks until
maximum memory usage occurs, at which point it will abort unconditionally.
Even before it aborts, high memory usage will cause poor garbage collector
performance and high RSS (which is not typically released back to the system,
even after the memory is no longer required). Since TCP sockets may never
drain if the remote peer does not read the data, writing a socket that is
not draining may lead to a remotely exploitable vulnerability.
Writing data while the stream is not draining is particularly
problematic for a `Transform`, because the `Transform` streams are paused
by default until they are piped or a `'data'` or `'readable'` event handler
is added.
If the data to be written can be generated or fetched on demand, it is
recommended to encapsulate the logic into a `Readable` and use
{@link
pipe
}
. However, if calling `write()` is preferred, it is
possible to respect backpressure and avoid memory issues using the `'drain'` event:
```js
function write(data, cb) {
if (!stream.write(data)) {
stream.once('drain', cb);
} else {
process.nextTick(cb);
}
}
// Wait for cb to be called before doing any other write.
write('hello', () => {
console.log('Write completed, do more writes now.');
});
```
A `Writable` stream in object mode will always ignore the `encoding` argument.write(var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.JSON.JSON.stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string (+1 overload)
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.stringify(const responseBody: {
headers: http.IncomingHttpHeaders;
method: string | undefined;
url: string | undefined;
body: any[];
}
responseBody));
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.end(cb?: () => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+2 overloads)
Calling the `writable.end()` method signals that no more data will be written
to the `Writable`. The optional `chunk` and `encoding` arguments allow one
final additional chunk of data to be written immediately before closing the
stream.
Calling the
{@link
write
}
method after calling
{@link
end
}
will raise an error.
```js
// Write 'hello, ' and then end with 'world!'.
import fs from 'node:fs';
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// Writing more now is not allowed!
```end();
// Note: the 2 lines above could be replaced with this next one:
// response.end(JSON.stringify(responseBody))
// END OF NEW STUFF
});
})
.Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or
an `IPC` server depending on what it listens to.
Possible signatures:
* `server.listen(handle[, backlog][, callback])`
* `server.listen(options[, callback])`
* `server.listen(path[, backlog][, callback])` for `IPC` servers
* `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
event.
All `listen()` methods can take a `backlog` parameter to specify the maximum
length of the queue of pending connections. The actual length will be determined
by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512).
All
{@link
Socket
}
are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
details).
The `server.listen()` method can be called again if and only if there was an
error during the first `server.listen()` call or `server.close()` has been
called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
One of the most common errors raised when listening is `EADDRINUSE`.
This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
after a certain amount of time:
```js
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
console.error('Address in use, retrying...');
setTimeout(() => {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
```listen(8080);
Echo Server Example
Let's simplify the previous example to make a simple echo server, which just sends whatever data is received in the request right back in the response. All we need to do is grab the data from the request stream and write that data to the response stream, similar to what we did previously.
const module "node:http"
http = var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.require('node:http');
module "node:http"
http
.function createServer<typeof http.IncomingMessage, typeof http.ServerResponse>(requestListener?: http.RequestListener<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined): http.Server<...> (+1 overload)
Returns a new instance of
{@link
Server
}
.
The `requestListener` is a function which is automatically
added to the `'request'` event.
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer();
// Listen to the request event
server.on('request', (request, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```createServer((request: http.IncomingMessage
request, response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response) => {
let let body: any[]
body = [];
request: http.IncomingMessage
request
.Stream.Readable.on(event: "data", listener: (chunk: any) => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('data', chunk: any
chunk => {
let body: any[]
body.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.push(chunk: any
chunk);
})
.Stream.Readable.on(event: "end", listener: () => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('end', () => {
let body: any[]
body = var Buffer: BufferConstructor
Buffer.BufferConstructor.concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>
Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together.
If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned.
If `totalLength` is not provided, it is calculated from the `Buffer` instances
in `list` by adding their lengths.
If `totalLength` is provided, it is coerced to an unsigned integer. If the
combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is
truncated to `totalLength`. If the combined length of the `Buffer`s in `list` is
less than `totalLength`, the remaining space is filled with zeros.
```js
import { Buffer } from 'node:buffer';
// Create a single `Buffer` from a list of three `Buffer` instances.
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;
console.log(totalLength);
// Prints: 42
const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
console.log(bufA);
// Prints: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42
```
`Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.concat(let body: any[]
body).Buffer<ArrayBuffer>.toString(encoding?: BufferEncoding, start?: number, end?: number): string
Decodes `buf` to a string according to the specified character encoding in`encoding`. `start` and `end` may be passed to decode only a subset of `buf`.
If `encoding` is `'utf8'` and a byte sequence in the input is not valid UTF-8,
then each invalid byte is replaced with the replacement character `U+FFFD`.
The maximum length of a string instance (in UTF-16 code units) is available
as
{@link
constants.MAX_STRING_LENGTH
}
.
```js
import { Buffer } from 'node:buffer';
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 is the decimal ASCII value for 'a'.
buf1[i] = i + 97;
}
console.log(buf1.toString('utf8'));
// Prints: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('utf8', 0, 5));
// Prints: abcde
const buf2 = Buffer.from('tést');
console.log(buf2.toString('hex'));
// Prints: 74c3a97374
console.log(buf2.toString('utf8', 0, 3));
// Prints: té
console.log(buf2.toString(undefined, 0, 3));
// Prints: té
```toString();
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.end(chunk: any, cb?: () => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+2 overloads)
Calling the `writable.end()` method signals that no more data will be written
to the `Writable`. The optional `chunk` and `encoding` arguments allow one
final additional chunk of data to be written immediately before closing the
stream.
Calling the
{@link
write
}
method after calling
{@link
end
}
will raise an error.
```js
// Write 'hello, ' and then end with 'world!'.
import fs from 'node:fs';
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// Writing more now is not allowed!
```end(let body: any[]
body);
});
})
.Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or
an `IPC` server depending on what it listens to.
Possible signatures:
* `server.listen(handle[, backlog][, callback])`
* `server.listen(options[, callback])`
* `server.listen(path[, backlog][, callback])` for `IPC` servers
* `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
event.
All `listen()` methods can take a `backlog` parameter to specify the maximum
length of the queue of pending connections. The actual length will be determined
by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512).
All
{@link
Socket
}
are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
details).
The `server.listen()` method can be called again if and only if there was an
error during the first `server.listen()` call or `server.close()` has been
called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
One of the most common errors raised when listening is `EADDRINUSE`.
This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
after a certain amount of time:
```js
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
console.error('Address in use, retrying...');
setTimeout(() => {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
```listen(8080);
Now let's tweak this. We want to only send an echo under the following conditions:
- The request method is POST.
- The URL is
/echo
.
In any other case, we want to simply respond with a 404.
const module "node:http"
http = var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.require('node:http');
module "node:http"
http
.function createServer<typeof http.IncomingMessage, typeof http.ServerResponse>(requestListener?: http.RequestListener<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined): http.Server<...> (+1 overload)
Returns a new instance of
{@link
Server
}
.
The `requestListener` is a function which is automatically
added to the `'request'` event.
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer();
// Listen to the request event
server.on('request', (request, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```createServer((request: http.IncomingMessage
request, response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response) => {
if (request: http.IncomingMessage
request.IncomingMessage.method?: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
The request method as a string. Read only. Examples: `'GET'`, `'DELETE'`.method === 'POST' && request: http.IncomingMessage
request.IncomingMessage.url?: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
Request URL string. This contains only the URL that is present in the actual
HTTP request. Take the following request:
```http
GET /status?name=ryan HTTP/1.1
Accept: text/plain
```
To parse the URL into its parts:
```js
new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
```
When `request.url` is `'/status?name=ryan'` and `process.env.HOST` is undefined:
```console
$ node
> new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
URL {
href: 'http://localhost/status?name=ryan',
origin: 'http://localhost',
protocol: 'http:',
username: '',
password: '',
host: 'localhost',
hostname: 'localhost',
port: '',
pathname: '/status',
search: '?name=ryan',
searchParams: URLSearchParams { 'name' => 'ryan' },
hash: ''
}
```
Ensure that you set `process.env.HOST` to the server's host name, or consider replacing this part entirely. If using `req.headers.host`, ensure proper
validation is used, as clients may specify a custom `Host` header.url === '/echo') {
let let body: any[]
body = [];
request: http.IncomingMessage
request
.Stream.Readable.on(event: "data", listener: (chunk: any) => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('data', chunk: any
chunk => {
let body: any[]
body.Array<any>.push(...items: any[]): number
Appends new elements to the end of an array, and returns the new length of the array.push(chunk: any
chunk);
})
.Stream.Readable.on(event: "end", listener: () => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('end', () => {
let body: any[]
body = var Buffer: BufferConstructor
Buffer.BufferConstructor.concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>
Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together.
If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned.
If `totalLength` is not provided, it is calculated from the `Buffer` instances
in `list` by adding their lengths.
If `totalLength` is provided, it is coerced to an unsigned integer. If the
combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is
truncated to `totalLength`. If the combined length of the `Buffer`s in `list` is
less than `totalLength`, the remaining space is filled with zeros.
```js
import { Buffer } from 'node:buffer';
// Create a single `Buffer` from a list of three `Buffer` instances.
const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;
console.log(totalLength);
// Prints: 42
const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
console.log(bufA);
// Prints: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// Prints: 42
```
`Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.concat(let body: any[]
body).Buffer<ArrayBuffer>.toString(encoding?: BufferEncoding, start?: number, end?: number): string
Decodes `buf` to a string according to the specified character encoding in`encoding`. `start` and `end` may be passed to decode only a subset of `buf`.
If `encoding` is `'utf8'` and a byte sequence in the input is not valid UTF-8,
then each invalid byte is replaced with the replacement character `U+FFFD`.
The maximum length of a string instance (in UTF-16 code units) is available
as
{@link
constants.MAX_STRING_LENGTH
}
.
```js
import { Buffer } from 'node:buffer';
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 is the decimal ASCII value for 'a'.
buf1[i] = i + 97;
}
console.log(buf1.toString('utf8'));
// Prints: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('utf8', 0, 5));
// Prints: abcde
const buf2 = Buffer.from('tést');
console.log(buf2.toString('hex'));
// Prints: 74c3a97374
console.log(buf2.toString('utf8', 0, 3));
// Prints: té
console.log(buf2.toString(undefined, 0, 3));
// Prints: té
```toString();
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.end(chunk: any, cb?: () => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+2 overloads)
Calling the `writable.end()` method signals that no more data will be written
to the `Writable`. The optional `chunk` and `encoding` arguments allow one
final additional chunk of data to be written immediately before closing the
stream.
Calling the
{@link
write
}
method after calling
{@link
end
}
will raise an error.
```js
// Write 'hello, ' and then end with 'world!'.
import fs from 'node:fs';
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// Writing more now is not allowed!
```end(let body: any[]
body);
});
} else {
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.ServerResponse<Request extends IncomingMessage = IncomingMessage>.statusCode: number
When using implicit headers (not calling `response.writeHead()` explicitly),
this property controls the status code that will be sent to the client when
the headers get flushed.
```js
response.statusCode = 404;
```
After response header was sent to the client, this property indicates the
status code which was sent out.statusCode = 404;
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.end(cb?: () => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+2 overloads)
Calling the `writable.end()` method signals that no more data will be written
to the `Writable`. The optional `chunk` and `encoding` arguments allow one
final additional chunk of data to be written immediately before closing the
stream.
Calling the
{@link
write
}
method after calling
{@link
end
}
will raise an error.
```js
// Write 'hello, ' and then end with 'world!'.
import fs from 'node:fs';
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// Writing more now is not allowed!
```end();
}
})
.Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or
an `IPC` server depending on what it listens to.
Possible signatures:
* `server.listen(handle[, backlog][, callback])`
* `server.listen(options[, callback])`
* `server.listen(path[, backlog][, callback])` for `IPC` servers
* `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
event.
All `listen()` methods can take a `backlog` parameter to specify the maximum
length of the queue of pending connections. The actual length will be determined
by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512).
All
{@link
Socket
}
are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
details).
The `server.listen()` method can be called again if and only if there was an
error during the first `server.listen()` call or `server.close()` has been
called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
One of the most common errors raised when listening is `EADDRINUSE`.
This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
after a certain amount of time:
```js
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
console.error('Address in use, retrying...');
setTimeout(() => {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
```listen(8080);
By checking the URL in this way, we're doing a form of "routing". Other forms of routing can be as simple as
switch
statements or as complex as whole frameworks likeexpress
. If you're looking for something that does routing and nothing else, tryrouter
.
Great! Now let's take a stab at simplifying this. Remember, the request
object
is a ReadableStream
and the response
object is a WritableStream
.
That means we can use pipe
to direct data from one to the other. That's
exactly what we want for an echo server!
const module "node:http"
http = var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.require('node:http');
module "node:http"
http
.function createServer<typeof http.IncomingMessage, typeof http.ServerResponse>(requestListener?: http.RequestListener<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined): http.Server<...> (+1 overload)
Returns a new instance of
{@link
Server
}
.
The `requestListener` is a function which is automatically
added to the `'request'` event.
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer();
// Listen to the request event
server.on('request', (request, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```createServer((request: http.IncomingMessage
request, response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response) => {
if (request: http.IncomingMessage
request.IncomingMessage.method?: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
The request method as a string. Read only. Examples: `'GET'`, `'DELETE'`.method === 'POST' && request: http.IncomingMessage
request.IncomingMessage.url?: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
Request URL string. This contains only the URL that is present in the actual
HTTP request. Take the following request:
```http
GET /status?name=ryan HTTP/1.1
Accept: text/plain
```
To parse the URL into its parts:
```js
new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
```
When `request.url` is `'/status?name=ryan'` and `process.env.HOST` is undefined:
```console
$ node
> new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
URL {
href: 'http://localhost/status?name=ryan',
origin: 'http://localhost',
protocol: 'http:',
username: '',
password: '',
host: 'localhost',
hostname: 'localhost',
port: '',
pathname: '/status',
search: '?name=ryan',
searchParams: URLSearchParams { 'name' => 'ryan' },
hash: ''
}
```
Ensure that you set `process.env.HOST` to the server's host name, or consider replacing this part entirely. If using `req.headers.host`, ensure proper
validation is used, as clients may specify a custom `Host` header.url === '/echo') {
request: http.IncomingMessage
request.Stream.pipe<http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}>(destination: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}, options?: {
...;
} | undefined): http.ServerResponse<...> & {
req: http.IncomingMessage;
}
pipe(response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response);
} else {
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.ServerResponse<Request extends IncomingMessage = IncomingMessage>.statusCode: number
When using implicit headers (not calling `response.writeHead()` explicitly),
this property controls the status code that will be sent to the client when
the headers get flushed.
```js
response.statusCode = 404;
```
After response header was sent to the client, this property indicates the
status code which was sent out.statusCode = 404;
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.end(cb?: () => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+2 overloads)
Calling the `writable.end()` method signals that no more data will be written
to the `Writable`. The optional `chunk` and `encoding` arguments allow one
final additional chunk of data to be written immediately before closing the
stream.
Calling the
{@link
write
}
method after calling
{@link
end
}
will raise an error.
```js
// Write 'hello, ' and then end with 'world!'.
import fs from 'node:fs';
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// Writing more now is not allowed!
```end();
}
})
.Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or
an `IPC` server depending on what it listens to.
Possible signatures:
* `server.listen(handle[, backlog][, callback])`
* `server.listen(options[, callback])`
* `server.listen(path[, backlog][, callback])` for `IPC` servers
* `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
event.
All `listen()` methods can take a `backlog` parameter to specify the maximum
length of the queue of pending connections. The actual length will be determined
by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512).
All
{@link
Socket
}
are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
details).
The `server.listen()` method can be called again if and only if there was an
error during the first `server.listen()` call or `server.close()` has been
called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
One of the most common errors raised when listening is `EADDRINUSE`.
This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
after a certain amount of time:
```js
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
console.error('Address in use, retrying...');
setTimeout(() => {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
```listen(8080);
Yay streams!
We're not quite done yet though. As mentioned multiple times in this guide, errors can and do happen, and we need to deal with them.
To handle errors on the request stream, we'll log the error to stderr
and send
a 400 status code to indicate a Bad Request
. In a real-world application,
though, we'd want to inspect the error to figure out what the correct status code
and message would be. As usual with errors, you should consult the
Error
documentation.
On the response, we'll just log the error to stderr
.
const module "node:http"
http = var require: NodeJS.Require
(id: string) => any
Used to import modules, `JSON`, and local files.require('node:http');
module "node:http"
http
.function createServer<typeof http.IncomingMessage, typeof http.ServerResponse>(requestListener?: http.RequestListener<typeof http.IncomingMessage, typeof http.ServerResponse> | undefined): http.Server<...> (+1 overload)
Returns a new instance of
{@link
Server
}
.
The `requestListener` is a function which is automatically
added to the `'request'` event.
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```
```js
import http from 'node:http';
// Create a local server to receive data from
const server = http.createServer();
// Listen to the request event
server.on('request', (request, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
data: 'Hello World!',
}));
});
server.listen(8000);
```createServer((request: http.IncomingMessage
request, response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response) => {
request: http.IncomingMessage
request.Stream.Readable.on(event: "error", listener: (err: Error) => void): http.IncomingMessage (+7 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('error', err: Error
err => {
var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```console.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr
```
If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the
resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
for more information.error(err: Error
err);
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.ServerResponse<Request extends IncomingMessage = IncomingMessage>.statusCode: number
When using implicit headers (not calling `response.writeHead()` explicitly),
this property controls the status code that will be sent to the client when
the headers get flushed.
```js
response.statusCode = 404;
```
After response header was sent to the client, this property indicates the
status code which was sent out.statusCode = 400;
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.end(cb?: () => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+2 overloads)
Calling the `writable.end()` method signals that no more data will be written
to the `Writable`. The optional `chunk` and `encoding` arguments allow one
final additional chunk of data to be written immediately before closing the
stream.
Calling the
{@link
write
}
method after calling
{@link
end
}
will raise an error.
```js
// Write 'hello, ' and then end with 'world!'.
import fs from 'node:fs';
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// Writing more now is not allowed!
```end();
});
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.on(event: "error", listener: (err: Error) => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+6 overloads)
Adds the `listener` function to the end of the listeners array for the event
named `eventName`. No checks are made to see if the `listener` has already
been added. Multiple calls passing the same combination of `eventName` and
`listener` will result in the `listener` being added, and called, multiple times.
```js
server.on('connection', (stream) => {
console.log('someone connected!');
});
```
Returns a reference to the `EventEmitter`, so that calls can be chained.
By default, event listeners are invoked in the order they are added. The `emitter.prependListener()` method can be used as an alternative to add the
event listener to the beginning of the listeners array.
```js
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
```on('error', err: Error
err => {
var console: Console
The `console` module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
* A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
* A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
[`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
_**Warning**_: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
more information.
Example using the global `console`:
```js
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
```
Example using the `Console` class:
```js
const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
```console.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
(the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
```js
const code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr
```
If formatting elements (e.g. `%d`) are not found in the first string then
[`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the
resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
for more information.error(err: Error
err);
});
if (request: http.IncomingMessage
request.IncomingMessage.method?: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
The request method as a string. Read only. Examples: `'GET'`, `'DELETE'`.method === 'POST' && request: http.IncomingMessage
request.IncomingMessage.url?: string | undefined
**Only valid for request obtained from
{@link
Server
}
.**
Request URL string. This contains only the URL that is present in the actual
HTTP request. Take the following request:
```http
GET /status?name=ryan HTTP/1.1
Accept: text/plain
```
To parse the URL into its parts:
```js
new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
```
When `request.url` is `'/status?name=ryan'` and `process.env.HOST` is undefined:
```console
$ node
> new URL(`http://${process.env.HOST ?? 'localhost'}${request.url}`);
URL {
href: 'http://localhost/status?name=ryan',
origin: 'http://localhost',
protocol: 'http:',
username: '',
password: '',
host: 'localhost',
hostname: 'localhost',
port: '',
pathname: '/status',
search: '?name=ryan',
searchParams: URLSearchParams { 'name' => 'ryan' },
hash: ''
}
```
Ensure that you set `process.env.HOST` to the server's host name, or consider replacing this part entirely. If using `req.headers.host`, ensure proper
validation is used, as clients may specify a custom `Host` header.url === '/echo') {
request: http.IncomingMessage
request.Stream.pipe<http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}>(destination: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}, options?: {
...;
} | undefined): http.ServerResponse<...> & {
req: http.IncomingMessage;
}
pipe(response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response);
} else {
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.ServerResponse<Request extends IncomingMessage = IncomingMessage>.statusCode: number
When using implicit headers (not calling `response.writeHead()` explicitly),
this property controls the status code that will be sent to the client when
the headers get flushed.
```js
response.statusCode = 404;
```
After response header was sent to the client, this property indicates the
status code which was sent out.statusCode = 404;
response: http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
}
response.Stream.Writable.end(cb?: () => void): http.ServerResponse<http.IncomingMessage> & {
req: http.IncomingMessage;
} (+2 overloads)
Calling the `writable.end()` method signals that no more data will be written
to the `Writable`. The optional `chunk` and `encoding` arguments allow one
final additional chunk of data to be written immediately before closing the
stream.
Calling the
{@link
write
}
method after calling
{@link
end
}
will raise an error.
```js
// Write 'hello, ' and then end with 'world!'.
import fs from 'node:fs';
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
// Writing more now is not allowed!
```end();
}
})
.Server.listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> (+8 overloads)
Start a server listening for connections. A `net.Server` can be a TCP or
an `IPC` server depending on what it listens to.
Possible signatures:
* `server.listen(handle[, backlog][, callback])`
* `server.listen(options[, callback])`
* `server.listen(path[, backlog][, callback])` for `IPC` servers
* `server.listen([port[, host[, backlog]]][, callback])` for TCP servers
This function is asynchronous. When the server starts listening, the `'listening'` event will be emitted. The last parameter `callback`will be added as a listener for the `'listening'`
event.
All `listen()` methods can take a `backlog` parameter to specify the maximum
length of the queue of pending connections. The actual length will be determined
by the OS through sysctl settings such as `tcp_max_syn_backlog` and `somaxconn` on Linux. The default value of this parameter is 511 (not 512).
All
{@link
Socket
}
are set to `SO_REUSEADDR` (see [`socket(7)`](https://man7.org/linux/man-pages/man7/socket.7.html) for
details).
The `server.listen()` method can be called again if and only if there was an
error during the first `server.listen()` call or `server.close()` has been
called. Otherwise, an `ERR_SERVER_ALREADY_LISTEN` error will be thrown.
One of the most common errors raised when listening is `EADDRINUSE`.
This happens when another server is already listening on the requested`port`/`path`/`handle`. One way to handle this would be to retry
after a certain amount of time:
```js
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
console.error('Address in use, retrying...');
setTimeout(() => {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
});
```listen(8080);
We've now covered most of the basics of handling HTTP requests. At this point, you should be able to:
- Instantiate an HTTP server with a request handler function, and have it listen on a port.
- Get headers, URL, method and body data from
request
objects. - Make routing decisions based on URL and/or other data in
request
objects. - Send headers, HTTP status codes and body data via
response
objects. - Pipe data from
request
objects and toresponse
objects. - Handle stream errors in both the
request
andresponse
streams.
From these basics, Node.js HTTP servers for many typical use cases can be
constructed. There are plenty of other things these APIs provide, so be sure to
read through the API docs for EventEmitters
, Streams
, and HTTP
.