Skip to content

Commit

Permalink
add backward compatibility for the undici v6
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-tymoshenko committed Nov 27, 2024
1 parent 53c9346 commit 52eeff0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { threadId, MessageChannel, parentPort } = require('worker_threads')
const inject = require('light-my-request')
const Hooks = require('./lib/hooks')
const DispatchController = require('./lib/dispatch-controller')
const WrapHandler = require('./lib/wrap-handler')

const kAddress = Symbol('undici-thread-interceptor.address')

Expand All @@ -30,6 +31,8 @@ function createThreadInterceptor (opts) {
url = new URL(opts.path, url)
}

handler = handler.onRequestStart ? handler : new WrapHandler(handler)

// Hostnames are case-insensitive
const roundRobin = routes.get(url.hostname.toLowerCase())
if (!roundRobin) {
Expand Down
46 changes: 46 additions & 0 deletions lib/wrap-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict'

class WrapHandler {
#handler

constructor (handler) {
this.#handler = handler
}

onRequestStart (controller, context) {
this.#handler.onConnect?.((err) => controller.abort(err), context)
}

onResponseStart (controller, statusCode, statusMessage, headers) {
const rawHeaders = []
for (const [key, val] of Object.entries(headers)) {
rawHeaders.push(Buffer.from(key), Buffer.from(val))
}

this.#handler.onHeaders?.(
statusCode,
rawHeaders,
() => {},
statusMessage
)
}

onResponseData (controller, data) {
this.#handler.onData?.(data)
}

onResponseEnd (controller, trailers) {
const rawTrailers = []
for (const [key, val] of Object.entries(trailers)) {
rawTrailers.push(Buffer.from(key), Buffer.from(val))
}

this.#handler.onComplete?.(rawTrailers)
}

onResponseError (controller, err) {
this.#handler.onError?.(err)
}
}

module.exports = WrapHandler
25 changes: 24 additions & 1 deletion test/handler.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
'use strict'

// This is needed to set the nodejs Global Dispatcher
fetch('http://google.com')

const { test } = require('node:test')
const { deepStrictEqual, strictEqual } = require('node:assert')
const { join } = require('node:path')
const { Worker } = require('node:worker_threads')
const { createThreadInterceptor } = require('../')
const { Agent, request } = require('undici')
const { Agent, getGlobalDispatcher, request } = require('undici')

class TestHandler {
#handler
Expand Down Expand Up @@ -82,3 +85,23 @@ test('support undici v7 handler interface', async (t) => {
strictEqual(statusCode, 200)
deepStrictEqual(await body.json(), { hello: 'world' })
})

test('support undici v6 handler interface', async (t) => {
const worker = new Worker(join(__dirname, 'fixtures', 'worker1.js'))
t.after(() => worker.terminate())

const interceptor = createThreadInterceptor({
domain: '.local',
})
interceptor.route('myserver', worker)

const agent = getGlobalDispatcher()
.compose(interceptor)

Check failure on line 99 in test/handler.test.js

View workflow job for this annotation

GitHub Actions / test (18.x)

support undici v6 handler interface

[Error [ERR_TEST_FAILURE]: getGlobalDispatcher(...).compose is not a function] { failureType: 'testCodeFailure', cause: TypeError [Error]: getGlobalDispatcher(...).compose is not a function at TestContext.<anonymous> (/home/runner/work/undici-thread-interceptor/undici-thread-interceptor/test/handler.test.js:99:6) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Test.processPendingSubtests (node:internal/test_runner/test:374:18) at Test.postRun (node:internal/test_runner/test:715:19) at Test.run (node:internal/test_runner/test:673:12) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async startSubtest (node:internal/test_runner/harness:214:3), code: 'ERR_TEST_FAILURE' }

Check failure on line 99 in test/handler.test.js

View workflow job for this annotation

GitHub Actions / test (18.x)

support undici v6 handler interface

[Error [ERR_TEST_FAILURE]: getGlobalDispatcher(...).compose is not a function] { failureType: 'testCodeFailure', cause: TypeError [Error]: getGlobalDispatcher(...).compose is not a function at TestContext.<anonymous> (/home/runner/work/undici-thread-interceptor/undici-thread-interceptor/test/handler.test.js:99:6) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:631:25) at Test.processPendingSubtests (node:internal/test_runner/test:374:18) at Test.postRun (node:internal/test_runner/test:715:19) at Test.run (node:internal/test_runner/test:673:12) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async startSubtest (node:internal/test_runner/harness:214:3), code: 'ERR_TEST_FAILURE' }

const { statusCode, body } = await request('http://myserver.local', {
dispatcher: agent
})

strictEqual(statusCode, 200)
deepStrictEqual(await body.json(), { hello: 'world' })
})

0 comments on commit 52eeff0

Please sign in to comment.