[d24f17c] | 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 | ```
|
---|