From 06c53d1f73378a02e4e954d69312d9c0442880ec Mon Sep 17 00:00:00 2001 From: Ahmet Ozisik Date: Mon, 9 Jan 2017 19:01:52 +0300 Subject: [PATCH] xml support added --- lib/content-negotiation.js | 5 +++ lib/send-xml.js | 14 +++++++ package.json | 1 + test/handler.test.js | 75 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 lib/send-xml.js diff --git a/lib/content-negotiation.js b/lib/content-negotiation.js index 5605f9a..7a676ed 100644 --- a/lib/content-negotiation.js +++ b/lib/content-negotiation.js @@ -8,6 +8,7 @@ var accepts = require('accepts'); var debug = require('debug')('strong-error-handler:http-response'); var sendJson = require('./send-json'); var sendHtml = require('./send-html'); +var sendXml = require('./send-xml'); var util = require('util'); module.exports = negotiateContentProducer; @@ -24,6 +25,7 @@ function negotiateContentProducer(req, options) { var SUPPORTED_TYPES = [ 'application/json', 'json', 'text/html', 'html', + 'text/xml', 'xml', ]; options = options || {}; @@ -82,5 +84,8 @@ function resolveOperation(contentType) { case 'text/html': case 'html': return sendHtml; + case 'text/xml': + case 'xml': + return sendXml; } } diff --git a/lib/send-xml.js b/lib/send-xml.js new file mode 100644 index 0000000..5427a71 --- /dev/null +++ b/lib/send-xml.js @@ -0,0 +1,14 @@ +// Copyright IBM Corp. 2016. All Rights Reserved. +// Node module: strong-error-handler +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; + +var js2xmlparser = require('js2xmlparser'); + +module.exports = function sendXml(res, data) { + var content = js2xmlparser.parse('error', data); + res.setHeader('Content-Type', 'text/xml; charset=utf-8'); + res.end(content, 'utf-8'); +}; diff --git a/package.json b/package.json index f3aa0a3..f324af8 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "debug": "^2.2.0", "ejs": "^2.4.2", "http-status": "^0.2.2", + "js2xmlparser": "^2.0.2", "strong-globalize": "^2.6.7" }, "devDependencies": { diff --git a/test/handler.test.js b/test/handler.test.js index 0dad7c9..c95fd56 100644 --- a/test/handler.test.js +++ b/test/handler.test.js @@ -435,6 +435,81 @@ describe('strong-error-handler', function() { } }); + context('XML response', function() { + it('contains all error properties when debug=true', function(done) { + var error = new ErrorWithProps({ + message: 'a test error message', + details: 'some details', + extra: 'sensitive data', + }); + error.statusCode = 500; + givenErrorHandlerForError(error, {debug: true}); + requestXML() + .expect(500) + .expect(/500<\/statusCode>/) + .expect(/ErrorWithProps<\/name>/) + .expect(/a test error message<\/message>/) + .expect(/
some details<\/details>/) + .expect(/sensitive data<\/extra>/) + .expect(/ErrorWithProps: a test error message(.*?)/, done); + }); + + it('contains subset of properties when status=4xx', function(done) { + var error = new ErrorWithProps({ + name: 'ValidationError', + message: 'The model instance is not valid.', + statusCode: 422, + details: 'some details', + extra: 'sensitive data', + }); + givenErrorHandlerForError(error, {debug: false}); + requestXML() + .end(function(err, res) { + expect(res.statusCode).to.eql(422); + var body = res.error.text; + expect(body).to.match(/
some details<\/details>/); + expect(body).to.not.match(/sensitive data<\/extra>/); + expect(body).to.match(/ValidationError<\/name>/); + expect(body).to.match( + /The model instance is not valid.<\/message>/ + ); + done(); + }); + }); + + it('contains only safe info when status=5xx', function(done) { + // Mock an error reported by fs.readFile + var error = new ErrorWithProps({ + name: 'Error', + message: 'ENOENT: no such file or directory, open "/etc/passwd"', + errno: -2, + code: 'ENOENT', + syscall: 'open', + path: '/etc/password', + }); + givenErrorHandlerForError(error); + + requestXML() + .end(function(err, res) { + expect(res.statusCode).to.eql(500); + var body = res.error.text; + expect(body).to.not.match(/\/etc\/password/); + expect(body).to.not.match(/-2/); + expect(body).to.not.match(/ENOENT/); + // only have the following + expect(body).to.match(/500<\/statusCode>/); + expect(body).to.match(/Internal Server Error<\/message>/); + done(); + }); + }); + + function requestXML(url) { + return request.get(url || '/') + .set('Accept', 'text/xml') + .expect('Content-Type', /^text\/xml/); + } + }); + context('Content Negotiation', function() { it('defaults to json without options', function(done) { givenErrorHandlerForError(new Error('Some error'), {});