From 4b3c8020888fa4d3a8df298a177d9608529911b9 Mon Sep 17 00:00:00 2001
From: dkrantsberg <dkrants@gmail.com>
Date: Tue, 3 Sep 2019 17:24:40 -0400
Subject: [PATCH] fix: handle Error objects with circular properties

---
 lib/send-json.js     |  4 +++-
 package.json         |  1 +
 test/handler.test.js | 21 +++++++++++++++++++++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/lib/send-json.js b/lib/send-json.js
index e33886c..dc6b5a2 100644
--- a/lib/send-json.js
+++ b/lib/send-json.js
@@ -5,8 +5,10 @@
 
 'use strict';
 
+var safeStringify = require('fast-safe-stringify');
+
 module.exports = function sendJson(res, data) {
-  var content = JSON.stringify({error: data});
+  var content = safeStringify({error: data});
   res.setHeader('Content-Type', 'application/json; charset=utf-8');
   res.end(content, 'utf-8');
 };
diff --git a/package.json b/package.json
index 6fcc1e3..0a9dcf4 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
     "accepts": "^1.3.3",
     "debug": "^3.1.0",
     "ejs": "^2.6.1",
+    "fast-safe-stringify": "^2.0.6",
     "http-status": "^1.1.2",
     "js2xmlparser": "^3.0.0",
     "strong-globalize": "^4.1.0"
diff --git a/test/handler.test.js b/test/handler.test.js
index 0423644..455571a 100644
--- a/test/handler.test.js
+++ b/test/handler.test.js
@@ -520,6 +520,27 @@ describe('strong-error-handler', function() {
       });
     });
 
+    it('handles Error objects containing circular properties', function(done) {
+      var circularObject = {};
+      circularObject.recursiveProp = circularObject;
+      var error = new ErrorWithProps({
+        statusCode: 422,
+        message: 'The model instance is not valid.',
+        name: 'ValidationError',
+        code: 'VALIDATION_ERROR',
+        details: circularObject,
+      });
+      givenErrorHandlerForError(error, {debug: true});
+      requestJson().end(function(err, res) {
+        if (err) return done(err);
+        expect(res.body).to.have.property('error');
+        expect(res.body.error).to.have.property('details');
+        expect(res.body.error.details).to.have.property('recursiveProp',
+          '[Circular]');
+        done();
+      });
+    });
+
     function requestJson(url) {
       return request.get(url || '/')
         .set('Accept', 'text/plain')