The HTTP and HTTPS modules
Reference for node:http and node:https in Cruft: the server half (createServer, IncomingMessage, ServerResponse) and the client half (request, get), which members are implemented, and the shared client limits such as no keep-alive and capped redirect following.
node:http is a focused module in Cruft's compatibility map: both halves ship, the server (createServer, streaming IncomingMessage, ServerResponse with writeHead/setHeader/write/end) and the client (http.request, http.get). The surface covers the request/response core; it stops short of full Node parity. node:https exposes the same client over a TLS 1.3 connection and a partial server adapter (createServer, Agent). Both, and the global fetch, are adapters over one canonical HTTP-client engine, so client behavior (redirect following, capped; AbortSignal honored) and limitations (no streaming request bodies, no keep-alive) are shared. All request and response callbacks are dispatched by the host event loop; a listening server keeps the process alive until closed.
Import forms
import http from 'node:http';
import https from 'node:https';
const http = require('node:http'); // bare 'http' / 'https' also resolve
API surface
Module-level
| Export | Notes |
|---|---|
http.createServer(handler) | Returns a server; handler(req, res) runs per request. |
http.request(url[, options][, cb]) | Returns a ClientRequest; cb(res) receives an IncomingMessage. Options include method, headers, body written via req.write. |
http.get(url[, options][, cb]) | request plus an automatic .end(). |
http.Agent | Constructor present; agents are inert placeholders (no connection pooling / keep-alive). |
http.STATUS_CODES | Partial code→reason-phrase table (common codes covered). |
http.METHODS | Array of HTTP method names (ACL, BIND, CHECKOUT, CONNECT, COPY, …). |
https.request / https.get | Same client over a TLS 1.3 connection. |
https.createServer | Partial TLS server adapter; do not assume full Node TLS server parity. (https.createSecureServer is not exported.) |
https.Agent | Present; inert as with http.Agent. |
Server and request/response objects
| Object | Implemented members |
|---|---|
| Server | listen(port[, cb]), request listeners via createServer(handler) / on('request', …), close. |
IncomingMessage (server request) | method, url, headers; events data, end via on/once/addListener; resume, pause, setEncoding, pipe/unpipe, isPaused. |
ServerResponse | writeHead(status[, headers]), setHeader, getHeader, removeHeader, hasHeader, getHeaderNames, write, end, flushHeaders, cork/uncork (no-ops), event registration (on, once, emit, listeners). |
ClientRequest | write, end, event registration (on, once, addListener, prependListener, removeListener), abort surface present. |
IncomingMessage (client response) | statusCode, headers; events data, end. |
Examples
A request/response server; the body streams in via data/end:
import http from 'node:http';
const server = http.createServer((req, res) => {
let body = '';
req.on('data', (chunk) => { body += chunk; });
req.on('end', () => {
console.log(`${req.method} ${req.url} body=${JSON.stringify(body)}`);
res.setHeader('X-Extra', 'yes');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello ');
res.end('world');
});
});
server.listen(8431, () => console.log('listening'));
$ curl -s -i -X POST -d 'ping' http://127.0.0.1:8431/echo
HTTP/1.1 200 OK
x-extra: yes
content-type: text/plain
transfer-encoding: chunked
hello world
The client:
const http = require('node:http');
http.get('http://127.0.0.1:8800/hello', res => {
let body = '';
console.log(res.statusCode, res.headers['content-type']);
res.on('data', c => body += c);
res.on('end', () => console.log(body));
});
// → 200 application/json
// → {"method":"GET","path":"/hello"}
Write a request body with req.write(...) then req.end():
const req = http.request('http://127.0.0.1:8800/api', { method: 'POST' }, res => {
let b = ''; res.on('data', c => b += c); res.on('end', () => console.log(b));
});
req.write('payload'); req.end();
// → {"method":"POST","got":"payload"}
STATUS_CODES and METHODS:
$ cruft -e 'import("node:http").then(m => {
const h = m.default;
console.log(h.STATUS_CODES[200], "/", h.STATUS_CODES[404], "/", h.STATUS_CODES[500]);
})'
OK / Not Found / Internal Server Error
Not implemented / gaps
Anything not listed above should be assumed absent. Known gaps:
- Client: the client engine shared with
fetchfollows redirects (capped) and honors anAbortSignal(an aborted signal rejects with anAbortError); the same applies tonode:httpclients. There is no keep-alive or connection pooling yet, so anAgentis inert. Binary bodies are byte-faithful in both directions and clientdatachunks are real Buffers. - Server: no
Upgrade/CONNECThandling, no trailers, nohttp.ClientRequesttimeout controls, noserver.setTimeout;cork/uncork/flushHeadersare accepted no-ops. httpsserver: partial adapter; TLS server machinery exists but Node server parity is not claimed.STATUS_CODESis a partial table, not the full Node set.
Async behaviors (listeners, request delivery, client responses) run on the host event loop; ordering follows the loop's task scheduling, not Node's exact internal phase order.