Skip to content

Commit e1444d7

Browse files
authored
Expose a mock socket that is an EventEmitter like a real one would be (#101)
Before this change, if a Fastify user attached an `onTimeout` hook to their server, an error would be thrown in test mode when injecting requests with light-my-request ``` TypeError: request.raw.socket.on is not a function at Object.routeHandler [as handler] (../../node_modules/fastify/lib/route.js:350:28) at Router.lookup (../../node_modules/find-my-way/index.js:356:14) at ../../node_modules/light-my-request/index.js:101:38 at Request.prepare (../../node_modules/light-my-request/lib/request.js:110:12) at ../../node_modules/light-my-request/index.js:101:11 at doInject (../../node_modules/light-my-request/index.js:97:12) at Chain.<computed> [as then] (../../node_modules/light-my-request/index.js:187:23) at runMicrotasks (<anonymous>) ``` This fixes the socket object to have an `on` function (as well as the rest of the EventEmitter interface) so that things that add timeout handlers can at least add them without erroring. This doesn't implement actual timeout injection, but I think that could be done in userland by emitting events on the socket manually. Similar to #99.
1 parent 009ece0 commit e1444d7

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

lib/request.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const assert = require('assert')
99
const warning = require('fastify-warning')()
1010

1111
const parseURL = require('./parseURL')
12+
const { EventEmitter } = require('events')
1213

1314
// request.connectin deprecation https://nodejs.org/api/http.html#http_request_connection
1415
warning.create('FastifyDeprecationLightMyRequest', 'FST_LIGHTMYREQUEST_DEP01', 'You are accessing "request.connection", use "request.socket" instead.')
@@ -25,6 +26,19 @@ function hostHeaderFromURL (parsedURL) {
2526
: parsedURL.hostname + (parsedURL.protocol === 'https:' ? ':443' : ':80')
2627
}
2728

29+
/**
30+
* Mock socket object used to fake access to a socket for a request
31+
*
32+
* @constructor
33+
* @param {String} remoteAddress the fake address to show consumers of the socket
34+
*/
35+
class MockSocket extends EventEmitter {
36+
constructor (remoteAddress) {
37+
super()
38+
this.remoteAddress = remoteAddress
39+
}
40+
}
41+
2842
/**
2943
* Request
3044
*
@@ -68,9 +82,7 @@ function Request (options) {
6882
this.headers.cookie = cookieValues.join('; ')
6983
}
7084

71-
this.socket = {
72-
remoteAddress: options.remoteAddress || '127.0.0.1'
73-
}
85+
this.socket = new MockSocket(options.remoteAddress || '127.0.0.1')
7486

7587
Object.defineProperty(this, 'connection', {
7688
get () {

test/test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,20 @@ test('passes remote address', (t) => {
9696
})
9797
})
9898

99+
test('passes a socket which emits events like a normal one does', (t) => {
100+
t.plan(2)
101+
const dispatch = function (req, res) {
102+
res.writeHead(200, { 'Content-Type': 'text/plain' })
103+
req.socket.on('timeout', () => {})
104+
res.end('added')
105+
}
106+
107+
inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello' }, (err, res) => {
108+
t.error(err)
109+
t.equal(res.payload, 'added')
110+
})
111+
})
112+
99113
test('includes deprecated connection on request', (t) => {
100114
t.plan(2)
101115
const dispatch = function (req, res) {

0 commit comments

Comments
 (0)