'use strict'; var cookie = require('cookie'); var urlParser = require('url'); var stringify = require('../vendor/json-stringify-safe'); var utils = require('./utils'); module.exports.parseText = function parseText(message, kwargs) { kwargs = kwargs || {}; kwargs.message = message; return kwargs; }; module.exports.parseError = function parseError(err, kwargs, cb) { utils.parseStack(err, function(frames) { var name = ({}.hasOwnProperty.call(err, 'name') ? err.name : err.constructor.name) + ''; if (typeof kwargs.message === 'undefined') { kwargs.message = name + ': ' + (err.message || ''); } kwargs.exception = [ { type: name, value: err.message, stacktrace: { frames: frames } } ]; // Save additional error properties to `extra` under the error type (e.g. `extra.AttributeError`) var extraErrorProps; for (var key in err) { if (err.hasOwnProperty(key)) { if (key !== 'name' && key !== 'message' && key !== 'stack' && key !== 'domain') { extraErrorProps = extraErrorProps || {}; extraErrorProps[key] = err[key]; } } } if (extraErrorProps) { kwargs.extra = kwargs.extra || {}; kwargs.extra[name] = extraErrorProps; } for (var n = frames.length - 1; n >= 0; n--) { if (frames[n].in_app) { kwargs.culprit = kwargs.culprit || utils.getCulprit(frames[n]); break; } } cb(kwargs); }); }; module.exports.parseRequest = function parseRequest(req, parseUser) { var kwargs = {}; // headers: // node, express: req.headers // koa: req.header var headers = req.headers || req.header || {}; // method: // node, express, koa: req.method var method = req.method; // host: // express: req.hostname in > 4 and req.host in < 4 // koa: req.host // node: req.headers.host var host = req.hostname || req.host || headers.host || ''; // protocol: // node: // express, koa: req.protocol var protocol = req.protocol === 'https' || req.secure || (req.socket || {}).encrypted ? 'https' : 'http'; // url (including path and query string): // node, express: req.originalUrl // koa: req.url var originalUrl = req.originalUrl || req.url; // absolute url var absoluteUrl = protocol + '://' + host + originalUrl; // query string: // node: req.url (raw) // express, koa: req.query var query = req.query || urlParser.parse(originalUrl || '', true).query; // cookies: // node, express, koa: req.headers.cookie var cookies = cookie.parse(headers.cookie || ''); // body data: // node, express, koa: req.body var data = req.body; if (['GET', 'HEAD'].indexOf(method) === -1) { if (typeof data === 'undefined') { data = ''; } } if (data && typeof data !== 'string' && {}.toString.call(data) !== '[object String]') { // Make sure the request body is a string data = stringify(data); } // http interface var http = { method: method, query_string: query, headers: headers, cookies: cookies, data: data, url: absoluteUrl }; // expose http interface kwargs.request = http; // user: typically found on req.user in express/passport patterns // five cases for parseUser value: // absent: grab only id, username, email from req.user // false: capture nothing // true: capture all keys from req.user // array: provided whitelisted keys to grab from req.user // function :: req -> user: custom parsing function if (parseUser == null) parseUser = ['id', 'username', 'email']; if (parseUser) { var user = {}; if (typeof parseUser === 'function') { user = parseUser(req); } else if (req.user) { if (parseUser === true) { for (var key in req.user) { if ({}.hasOwnProperty.call(req.user, key)) { user[key] = req.user[key]; } } } else { parseUser.forEach(function(fieldName) { if ({}.hasOwnProperty.call(req.user, fieldName)) { user[fieldName] = req.user[fieldName]; } }); } } // client ip: // node: req.connection.remoteAddress // express, koa: req.ip var ip = req.ip || (req.connection && req.connection.remoteAddress); if (ip) { user.ip_address = ip; } kwargs.user = user; } return kwargs; };