diff options
Diffstat (limited to 'test/jest/interceptor.test.js')
-rw-r--r-- | test/jest/interceptor.test.js | 197 |
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) + }) +}) |