summaryrefslogtreecommitdiffstats
path: root/test/jest/interceptor.test.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/jest/interceptor.test.js')
-rw-r--r--test/jest/interceptor.test.js197
1 files changed, 197 insertions, 0 deletions
diff --git a/test/jest/interceptor.test.js b/test/jest/interceptor.test.js
new file mode 100644
index 0000000..73d70b7
--- /dev/null
+++ b/test/jest/interceptor.test.js
@@ -0,0 +1,197 @@
+'use strict'
+
+const { createServer } = require('http')
+const { Agent, request } = require('../../index')
+const DecoratorHandler = require('../../lib/handler/DecoratorHandler')
+/* global expect */
+
+const defaultOpts = { keepAliveTimeout: 10, keepAliveMaxTimeout: 10 }
+
+describe('interceptors', () => {
+ let server
+ beforeEach(async () => {
+ server = createServer((req, res) => {
+ res.setHeader('Content-Type', 'text/plain')
+ res.end('hello')
+ })
+ await new Promise((resolve) => { server.listen(0, resolve) })
+ })
+ afterEach(async () => {
+ await new Promise((resolve) => server.close(resolve))
+ })
+
+ test('interceptors are applied on client from an agent', async () => {
+ const interceptors = []
+ const buildInterceptor = dispatch => {
+ const interceptorContext = { requestCount: 0 }
+ interceptors.push(interceptorContext)
+ return (opts, handler) => {
+ interceptorContext.requestCount++
+ return dispatch(opts, handler)
+ }
+ }
+
+ const opts = { interceptors: { Client: [buildInterceptor] }, ...defaultOpts }
+ const agent = new Agent(opts)
+ const origin = new URL(`http://localhost:${server.address().port}`)
+ await Promise.all([
+ request(origin, { dispatcher: agent }),
+ request(origin, { dispatcher: agent })
+ ])
+
+ // Assert that the requests are run on different interceptors (different Clients)
+ const requestCounts = interceptors.map(x => x.requestCount)
+ expect(requestCounts).toEqual([1, 1])
+ })
+
+ test('interceptors are applied in the correct order', async () => {
+ const setHeaderInterceptor = (dispatch) => {
+ return (opts, handler) => {
+ opts.headers.push('foo', 'bar')
+ return dispatch(opts, handler)
+ }
+ }
+
+ const assertHeaderInterceptor = (dispatch) => {
+ return (opts, handler) => {
+ expect(opts.headers).toEqual(['foo', 'bar'])
+ return dispatch(opts, handler)
+ }
+ }
+
+ const opts = { interceptors: { Pool: [setHeaderInterceptor, assertHeaderInterceptor] }, ...defaultOpts }
+ const agent = new Agent(opts)
+ const origin = new URL(`http://localhost:${server.address().port}`)
+ await request(origin, { dispatcher: agent, headers: [] })
+ })
+
+ test('interceptors handlers are called in reverse order', async () => {
+ const clearResponseHeadersInterceptor = (dispatch) => {
+ return (opts, handler) => {
+ class ResultInterceptor extends DecoratorHandler {
+ onHeaders (statusCode, headers, resume) {
+ return super.onHeaders(statusCode, [], resume)
+ }
+ }
+
+ return dispatch(opts, new ResultInterceptor(handler))
+ }
+ }
+
+ const assertHeaderInterceptor = (dispatch) => {
+ return (opts, handler) => {
+ class ResultInterceptor extends DecoratorHandler {
+ onHeaders (statusCode, headers, resume) {
+ expect(headers).toEqual([])
+ return super.onHeaders(statusCode, headers, resume)
+ }
+ }
+
+ return dispatch(opts, new ResultInterceptor(handler))
+ }
+ }
+
+ const opts = { interceptors: { Agent: [assertHeaderInterceptor, clearResponseHeadersInterceptor] }, ...defaultOpts }
+ const agent = new Agent(opts)
+ const origin = new URL(`http://localhost:${server.address().port}`)
+ await request(origin, { dispatcher: agent, headers: [] })
+ })
+})
+
+describe('interceptors with NtlmRequestHandler', () => {
+ class FakeNtlmRequestHandler {
+ constructor (dispatch, opts, handler) {
+ this.dispatch = dispatch
+ this.opts = opts
+ this.handler = handler
+ this.requestCount = 0
+ }
+
+ onConnect (...args) {
+ return this.handler.onConnect(...args)
+ }
+
+ onError (...args) {
+ return this.handler.onError(...args)
+ }
+
+ onUpgrade (...args) {
+ return this.handler.onUpgrade(...args)
+ }
+
+ onHeaders (statusCode, headers, resume, statusText) {
+ this.requestCount++
+ if (this.requestCount < 2) {
+ // Do nothing
+ } else {
+ return this.handler.onHeaders(statusCode, headers, resume, statusText)
+ }
+ }
+
+ onData (...args) {
+ if (this.requestCount < 2) {
+ // Do nothing
+ } else {
+ return this.handler.onData(...args)
+ }
+ }
+
+ onComplete (...args) {
+ if (this.requestCount < 2) {
+ this.dispatch(this.opts, this)
+ } else {
+ return this.handler.onComplete(...args)
+ }
+ }
+
+ onBodySent (...args) {
+ if (this.requestCount < 2) {
+ // Do nothing
+ } else {
+ return this.handler.onBodySent(...args)
+ }
+ }
+ }
+ let server
+
+ beforeEach(async () => {
+ // This Test is important because NTLM and Negotiate require several
+ // http requests in sequence to run on the same keepAlive socket
+
+ const socketRequestCountSymbol = Symbol('Socket Request Count')
+ server = createServer((req, res) => {
+ if (req.socket[socketRequestCountSymbol] === undefined) {
+ req.socket[socketRequestCountSymbol] = 0
+ }
+ req.socket[socketRequestCountSymbol]++
+ res.setHeader('Content-Type', 'text/plain')
+
+ // Simulate NTLM/Negotiate logic, by returning 200
+ // on the second request of each socket
+ if (req.socket[socketRequestCountSymbol] >= 2) {
+ res.statusCode = 200
+ res.end()
+ } else {
+ res.statusCode = 401
+ res.end()
+ }
+ })
+ await new Promise((resolve) => { server.listen(0, resolve) })
+ })
+ afterEach(async () => {
+ await new Promise((resolve) => server.close(resolve))
+ })
+
+ test('Retry interceptor on Client will use the same socket', async () => {
+ const interceptor = dispatch => {
+ return (opts, handler) => {
+ return dispatch(opts, new FakeNtlmRequestHandler(dispatch, opts, handler))
+ }
+ }
+ const opts = { interceptors: { Client: [interceptor] }, ...defaultOpts }
+ const agent = new Agent(opts)
+ const origin = new URL(`http://localhost:${server.address().port}`)
+ const { statusCode } = await request(origin, { dispatcher: agent, headers: [] })
+ expect(statusCode).toEqual(200)
+ })
+})