Skip to content

Commit 302c3f7

Browse files
committed
Improve and expand node:http docs, examples
1 parent e657aa3 commit 302c3f7

File tree

2 files changed

+162
-94
lines changed

2 files changed

+162
-94
lines changed

src/content/docs/workers/runtime-apis/nodejs/http.mdx

Lines changed: 95 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,67 +13,80 @@ An implementation of the Node.js [`http.get`](https://nodejs.org/docs/latest/api
1313

1414
The `get` method performs a GET request to the specified URL and invokes the callback with the response. It's a convenience method that simplifies making HTTP GET requests without manually configuring request options.
1515

16+
Because `get` is a wrapper around `fetch(...)`, it may be used only within an exported
17+
fetch or similar handler. Outside of such a handler, attempts to use `get` will throw
18+
an error.
19+
1620
```js
1721
import { get } from 'node:http';
18-
import { strictEqual, ok } from 'node:assert';
19-
20-
get('http://docs.cloudflare.com/robots.txt', (res) => {
21-
// requests to http://docs.cloudflare.com get redirected to their https counterpart.
22-
strictEqual(res.statusCode, 301);
23-
let data = '';
24-
res.setEncoding('utf8');
25-
res.on('data', (chunk) => {
26-
data += chunk;
27-
});
28-
res.on('end', () => {
29-
ok(data.includes('301 Moved Permanently'));
30-
});
31-
});
22+
23+
export default {
24+
async fetch() {
25+
const { promise, resolve, reject } = Promise.withResolvers();
26+
get('http://example.org', (res) => {
27+
let data = '';
28+
res.setEncoding('utf8');
29+
res.on('data', (chunk) => {
30+
data += chunk;
31+
});
32+
res.on('end', () => {
33+
resolve(new Response(data));
34+
});
35+
res.on('error', reject);
36+
}).on('error', reject);
37+
return promise;
38+
}
39+
}
3240
```
3341

42+
The implementation of `get` in Workers is a wrapper around the global
43+
[`fetch` API](https://developers.cloudflare.com/workers/runtime-apis/fetch/)
44+
and is therefore subject to the same [limits](https://developers.cloudflare.com/workers/platform/limits/).
45+
46+
As shown in the example above, it is necessary to arrange for requests to be correctly
47+
awaited in the `fetch` handler using a promise or the fetch may be canceled prematurely
48+
when the handler returns.
49+
3450
## request
3551

3652
An implementation of the Node.js [`http.request'](https://nodejs.org/docs/latest/api/http.html#httprequesturl-options-callback) method.
3753

38-
The `request` method creates an HTTP request with customizable options like method, headers, and body. It provides full control over the request configuration and returns a [writable stream](https://nodejs.org/docs/latest/api/stream.html#class-streamwritable) for sending request data.
54+
The `request` method creates an HTTP request with customizable options like method, headers, and body. It provides full control over the request configuration and returns a Node.js [stream.Writable](https://developers.cloudflare.com/workers/runtime-apis/nodejs/streams/) for sending request data.
55+
56+
Because `request` is a wrapper around `fetch(...)`, it may be used only within an exported
57+
fetch or similar handler. Outside of such a handler, attempts to use `request` will throw
58+
an error.
3959

4060
```js
41-
import { request } from 'node:http';
42-
import { strictEqual } from 'node:assert';
61+
import { get } from 'node:http';
4362

44-
const req = request({
45-
method: 'GET',
46-
protocol: 'http:',
47-
hostname: 'docs.cloudflare.com',
48-
path: '/'
49-
}, (res) => {
50-
// requests to http://docs.cloudflare.com get redirected to their https counterpart.
51-
strictEqual(res.statusCode, 301);
52-
53-
let data = '';
54-
res.setEncoding('utf8');
55-
res.on('data', (chunk) => {
56-
data += chunk;
57-
});
58-
res.on('end', () => {
59-
ok(data.includes('301 Moved Permanently'));
60-
});
61-
});
62-
req.end();
63+
export default {
64+
async fetch() {
65+
const { promise, resolve, reject } = Promise.withResolvers();
66+
get({
67+
method: 'GET',
68+
protocol: 'http:',
69+
hostname: 'example.org',
70+
path: '/'
71+
}, (res) => {
72+
let data = '';
73+
res.setEncoding('utf8');
74+
res.on('data', (chunk) => {
75+
data += chunk;
76+
});
77+
res.on('end', () => {
78+
resolve(new Response(data));
79+
});
80+
res.on('error', reject);
81+
}).on('error', reject)
82+
.end();
83+
return promise;
84+
}
85+
}
6386
```
6487

65-
```js
66-
const req = request(new URL('http://docs.cloudflare.com'),{
67-
method: 'GET',
68-
}, (res) => {
69-
// requests to http://docs.cloudflare.com get redirected to their https counterpart.
70-
strictEqual(res.statusCode, 301);
71-
});
72-
73-
req.end();
74-
```
88+
The following options passed to the `request` (and `get`) method are not supported due to the differences required by Coudflare Workers implementation of `node:http` as a wrapper around the global `fetch` API:
7589

76-
The following options passed to the `request` method are not supported due to the differences in the Cloudflare Workers and the implementation of the `node:http` module:
7790
- `maxHeaderSize`
7891
- `insecureHTTPParser`
7992
- `createConnection`
@@ -82,16 +95,23 @@ The following options passed to the `request` method are not supported due to th
8295

8396
## OutgoingMessage
8497

85-
The [`OutgoingMessage`](https://nodejs.org/docs/latest/api/http.html#class-httpoutgoingmessage) class represents an HTTP response that is sent to the client. It provides methods for writing response headers and body, as well as for ending the response. `OutgoingMessage` extends from the [`Writable` stream class](https://nodejs.org/docs/latest/api/stream.html#class-streamwritable).
98+
The [`OutgoingMessage`](https://nodejs.org/docs/latest/api/http.html#class-httpoutgoingmessage) class represents an HTTP response that is sent to the client. It provides methods for writing response headers and body, as well as for ending the response. `OutgoingMessage` extends from the Node.js [`stream.Writable` stream class](https://developers.cloudflare.com/workers/runtime-apis/nodejs/streams/).
8699

87100
```js
88101
import { OutgoingMessage } from 'node:http';
89102

90-
const res = new OutgoingMessage();
91-
res.writeHead(200, { 'Content-Type': 'text/plain' });
92-
res.write('Hello, World!');
93-
res.end();
103+
export default {
104+
async fetch() {
105+
// ...
106+
const res = new OutgoingMessage();
107+
res.writeHead(200, { 'Content-Type': 'text/plain' });
108+
res.write('Hello, World!');
109+
res.end();
110+
// ...
111+
}
112+
}
94113
```
114+
95115
## IncomingMessage
96116

97117
The `IncomingMessage` class represents an HTTP request that is received from the client. It provides methods for reading request headers and body, as well as for ending the request. `IncomingMessage` extends from the `Readable` stream class.
@@ -100,10 +120,15 @@ The `IncomingMessage` class represents an HTTP request that is received from the
100120
import { get, IncomingMessage } from 'node:http';
101121
import { ok, strictEqual } from 'node:assert';
102122

103-
get('http://docs.cloudflare.com', (res) => {
104-
strictEqual(res.statusCode, 301);
105-
ok(res instanceof IncomingMessage);
106-
});
123+
export default {
124+
async fetch() {
125+
// ...
126+
get('http://example.org', (res) => {
127+
ok(res instanceof IncomingMessage);
128+
});
129+
// ...
130+
}
131+
}
107132
```
108133

109134
## Agent
@@ -133,3 +158,17 @@ export default {
133158
}
134159
}
135160
```
161+
162+
## Other differences between Node.js and Workers implementation of `node:http`
163+
164+
Because the Workers implementation of `node:http` is a wrapper around the global `fetch` API, there are some differences in behavior and limitations compared to a standard Node.js environment:
165+
166+
* `Connection` headers are not used. Workers will manage connections automatically.
167+
* `Content-Length` headers will be handled the same way as in the `fetch` API. If a body is provided, the header will be set automatically and manually set values will be ignored.
168+
* `Expect: 100-continue` headers are not supported.
169+
* Trailing headers are not supported.
170+
* The `'continue'` event is not supported.
171+
* The `'information'` event is not supported.
172+
* The `'socket'` event is not supported.
173+
* The `'upgrade'` event is not supported.
174+
* Gaining direct access to the underlying `socket` is not supported.

src/content/docs/workers/runtime-apis/nodejs/https.mdx

Lines changed: 67 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,64 +11,78 @@ import { Render } from "~/components";
1111

1212
An implementation of the Node.js [`https.get'](https://nodejs.org/docs/latest/api/https.html#httpsgetoptions-callback) method.
1313

14-
The [`get`](https://nodejs.org/docs/latest/api/https.html#httpsgetoptions-callback) method performs a GET request to the specified URL and invokes the callback with the response. This is a convenience method that simplifies making HTTPS GET requests without manually configuring request options.
14+
The `get` method performs a GET request to the specified URL and invokes the callback with the response. This is a convenience method that simplifies making HTTPS GET requests without manually configuring request options.
15+
16+
Because `get` is a wrapper around `fetch(...)`, it may be used only within an exported
17+
fetch or similar handler. Outside of such a handler, attempts to use `get` will throw
18+
an error.
1519

1620
```js
17-
import { get } from "node:https";
21+
import { get } from 'node:https';
1822

1923
export default {
2024
async fetch() {
2125
const { promise, resolve, reject } = Promise.withResolvers();
22-
get("http://example.com", (res) => {
23-
let data = "";
24-
res.setEncoding("utf8");
25-
res.on("data", (chunk) => {
26+
get('https://example.org', (res) => {
27+
let data = '';
28+
res.setEncoding('utf8');
29+
res.on('data', (chunk) => {
2630
data += chunk;
2731
});
28-
res.on("error", reject);
29-
res.on("end", () => {
32+
res.on('end', () => {
3033
resolve(new Response(data));
3134
});
32-
}).on("error", reject);
35+
res.on('error', reject);
36+
}).on('error', reject);
3337
return promise;
34-
},
35-
};
38+
}
39+
}
3640
```
3741

42+
The implementation of `get` in Workers is a wrapper around the global
43+
[`fetch` API](https://developers.cloudflare.com/workers/runtime-apis/fetch/)
44+
and is therefore subject to the same [limits](https://developers.cloudflare.com/workers/platform/limits/).
45+
46+
As shown in the example above, it is necessary to arrange for requests to be correctly
47+
awaited in the `fetch` handler using a promise or the fetch may be canceled prematurely
48+
when the handler returns.
49+
3850
## request
3951

4052
An implementation of the Node.js [`https.request'](https://nodejs.org/docs/latest/api/https.html#httpsrequestoptions-callback) method.
4153

42-
The [`request`](https://nodejs.org/docs/latest/api/https.html#httpsrequestoptions-callback) method creates an HTTPS request with customizable options like method, headers, and body. It provides full control over the request configuration and returns a [writable stream](https://developers.cloudflare.com/workers/runtime-apis/streams/writablestream/) for sending request data.
43-
44-
Request method accepts all options from `http.request` with some differences in default values:
54+
The `request` method creates an HTTPS request with customizable options like method, headers, and body. It provides full control over the request configuration and returns a Node.js [stream.Writable](https://developers.cloudflare.com/workers/runtime-apis/nodejs/streams/) for sending request data.
4555

46-
- `protocol`: default `https:`
47-
- `port`: default `443`
48-
- `agent`: default `https.globalAgent`
56+
Because `get` is a wrapper around `fetch(...)`, it may be used only within an exported
57+
fetch or similar handler. Outside of such a handler, attempts to use `get` will throw
58+
an error.
4959

5060
```js
51-
import { request } from "node:https";
52-
import { strictEqual, ok } from "node:assert";
53-
54-
const req = request(
55-
"https://developers.cloudflare.com/robots.txt",
56-
{
57-
method: "GET",
58-
},
59-
(res) => {
60-
strictEqual(res.statusCode, 200);
61-
let data = "";
62-
res.setEncoding("utf8");
63-
res.on("data", (chunk) => {
64-
data += chunk;
65-
});
66-
res.on("end", () => {
67-
ok(data.includes("User-agent"));
68-
});
69-
},
70-
);
71-
req.end();
61+
import { get } from 'node:http';
62+
63+
export default {
64+
async fetch() {
65+
const { promise, resolve, reject } = Promise.withResolvers();
66+
get({
67+
method: 'GET',
68+
protocol: 'https:',
69+
hostname: 'example.org',
70+
path: '/'
71+
}, (res) => {
72+
let data = '';
73+
res.setEncoding('utf8');
74+
res.on('data', (chunk) => {
75+
data += chunk;
76+
});
77+
res.on('end', () => {
78+
resolve(new Response(data));
79+
});
80+
res.on('error', reject);
81+
}).on('error', reject)
82+
.end();
83+
return promise;
84+
}
85+
}
7286
```
7387

7488
The following additional options are not supported: `ca`, `cert`, `ciphers`, `clientCertEngine` (deprecated), `crl`, `dhparam`, `ecdhCurve`, `honorCipherOrder`, `key`, `passphrase`, `pfx`, `rejectUnauthorized`, `secureOptions`, `secureProtocol`, `servername`, `sessionIdContext`, `highWaterMark`.
@@ -100,3 +114,18 @@ export default {
100114
}
101115
}
102116
```
117+
118+
## Other differences between Node.js and Workers implementation of `node:https`
119+
120+
Because the Workers imlementation of `node:https` is a wrapper around the global `fetch` API, there are some differences in behavior compared to Node.js:
121+
122+
* `Connection` headers are not used. Workers will manage connections automatically.
123+
* `Content-Length` headers will be handled the same way as in the `fetch` API. If a body is provided, the header will be set automatically and manually set values will be ignored.
124+
* `Expect: 100-continue` headers are not supported.
125+
* Trailing headers are not supported.
126+
* The `'continue'` event is not supported.
127+
* The `'information'` event is not supported.
128+
* The `'socket'` event is not supported.
129+
* The `'upgrade'` event is not supported.
130+
* Gaining direct access to the underlying `socket` is not supported.
131+
* Configuring TLS-specific options like `ca`, `cert`, `key`, `rejectUnauthorized`, etc, is not supported.

0 commit comments

Comments
 (0)