@@ -4,6 +4,7 @@ const express = require('express');
4
4
const supertest = require ( 'supertest' ) ;
5
5
6
6
const httpContext = require ( '../index' ) ;
7
+ const { init, REQUEST_ID_CONTEXT_KEY , REQUEST_ID_IN_RESPONSE_HTTP_HEADER_NAME } = require ( '@oliverlockwood/express-http-context-intermediate-library' ) ;
7
8
8
9
describe ( 'express-http-context' , function ( ) {
9
10
it ( 'does not store or return context outside of request' , function ( ) {
@@ -222,4 +223,58 @@ describe('express-http-context', function () {
222
223
done ( ) ;
223
224
} ) ;
224
225
} ) ;
226
+
227
+ it ( 'maintains unique value when the library is depended upon both directly and transitively' , async ( ) => {
228
+ // ARRANGE
229
+ const app = express ( ) ;
230
+
231
+ // this function in the test library makes the following two calls:
232
+ // 1. app.use(middleware) and
233
+ // 2. httpContext.set(REQUEST_ID_CONTEXT_KEY, <a unique id>)
234
+ // as can be seen in https://github.com/oliverlockwood/express-http-context-intermediate-library/blob/original-express-http-context/src/index.ts#L13-L19
235
+ init ( app ) ;
236
+
237
+ app . get ( '/' , ( ( req , res ) => {
238
+ httpContext . set ( 'value' , req . query [ 'value' ] ) ;
239
+
240
+ res . status ( 200 ) . json ( {
241
+ fred : '123' ,
242
+ value : req . query [ 'value' ] ,
243
+ valueFromContext : httpContext . get ( 'value' ) ,
244
+ requestId : httpContext . get ( REQUEST_ID_CONTEXT_KEY )
245
+ } ) ;
246
+ } ) ) ;
247
+
248
+ const request = supertest ( app ) ;
249
+
250
+ // ACT
251
+ const [ response1 , response2 ] = await Promise . all ( [
252
+ request . get ( '/' ) . query ( { value : 'value1' } ) ,
253
+ request . get ( '/' ) . query ( { value : 'value2' } ) ,
254
+ ] ) ;
255
+
256
+ // ASSERT
257
+ expect ( response1 . body . value ) . toBe ( 'value1' ) ;
258
+ expect ( response2 . body . value ) . toBe ( 'value2' ) ;
259
+
260
+ expect ( response1 . header [ REQUEST_ID_IN_RESPONSE_HTTP_HEADER_NAME ] ?. length ) . toBe ( 21 ) ;
261
+ expect ( response2 . header [ REQUEST_ID_IN_RESPONSE_HTTP_HEADER_NAME ] ?. length ) . toBe ( 21 ) ;
262
+
263
+ // This is the specific example I had flagged in the Github issues (#26, #78) - where
264
+ // setting something into the httpContext in a common library, but it's
265
+ // unusable from within the application code.
266
+ expect ( response1 . body . requestId ) . toBe ( response1 . header [ REQUEST_ID_IN_RESPONSE_HTTP_HEADER_NAME ] ) ;
267
+ expect ( response2 . body . requestId ) . toBe ( response2 . header [ REQUEST_ID_IN_RESPONSE_HTTP_HEADER_NAME ] ) ;
268
+
269
+ // These operations also fail, I suspect, because neither of the set/get
270
+ // functions are usable, because the directly imported AsyncLocalStorage has
271
+ // not been initialised by a call to `app.use(middleware)` within our code
272
+ // here. Effectively this is another manifestation of the same bug -
273
+ // showing that although the middleware *has* already been initialised in
274
+ // Express request handler chain, it is not usable because the
275
+ // AsyncLocalStorage context is not identical for all usages of the
276
+ // `express-http-context` library code.
277
+ expect ( response1 . body . valueFromContext ) . toBe ( 'value1' ) ;
278
+ expect ( response2 . body . valueFromContext ) . toBe ( 'value2' ) ;
279
+ } ) ;
225
280
} ) ;
0 commit comments