Skip to content

Commit ecda4e8

Browse files
authored
fix: Added defensive code for obtaining protocol in outbound http calls (newrelic#3367)
1 parent 7da99b5 commit ecda4e8

File tree

3 files changed

+48
-17
lines changed

3 files changed

+48
-17
lines changed

lib/instrumentation/core/http-outbound.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ function applySegment({ opts, makeRequest, host, port, hostname, segment, config
269269
obfuscatedPath = request.path
270270
}
271271

272-
const proto = parsed.protocol || opts.protocol || 'http:'
272+
const proto = parsed?.protocol || opts.protocol || 'http:'
273273

274274
segment.captureExternalAttributes({
275275
protocol: proto,

test/integration/instrumentation/http-outbound.test.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ const test = require('node:test')
1010
const symbols = require('../../../lib/symbols')
1111
const nock = require('nock')
1212
const { tspl } = require('@matteo.collina/tspl')
13+
const net = require('net')
14+
const { DESTINATIONS } = require('../../../lib/config/attribute-filter')
15+
const fs = require('node:fs/promises')
1316

1417
test('external requests', async function (t) {
1518
t.beforeEach((ctx) => {
@@ -187,6 +190,50 @@ test('external requests', async function (t) {
187190
})
188191
})
189192

193+
await t.test('unix sockets', async function(t) {
194+
const { agent, http } = t.nr
195+
const plan = tspl(t, { plan: 2 })
196+
const socketPath = './test.sock'
197+
try {
198+
await fs.unlink(socketPath)
199+
} catch {
200+
// this is defensive code in case a socket was dangling
201+
}
202+
const server = net.createServer((socket) => {
203+
socket.on('data', () => {
204+
socket.end('HTTP/1.1 200 OK\r\n\r\n')
205+
})
206+
})
207+
208+
await new Promise((resolve) => {
209+
server.listen(socketPath, resolve)
210+
})
211+
t.after(() => {
212+
server.close()
213+
})
214+
215+
await helper.runInTransaction(agent, async function () {
216+
await new Promise((resolve) => {
217+
http.get({ host: '::1', socketPath }, (res) => {
218+
const segment = agent.tracer.getSegment()
219+
plan.equal(segment.name, 'External/::1')
220+
const attributes = segment.attributes.get(DESTINATIONS.SPAN_EVENT)
221+
plan.deepEqual(attributes, {
222+
hostname: '::1',
223+
port: 80,
224+
url: 'http://::1/',
225+
procedure: 'GET',
226+
'http.statusCode': 200,
227+
'http.statusText': 'OK'
228+
})
229+
res.resume()
230+
resolve()
231+
})
232+
})
233+
})
234+
await plan.completed
235+
})
236+
190237
await t.test('should record requests to default ports', async (t) => {
191238
const plan = tspl(t, { plan: 1 })
192239
const { agent, http } = t.nr

test/unit/instrumentation/http/outbound.test.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -160,22 +160,6 @@ test('instrumentOutbound', async (t) => {
160160
})
161161
})
162162

163-
await t.test('should not accept an undefined path', (t, end) => {
164-
const { agent } = t.nr
165-
const req = new events.EventEmitter()
166-
helper.runInTransaction(agent, function () {
167-
assert.throws(
168-
() => instrumentOutbound(agent, { host: HOSTNAME, port: PORT }, makeFakeRequest),
169-
Error
170-
)
171-
end()
172-
})
173-
174-
function makeFakeRequest() {
175-
return req
176-
}
177-
})
178-
179163
await t.test('should accept a simple path with no parameters', (t, end) => {
180164
const { agent } = t.nr
181165
const req = new events.EventEmitter()

0 commit comments

Comments
 (0)