Browse Source

fix(core): Handle array circular refs when serializing RequestContext

Fixes #864
Michael Bromley 4 years ago
parent
commit
4abb912b00

+ 26 - 1
packages/core/src/api/common/request-context.spec.ts

@@ -57,6 +57,30 @@ describe('RequestContext', () => {
             const result = RequestContext.deserialize(serializedCtx);
             const result = RequestContext.deserialize(serializedCtx);
             expect(result.session).toEqual(original.session);
             expect(result.session).toEqual(original.session);
         });
         });
+
+        // https://github.com/vendure-ecommerce/vendure/issues/864
+        it('serialize request context with circular refs', () => {
+            const cyclic: any = {};
+            const cyclic1: any = {
+                prop: cyclic,
+            };
+            cyclic.prop = cyclic1;
+
+            const requestContext = createRequestContext({
+                simple: 'foo',
+                arr: [1, 2, 3],
+                cycle: cyclic,
+                cycleArr: [cyclic, cyclic],
+            });
+
+            const serialized = requestContext.serialize();
+            expect(serialized._req).toEqual({
+                simple: 'foo',
+                arr: [1, 2, 3],
+                cycle: {},
+                cycleArr: [{}, {}],
+            });
+        });
     });
     });
 
 
     describe('copy', () => {
     describe('copy', () => {
@@ -106,7 +130,7 @@ describe('RequestContext', () => {
         });
         });
     });
     });
 
 
-    function createRequestContext() {
+    function createRequestContext(req?: any) {
         let session: CachedSession;
         let session: CachedSession;
         let channel: Channel;
         let channel: Channel;
         let activeOrder: Order;
         let activeOrder: Order;
@@ -148,6 +172,7 @@ describe('RequestContext', () => {
             languageCode: LanguageCode.en,
             languageCode: LanguageCode.en,
             channel,
             channel,
             session,
             session,
+            req: req ?? {},
             isAuthorized: true,
             isAuthorized: true,
             authorizedAsOwnerOnly: false,
             authorizedAsOwnerOnly: false,
         });
         });

+ 18 - 2
packages/core/src/api/common/request-context.ts

@@ -246,8 +246,24 @@ export class RequestContext {
                     // avoid Express "deprecated: req.host" warning
                     // avoid Express "deprecated: req.host" warning
                     continue;
                     continue;
                 }
                 }
-                const val = (target as any)[key];
-                if (!isObject(val) && typeof val !== 'function') {
+                let val: any;
+                try {
+                    val = (target as any)[key];
+                } catch (e) {
+                    val = String(e);
+                }
+
+                if (Array.isArray(val)) {
+                    depth++;
+                    result[key] = val.map(v => {
+                        if (!isObject(v) && typeof val !== 'function') {
+                            return v;
+                        } else {
+                            return copySimpleFieldsToDepth(v, maxDepth, depth);
+                        }
+                    });
+                    depth--;
+                } else if (!isObject(val) && typeof val !== 'function') {
                     result[key] = val;
                     result[key] = val;
                 } else if (depth < maxDepth) {
                 } else if (depth < maxDepth) {
                     depth++;
                     depth++;