Promise.resolve().then(() => { const type = req.headers['content-type'] || 'text/plain' const length = req.headers['content-length'] encoding = encoding === undefined ? typer.parse(type).parameters.charset : encoding const body = rawBodyMap.get(req) if (body) { return body } return getRawBody(req, { limit, length, encoding }) .then(buf => { rawBodyMap.set(req, buf) return buf }) .catch(err => { if (err.type === 'entity.too.large') { throw createError(413, `Body exceeded ${limit} limit`, err) } else { throw createError(400, 'Invalid body', err) } }) })
app.post('/gzh', function (req, res, next) { //console.log(req.query); var token = config.weixinGZH.token; // var openID = req.query.openid; var signature = req.query.signature; var nonce = req.query.nonce; var timestamp = req.query.timestamp; var str = [token, timestamp, nonce].sort().join(''); var sha = sha1(str); if (sha === signature) { Promise.resolve(getRawBody(req, { length: req.headers['content-length'], limit: '1mb', encoding: typer.parse(req.headers['content-type']).parameters.charset })).then(function (rawBodyData) { req.rawBodyData = rawBodyData; //console.log('rawBodyData is\n', req.rawBodyData.toString()); return utils.parseXMLAsync(rawBodyData); }).then(function (jsonData) { req.messageFromWeixin = utils.formatMessage(jsonData.xml); //console.log('message from weixin\n', req.messageFromWeixin) username = req.messageFromWeixin.FromUserName; return messageProcessor(req.messageFromWeixin, app) }).then(function (xmlReply) { console.log('message to weixin\n', xmlReply) res.send(xmlReply) }).catch(function (e) { res.send(e.statusText); }); } else { res.send('微信server以外的请求'); } });
function rawBodyParser(req, res, next) { if (req._body) { return next(); } req.body = ""; req._body = true; var isText = true; var checkUTF = false; if (req.headers['content-type']) { var parsedType = typer.parse(req.headers['content-type']) if (parsedType.type === "text") { isText = true; } else if (parsedType.subtype === "xml" || parsedType.suffix === "xml") { isText = true; } else if (parsedType.type !== "application") { isText = false; } else if (parsedType.subtype !== "octet-stream") { checkUTF = true; } } getBody(req, { length: req.headers['content-length'], encoding: isText ? "utf8" : null }, function (err, buf) { if (err) { return next(err); } if (!isText && checkUTF && isUtf8(buf)) { buf = buf.toString() } req.body = buf; next(); }); }
}, function (body) { collectAverages(Date.now() - stopwatch) var parsed = body var display = null var type = typer.parse(response.headers['content-type'] || 'application/octet-stream') switch (type.type + '/' + type.subtype) { case 'application/json': display = parsed = JSON.parse(body) break case 'text/html': case 'text/plain': display = body.toString() break } response.okay = Math.floor(response.statusCode / 100) == 2 log.call(this, 'response', { status: 'responded', options: options, sent: request.payload, received: display, statusCode: response.statusCode, headers: response.headers }) if (request.grant == 'cc' && response.statusCode == 401) { delete this._tokens[request.key] } return [ parsed, response, body ] })
/** * Parses a given content-type header into media type. * @param {string} contentType * @returns {[Error, MediaType]} */ function parseContentType(contentType) { try { const { type } = contentTypeUtils.parse(`${contentType}`); return mediaTyper.parse(type); } catch (error) { return null; } }
function getEncoding (type) { if (!type) return encoding const parsed = typer.parse(type) if (parsed) return parsed.parameters.charset || encoding return encoding }
setCharset: function(type, charset) { if (!type || !charset) { return type; } // parse type var parsed = typer.parse(type); // set charset parsed.parameters.charset = charset; // format type return typer.format(parsed); }
function typenormalize(value) { try { var type = typer.parse(value); delete type.parameters; return typer.format(type) } catch (err) { return null } }
function normalizeType(value) { // parse the type var type = typer.parse(value); // remove the parameters type.parameters = undefined; // reformat it return typer.format(type) }
exports.parseMediaType = function (srcType) { srcType = srcType || ''; try { return mediaTyper.parse(srcType); } catch (err) { exports.logger.warn('Invalid media type(%s): %s', srcType, err.toString()); return { type: 'unknown', err: err }; } };
part.on('header', function (headers) { var param = {} if (headers['content-disposition']) { var disposition = typer.parse(headers['content-disposition'][0].replace('form-data', 'form-data/text') || 'form-data/text') param.name = disposition.parameters.name if (disposition.parameters.filename) { param.fileName = disposition.parameters.filename } } if (headers['content-type']) { var type = typer.parse(headers['content-type'][0] || 'application/octet-stream') param.contentType = [[type.type, type.subtype].join('/'), type.suffix].join('+').replace(/\+$/, '') } req.multiPartParams.push(param) })
}, function (req, res) { var mime = mediaTyper.parse(req.headers['content-type']); var parser = new AttachParser(_.extend(mime, { length: req.headers['content-length'] })); parser.parse(req).fail(function (err) { test.ok(err instanceof SyntaxError); res.end(); }).done(); }, function (err) {
handle(req, res, next) { if (req.method === 'GET') return next(req, res) let type = typer.parse(req.headers['content-type']) console.log(type) getRawBody(req, { length: req.headers['content-length'], limit: '1mb', encoding: type.parameters.charset || 'utf-8' }, function (err, string) { if (err) return next(req, res) req.text = string next(req, res) }) }
, parser = (connection, callback, scopeIn) => { // parse out the body const contentType = connection.req.headers['content-type'] ? connection.req.headers['content-type'].split(';')[0] : 'application/json' , scope = scopeIn; let encoding = 'UTF-8'; if (isDefined(contentType)) { encoding = typer.parse(contentType).parameters.charset || 'UTF-8'; } if (contentType === 'multipart/form-data') { try { fileParser(connection, callback, { scope: scope }); } catch (err) { callback.apply(scope, [ null, err ]); } } else { getRawBody(connection.req, { length: connection.req.headers['content-length'] , limit: '1mb' , encoding: encoding }, (err, string) => { if (err) { events.emit('error:parse', err); callback.apply(scope, [ null, err ]); return; } if (contentType === 'application/x-www-form-urlencoded') { callback.apply(scope, [ querystring.parse(string) ]); return; } try { callback.apply(scope, [ JSON.parse(string) ]); } catch (e) { if (contentType === 'application/json') { events.emit('error:parse', e); callback.apply(scope, [ null, e ]); } else { callback.apply(scope, [ parseForm(string) ]); } } }); } };
}, function (req, res) { var mime = mediaTyper.parse(req.headers['content-type']); var parser = new AttachParser(_.extend(mime, { length: req.headers['content-length'] })); parser.parse(req).done(function (data) { test.deepEqual(data, { input: new Buffer('asd'), type: 'raw' }); res.end(); }); }, function (err) {
exports.setCharset = function(type, charset){ if (!type || !charset) return type; var parsed = typer.parse(type); var exists = parsed.parameters.charset; // keep existing charset if (exists) { return type; } // set charset parsed.parameters.charset = charset; return typer.format(parsed); };
}, function (req, res) { var mime = mediaTyper.parse(req.headers['content-type']); var parser = new AttachParser(_.extend(mime, { length: req.headers['content-length'] })); parser.parse(req).done(function (body) { test.deepEqual(body, { type: void 0, input: {} }); res.end(); }); }, function (err) {
return function textParser(req, res, next) { if (req._body) return next() req.body = req.body || {} if (!typeis(req, type)) return next() // get charset var charset = typer.parse(req).parameters.charset || defaultCharset // read read(req, res, next, parse, { encoding: charset, inflate: inflate, limit: limit, verify: verify }) }
/** * decode response body by parse `content-type`'s charset * @param {Buffer} data * @param {Http(s)Response} res * @return {String} */ function decodeBodyByCharset(data, res) { var type = res.headers['content-type']; if (!type) { return data.toString(); } var type = typer.parse(type); var charset = type.parameters.charset || 'utf-8'; if (!Buffer.isEncoding(charset)) { if (!_iconv) { _iconv = require('iconv-lite'); } return _iconv.decode(data, charset); } return data.toString(charset); }
isJsonContentType(contentTypeValue) { if (!contentTypeValue) { return false; } try { const { type } = contentType.parse(`${contentTypeValue}`); const parsed = mediaTyper.parse(type); return ( (parsed.type === 'application' && parsed.subtype === 'json') || parsed.suffix === 'json' ); } catch (e) { // The Content-Type value is basically a user input, it can be any // kind of rubbish, and it is neither this function's nor Gavel's problem // if it's invalid return false; } }
/** * Returns a tuple of error and schema media type * based on given body schema. * @param {string} bodySchema * @returns {[error, schemaType]} */ function getBodySchemaType(bodySchema) { const jsonSchemaType = mediaTyper.parse('application/schema+json'); if (typeof bodySchema !== 'string') { return [null, jsonSchemaType]; } try { jph.parse(bodySchema); return [null, jsonSchemaType]; } catch (exception) { const error = `Can't validate: expected body JSON Schema is not a parseable JSON:\n${ exception.message }`; return [error, null]; } }
}, function (req, res) { var mime = mediaTyper.parse(req.headers['content-type']); var parser = new AttachParser(_.extend(mime, { length: req.headers['content-length'] })); parser.parse(req).done(function (data) { test.deepEqual(data, { input: { dima: 'ok' }, files: {}, type: 'multipart' }); res.end(); }); }, function (err) {
app.use(function(req, res, next) { var contentType = req.headers['content-type']; var contentLength = req.headers['content-length']; var parseConfig = { length: contentLength, limit: '1mb' }; if (contentType) { parseConfig.encoding = typer.parse(contentType).parameters.charset; } getRawBody(req, parseConfig, function(err, string) { if (err) { return next(err); } req.text = string; next() }) });
/** * Returns a tuple of error and body media type based * on the given body and normalized headers. * @param {string} body * @param {Object} headers * @param {'real'|'expected'} bodyType * @returns {[error, bodyType]} */ function getBodyType(body, contentType, httpMessageOrigin) { const hasJsonContentType = isJsonContentType(contentType); try { jph.parse(body); const bodyMediaType = parseContentType( hasJsonContentType ? contentType : 'application/json' ); return [null, bodyMediaType]; } catch (parsingError) { const fallbackMediaType = mediaTyper.parse('text/plain'); const error = hasJsonContentType ? `Can't validate: ${httpMessageOrigin} body 'Content-Type' header is '${contentType}' \ but body is not a parseable JSON: ${parsingError.message}` : null; return [error, fallbackMediaType]; } }
return function urlencodedParser(req, res, next) { if (req._body) return next(); req.body = req.body || {} if (!typeis(req, type)) return next(); var charset = typer.parse(req).parameters.charset || 'utf-8' if (charset.toLowerCase() !== 'utf-8') { var err = new Error('unsupported charset') err.status = 415 next(err) return } // read read(req, res, next, parse, { encoding: charset, inflate: inflate, limit: limit, verify: verify }) }
export async function getBodyData (request) { /* parse content type so we can process data */ const contentType = request.headers['content-type'] || 'text/plain; charset=utf-8' const mediaType = typer.parse(contentType) /* get request body data */ // TODO: stream.destroy or stream.close needed for file descriptors? let body = await rawBody(request, { limit: config.payloadLimit, length: request.headers['content-length'], encoding: mediaType.parameters.charset || 'utf-8' }) /* process body data */ switch (mediaType.subtype) { case 'json': try { body = JSON.parse(body) } catch (err) { throw new Errors().badRequest('Invalid JSON payload') } break case 'x-www-form-urlencoded': try { body = qs.parse(body) } catch (err) { throw new Errors().badRequest('Invalid form data') } break case 'plain': /* no processing needed */ break default: throw new Errors().unsupportedMediaType() } return body }
app.use(function (req, res, next) { if(/^\/api\/errors/.test(req.url)){ type = req.headers['content-type'] len = req.headers['content-length'] if(type && len){ getRawBody(req, { length: len, limit: '20mb', encoding: typer.parse(type).parameters.charset }, function (err, string) { if (err) return next(err) req.text = string next() }) }else{ next() } }else{ var callback= bodyParser.urlencoded({extended: true}) callback(req, res, next) } })
app.post('/weixinopen', function (req, res, next) { console.log('来自微信开放平台\n', req.query); var token = config.weixinOpenGZH.token; // var openID = req.query.openid; var signature = req.query.signature; var nonce = req.query.nonce; var timestamp = req.query.timestamp; var str = [token, timestamp, nonce].sort().join(''); var sha = sha1(str); if (sha === signature) { Promise.resolve(getRawBody(req, { length: req.headers['content-length'], limit: '1mb', encoding: typer.parse(req.headers['content-type']).parameters.charset })).then(function (rawBodyData) { req.rawBodyDataWeixinOpen = rawBodyData; console.log('微信开发平台之公众号第三方平台 rawBodyData is\n', req.rawBodyDataWeixinOpen.toString()); return utils.parseXMLAsync(rawBodyData); }).then(function (jsonData) { req.messageFromWeixinOpen = utils.formatMessage(jsonData.xml); console.log('message from weixin open\n', req.messageFromWeixinOpen); var rawXmlVerifyTicket = new WxCrypto(config.weixinOpenGZH.token, config.weixinOpenGZH.appID, config.weixinOpenGZH.key).decrypt(req.messageFromWeixinOpen.Encrypt) console.log('xmlVerifyTicket---\n', rawXmlVerifyTicket) return utils.parseXMLAsync(rawXmlVerifyTicket); }).then(function (jsonVerifyTicket) { var verifyTicket = utils.formatMessage(jsonVerifyTicket.xml) console.log('verifyTicket json object is: ', JSON.stringify(verifyTicket)) utils.writeFileAsync(verifyTicketFile, verifyTicket.ComponentVerifyTicket) }).catch(function (e) { res.send(e.statusText); }); } else { res.send('微信server以外的请求'); } res.end() });
return function jsonParser(req, res, next) { if (req._body) return next() req.body = req.body || {} if (!typeis(req, type)) return next() // RFC 7159 sec 8.1 var charset = (typer.parse(req).parameters.charset || 'utf-8').toLowerCase() if (charset.substr(0, 4) !== 'utf-') { var err = new Error('unsupported charset "' + charset.toUpperCase() + '"') err.charset = charset err.status = 415 next(err) return } // read read(req, res, next, parse, { encoding: charset, inflate: inflate, limit: limit, verify: verify }) }
function t(o,i){var t,e,r=o.split(/ *; */),n={value:r[0],quality:1,params:{},originalIndex:i};for(t=1;t<r.length;++t)e=r[t].split(/ *= */),"q"==e[0]?n.quality=parseFloat(e[1]):n.params[e[0]]=e[1];return n}var r=require("send").mime,n=require("buffer-crc32"),o=require("crypto"),i=require("path").basename,a=require("proxy-addr"),e=require("media-typer");exports.etag=function(e,t){if(0===e.length)return'"1B2M2Y8AsgTpgAmY7PhCfg=="';var r=o.createHash("md5").update(e,t).digest("base64");return'"'+r+'"'},exports.wetag=function(e,o){var t,r;return 0===e.length?'W/"0-0"':(t=Buffer.isBuffer(e)?e:new Buffer(e,o),r=t.length,'W/"'+r.toString(16)+"-"+n.unsigned(t)+'"')},exports.isAbsolute=function(e){return"/"==e[0]?!0:":"==e[1]&&"\\"==e[2]?!0:"\\\\"==e.substring(0,2)?!0:void 0},exports.flatten=function(r,t){var n,e;for(t=t||[],n=r.length,e=0;n>e;++e)Array.isArray(r[e])?exports.flatten(r[e],t):t.push(r[e]);return t},exports.normalizeType=function(e){return~e.indexOf("/")?t(e):{value:r.lookup(e),params:{}}},exports.normalizeTypes=function(t){var e,r=[];for(e=0;e<t.length;++e)r.push(exports.normalizeType(t[e]));return r},exports.contentDisposition=function(e){var t="attachment";return e&&(e=i(e),t=/[^\040-\176]/.test(e)?'attachment; filename="'+encodeURI(e)+"\"; filename*=UTF-8''"+encodeURI(e):'attachment; filename="'+e+'"'),t},exports.compileETag=function(e){var t;if("function"==typeof e)return e;switch(e){case!0:t=exports.wetag;break;case!1:break;case"strong":t=exports.etag;break;case"weak":t=exports.wetag;break;default:throw new TypeError("unknown value for etag function: "+e)}return t},exports.compileTrust=function(e){return"function"==typeof e?e:e===!0?function(){return!0}:"number"==typeof e?function(r,t){return e>t}:("string"==typeof e&&(e=e.split(/ *, */)),a.compile(e||[]))},exports.setCharset=function(t,r){if(!t||!r)return t;var n=e.parse(t);return n.parameters.charset=r,e.format(n)};