Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for \t in content-type header #814

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 43 additions & 27 deletions lib/bindings/HTTPBinding.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,19 @@ const config = require('../configService');
let httpBindingServer;
const transport = 'HTTP';

const { promisify } = require('util');
const json = promisify(bodyParser.json({ strict: false })); // accept anything JSON.parse accepts.
const text = promisify(bodyParser.text());
const raw = promisify(bodyParser.raw());
const xml2js = require('xml2js');
const xmlStripPrefix = xml2js.processors.stripPrefix;
const xml = promisify(
bodyParser.xml({
const typeis = require('type-is');

function parserBody() {
const json = bodyParser.json({ strict: false }); // accept anything JSON.parse accepts.
const text = bodyParser.text();
const raw = bodyParser.raw();
const xml = bodyParser.xml({
// Tell bodyparser-xml to not check the Content-Type header,
// we will check it ourselves. This works around upstream bug
// https://github.com/jshttp/type-is/issues/52
type: () => true,
xmlParseOptions: {
// XML namespaces might change from one request to the next.
// It is useful to remove them from the document,
Expand All @@ -67,24 +72,39 @@ const xml = promisify(
attrNameProcessors: [xmlStripPrefix]
}
})
);

function parserBody() {
// generic bodyParser
return function (req, res, next) {
if (req.is('text/plain')) {
text(req, res).then(() => next(), next);
} else if (req.is('application/octet-stream')) {
raw(req, res).then(() => next(), next);
} else if (req.is('application/soap+xml')) {
xml(req, res).then(() => next(), next);
// use typeis.is on a trimmed header, instead of
// req.is on the request, to work around
// https://github.com/jshttp/type-is/issues/52
const contentType = req.get('content-type').split(';').shift().trim();
if (typeis.is(contentType, ['text/plain'])) {
text(req, res, next)
} else if (typeis.is(contentType, ['application/octet-stream'])) {
raw(req, res, next)
} else if (typeis.is(contentType, ['application/soap+xml'])) {
xml(req, res, next)
} else {
// req.is('json')
json(req, res).then(() => next(), next);
json(req, res, next)
}
};
}

function checkPostContentType(...mimeTypes) {
return function (req, res, next) {
let err
// use typeis.is on a trimmed header, instead of
// req.is on the request, to work around
// https://github.com/jshttp/type-is/issues/52
const contentType = req.get('content-type').split(';').shift().trim();
if (!typeis.hasBody(req) || !typeis.is(contentType, mimeTypes)) {
err = new errors.UnsupportedType(mimeTypes.join(', '));
}
next(err);
};
}

function checkMandatoryParams(queryPayload) {
return function (req, res, next) {
const notFoundParams = [];
Expand All @@ -106,17 +126,6 @@ function checkMandatoryParams(queryPayload) {
if (queryPayload && !req.query.d && req.query.getCmd !== '1') {
notFoundParams.push('Payload');
}
if (
req.method === 'POST' &&
!req.is('json') &&
!req.is('text/plain') &&
!req.is('application/octet-stream') &&
!req.is('application/soap+xml')
) {
error = new errors.UnsupportedType(
'application/json, text/plain, application/octet-stream, application/soap+xml'
);
}

if (notFoundParams.length !== 0) {
next(new errors.MandatoryParamsNotFound(notFoundParams));
Expand Down Expand Up @@ -681,6 +690,8 @@ function start(callback) {

httpBindingServer.router.post(
config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH,
// text and octet-stream allowed for backward compatibility
checkPostContentType('application/json', 'text/plain', 'application/octet-stream'),
bodyParser.json({ strict: false }), // accept anything JSON.parse accepts
checkMandatoryParams(false),
parseDataMultipleMeasure,
Expand All @@ -694,6 +705,7 @@ function start(callback) {
'/' +
constants.MEASURES_SUFIX +
'/:attrValue',
checkPostContentType('application/json', 'text/plain', 'application/octet-stream', 'application/soap+xml'),
parserBody(),
checkMandatoryParams(false),
parseData, // non multiple measures are expected in this route
Expand All @@ -704,6 +716,8 @@ function start(callback) {

httpBindingServer.router.post(
(config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH) + constants.HTTP_COMMANDS_PATH,
// text and octet-stream allowed for backward compatibility
checkPostContentType('application/json', 'text/plain', 'application/octet-stream'),
bodyParser.json({ strict: false }), // accept anything JSON.parse accepts.
checkMandatoryParams(false),
parseData,
Expand All @@ -715,6 +729,8 @@ function start(callback) {

httpBindingServer.router.post(
(config.getConfig().iota.defaultResource || constants.HTTP_MEASURE_PATH) + constants.HTTP_CONFIGURATION_PATH,
// text and octet-stream allowed for backward compatibility
checkPostContentType('application/json', 'text/plain', 'application/octet-stream'),
bodyParser.json({ strict: false }), // accept anything JSON.parse accepts.
checkMandatoryParams(false),
parseData,
Expand Down
Loading