1 | # Connector
|
---|
2 |
|
---|
3 | Undici creates the underlying socket via the connector builder.
|
---|
4 | Normally, this happens automatically and you don't need to care about this,
|
---|
5 | but if you need to perform some additional check over the currently used socket,
|
---|
6 | this is the right place.
|
---|
7 |
|
---|
8 | If you want to create a custom connector, you must import the `buildConnector` utility.
|
---|
9 |
|
---|
10 | #### Parameter: `buildConnector.BuildOptions`
|
---|
11 |
|
---|
12 | Every Tls option, see [here](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback).
|
---|
13 | Furthermore, the following options can be passed:
|
---|
14 |
|
---|
15 | * **socketPath** `string | null` (optional) - Default: `null` - An IPC endpoint, either Unix domain socket or Windows named pipe.
|
---|
16 | * **maxCachedSessions** `number | null` (optional) - Default: `100` - Maximum number of TLS cached sessions. Use 0 to disable TLS session caching. Default: `100`.
|
---|
17 | * **timeout** `number | null` (optional) - In milliseconds. Default `10e3`.
|
---|
18 | * **servername** `string | null` (optional)
|
---|
19 |
|
---|
20 | Once you call `buildConnector`, it will return a connector function, which takes the following parameters.
|
---|
21 |
|
---|
22 | #### Parameter: `connector.Options`
|
---|
23 |
|
---|
24 | * **hostname** `string` (required)
|
---|
25 | * **host** `string` (optional)
|
---|
26 | * **protocol** `string` (required)
|
---|
27 | * **port** `string` (required)
|
---|
28 | * **servername** `string` (optional)
|
---|
29 | * **localAddress** `string | null` (optional) Local address the socket should connect from.
|
---|
30 | * **httpSocket** `Socket` (optional) Establish secure connection on a given socket rather than creating a new socket. It can only be sent on TLS update.
|
---|
31 |
|
---|
32 | ### Basic example
|
---|
33 |
|
---|
34 | ```js
|
---|
35 | 'use strict'
|
---|
36 |
|
---|
37 | import { Client, buildConnector } from 'undici'
|
---|
38 |
|
---|
39 | const connector = buildConnector({ rejectUnauthorized: false })
|
---|
40 | const client = new Client('https://localhost:3000', {
|
---|
41 | connect (opts, cb) {
|
---|
42 | connector(opts, (err, socket) => {
|
---|
43 | if (err) {
|
---|
44 | cb(err)
|
---|
45 | } else if (/* assertion */) {
|
---|
46 | socket.destroy()
|
---|
47 | cb(new Error('kaboom'))
|
---|
48 | } else {
|
---|
49 | cb(null, socket)
|
---|
50 | }
|
---|
51 | })
|
---|
52 | }
|
---|
53 | })
|
---|
54 | ```
|
---|
55 |
|
---|
56 | ### Example: validate the CA fingerprint
|
---|
57 |
|
---|
58 | ```js
|
---|
59 | 'use strict'
|
---|
60 |
|
---|
61 | import { Client, buildConnector } from 'undici'
|
---|
62 |
|
---|
63 | const caFingerprint = 'FO:OB:AR'
|
---|
64 | const connector = buildConnector({ rejectUnauthorized: false })
|
---|
65 | const client = new Client('https://localhost:3000', {
|
---|
66 | connect (opts, cb) {
|
---|
67 | connector(opts, (err, socket) => {
|
---|
68 | if (err) {
|
---|
69 | cb(err)
|
---|
70 | } else if (getIssuerCertificate(socket).fingerprint256 !== caFingerprint) {
|
---|
71 | socket.destroy()
|
---|
72 | cb(new Error('Fingerprint does not match or malformed certificate'))
|
---|
73 | } else {
|
---|
74 | cb(null, socket)
|
---|
75 | }
|
---|
76 | })
|
---|
77 | }
|
---|
78 | })
|
---|
79 |
|
---|
80 | client.request({
|
---|
81 | path: '/',
|
---|
82 | method: 'GET'
|
---|
83 | }, (err, data) => {
|
---|
84 | if (err) throw err
|
---|
85 |
|
---|
86 | const bufs = []
|
---|
87 | data.body.on('data', (buf) => {
|
---|
88 | bufs.push(buf)
|
---|
89 | })
|
---|
90 | data.body.on('end', () => {
|
---|
91 | console.log(Buffer.concat(bufs).toString('utf8'))
|
---|
92 | client.close()
|
---|
93 | })
|
---|
94 | })
|
---|
95 |
|
---|
96 | function getIssuerCertificate (socket) {
|
---|
97 | let certificate = socket.getPeerCertificate(true)
|
---|
98 | while (certificate && Object.keys(certificate).length > 0) {
|
---|
99 | // invalid certificate
|
---|
100 | if (certificate.issuerCertificate == null) {
|
---|
101 | return null
|
---|
102 | }
|
---|
103 |
|
---|
104 | // We have reached the root certificate.
|
---|
105 | // In case of self-signed certificates, `issuerCertificate` may be a circular reference.
|
---|
106 | if (certificate.fingerprint256 === certificate.issuerCertificate.fingerprint256) {
|
---|
107 | break
|
---|
108 | }
|
---|
109 |
|
---|
110 | // continue the loop
|
---|
111 | certificate = certificate.issuerCertificate
|
---|
112 | }
|
---|
113 | return certificate
|
---|
114 | }
|
---|
115 | ```
|
---|