Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for passing in custom tlsOptions #303

Merged
merged 1 commit into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ Start autocannon against the given target.
* `servername`: A `String` identifying the server name for the SNI (Server Name Indication) TLS extension. _OPTIONAL_ default: Defaults to the hostname of the URL when it is not an IP address.
* `excludeErrorStats`: A `Boolean` which allows you to disable tracking non 2xx code responses in latency and bytes per second calculations. _OPTIONAL_ default: `false`.
* `expectBody`: A `String` representing the expected response body. Each request whose response body is not equal to `expectBody`is counted in `mismatches`. If enabled, mismatches count towards bailout. _OPTIONAL_
* `tlsOptions`: An `Object` that is passed into `tls.connect` call ([Full list of options](https://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback)). Note: this only applies if your url is secure.
* `cb`: The callback which is called on completion of a benchmark. Takes the following params. _OPTIONAL_.
* `err`: If there was an error encountered with the run.
* `results`: The results of the run.
Expand Down
5 changes: 3 additions & 2 deletions lib/httpClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function Client (opts) {
const pipelining = this.opts.pipelining
this.opts.port = this.opts.port || 80
this.opts.expectBody = this.opts.expectBody || null
this.opts.tlsOptions = this.opts.tlsOptions || {}
this.timeout = (this.opts.timeout || 10) * 1000
this.ipc = !!this.opts.socketPath
this.secure = this.opts.protocol === 'https:'
Expand Down Expand Up @@ -131,9 +132,9 @@ Client.prototype._connect = function () {
}

if (this.ipc) {
this.conn = tls.connect(this.opts.socketPath, { rejectUnauthorized: false })
this.conn = tls.connect(this.opts.socketPath, { ...this.opts.tlsOptions, rejectUnauthorized: false })
} else {
this.conn = tls.connect(this.opts.port, this.opts.hostname, { rejectUnauthorized: false, servername })
this.conn = tls.connect(this.opts.port, this.opts.hostname, { ...this.opts.tlsOptions, rejectUnauthorized: false, servername })
}
} else {
if (this.ipc) {
Expand Down
4 changes: 4 additions & 0 deletions lib/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ function _run (opts, cb, tracker) {
url.rate = distributeNums(opts.overallRate, i)
}

if (opts.tlsOptions) {
url.tlsOptions = opts.tlsOptions
}

const client = new Client(url)
client.on('response', onResponse)
client.on('connError', onError)
Expand Down
15 changes: 12 additions & 3 deletions test/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function startHttpsServer (opts = {}) {
return server
}

// this server will echo the SNI Server Name in a HTTP header
// this server will echo the SNI Server Name and emailAddress from the client certificate in a HTTP header
function startTlsServer () {
const key = fs.readFileSync(path.join(__dirname, '/key.pem'))
const cert = fs.readFileSync(path.join(__dirname, '/cert.pem'))
Expand All @@ -116,7 +116,9 @@ function startTlsServer () {
const options = {
key,
cert,
passphrase
passphrase,
requestCert: true,
rejectUnauthorized: false
}

const server = tls.createServer(options, handle)
Expand All @@ -125,9 +127,16 @@ function startTlsServer () {

function handle (socket) {
const servername = socket.servername || ''
const certificate = socket.getPeerCertificate()
const email = (certificate && certificate.subject && certificate.subject.emailAddress) || ''
socket.on('data', function (data) {
// Assume this is a http get request and send back the servername in an otherwise empty reponse.
socket.write('HTTP/1.1 200 OK\nX-servername: ' + servername + '\nContent-Length: 0\n\n')
socket.write('HTTP/1.1 200 OK\n')
socket.write('X-servername: ' + servername + '\n')
if (email) {
socket.write('X-email: ' + email + '\n')
}
socket.write('Content-Length: 0\n\n')
socket.setEncoding('utf8')
socket.pipe(socket)
})
Expand Down
23 changes: 23 additions & 0 deletions test/httpClient.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const httpsServer = helper.startHttpsServer()
const tlsServer = helper.startTlsServer()
const trailerServer = helper.startTrailerServer()
const bl = require('bl')
const fs = require('fs')

const makeResponseFromBody = ({ server, method, body, headers = {} }) => {
const sentHeaders = {
Expand Down Expand Up @@ -170,6 +171,28 @@ test('client ignores falsy SNI servername', (t) => {
})
})

test('client passes through tlsOptions to connect', (t) => {
t.plan(4)

var opts = tlsServer.address()
opts.protocol = 'https:'
opts.tlsOptions = {
key: fs.readFileSync(path.join(__dirname, '/key.pem')),
cert: fs.readFileSync(path.join(__dirname, '/cert.pem')),
passphrase: 'test'
}
const client = new Client(opts)
let count = 0

client.on('headers', (response) => {
t.equal(response.statusCode, 200, 'status code matches')
t.deepEqual(response.headers, ['X-servername', '', 'X-email', '[email protected]', 'Content-Length', '0'])
if (count++ > 0) {
client.destroy()
}
})
})

test('http client automatically reconnects', (t) => {
t.plan(4)

Expand Down