nock
Version:
HTTP server mocking and expectations library for Node.js
109 lines (92 loc) • 2.68 kB
JavaScript
'use strict'
const { EventEmitter } = require('events')
const debug = require('debug')('nock.socket')
module.exports = class Socket extends EventEmitter {
constructor(options) {
super()
// Pretend this is a TLSSocket
if (options.proto === 'https') {
// https://github.com/nock/nock/issues/158
this.authorized = true
// https://github.com/nock/nock/issues/2147
this.encrypted = true
}
this.bufferSize = 0
this.writableLength = 0
this.writable = true
this.readable = true
this.pending = false
this.destroyed = false
this.connecting = true
// Undocumented flag used by ClientRequest to ensure errors aren't double-fired
this._hadError = false
// Maximum allowed delay. 0 means unlimited.
this.timeout = 0
const ipv6 = options.family === 6
this.remoteFamily = ipv6 ? 'IPv6' : 'IPv4'
this.localAddress = this.remoteAddress = ipv6 ? '::1' : '127.0.0.1'
this.localPort = this.remotePort = parseInt(options.port)
}
setNoDelay() {}
setKeepAlive() {}
resume() {}
ref() {}
unref() {}
write() {}
address() {
return {
port: this.remotePort,
family: this.remoteFamily,
address: this.remoteAddress,
}
}
setTimeout(timeoutMs, fn) {
this.timeout = timeoutMs
if (fn) {
this.once('timeout', fn)
}
return this
}
/**
* Artificial delay that will trip socket timeouts when appropriate.
*
* Doesn't actually wait for time to pass.
* Timeout events don't necessarily end the request.
* While many clients choose to abort the request upon a timeout, Node itself does not.
*/
applyDelay(delayMs) {
if (this.timeout && delayMs > this.timeout) {
debug('socket timeout')
this.emit('timeout')
}
}
getPeerCertificate() {
return Buffer.from(
(Math.random() * 10000 + Date.now()).toString(),
).toString('base64')
}
/**
* Denotes that no more I/O activity should happen on this socket.
*
* The implementation in Node if far more complex as it juggles underlying async streams.
* For the purposes of Nock, we just need it to set some flags and on the first call
* emit a 'close' and optional 'error' event. Both events propagate through the request object.
*/
destroy(err) {
if (this.destroyed) {
return this
}
debug('socket destroy')
this.destroyed = true
this.readable = this.writable = false
this.readableEnded = this.writableFinished = true
process.nextTick(() => {
if (err) {
this._hadError = true
this.emit('error', err)
}
this.emit('close')
})
return this
}
}