react / wstein / node_modules / jest-cli / node_modules / jsdom / node_modules / request / node_modules / hawk / lib / utils.js
81146 views// Load modules12var Sntp = require('sntp');3var Boom = require('boom');456// Declare internals78var internals = {};91011exports.version = function () {1213return require('../package.json').version;14};151617// Extract host and port from request1819// $1 $220internals.hostHeaderRegex = /^(?:(?:\r\n)?\s)*((?:[^:]+)|(?:\[[^\]]+\]))(?::(\d+))?(?:(?:\r\n)?\s)*$/; // (IPv4, hostname)|(IPv6)212223exports.parseHost = function (req, hostHeaderName) {2425hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');26var hostHeader = req.headers[hostHeaderName];27if (!hostHeader) {28return null;29}3031var hostParts = hostHeader.match(internals.hostHeaderRegex);32if (!hostParts) {33return null;34}3536return {37name: hostParts[1],38port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))39};40};414243// Parse Content-Type header content4445exports.parseContentType = function (header) {4647if (!header) {48return '';49}5051return header.split(';')[0].trim().toLowerCase();52};535455// Convert node's to request configuration object5657exports.parseRequest = function (req, options) {5859if (!req.headers) {60return req;61}6263// Obtain host and port information6465if (!options.host || !options.port) {66var host = exports.parseHost(req, options.hostHeaderName);67if (!host) {68return new Error('Invalid Host header');69}70}7172var request = {73method: req.method,74url: req.url,75host: options.host || host.name,76port: options.port || host.port,77authorization: req.headers.authorization,78contentType: req.headers['content-type'] || ''79};8081return request;82};838485exports.now = function (localtimeOffsetMsec) {8687return Sntp.now() + (localtimeOffsetMsec || 0);88};899091exports.nowSecs = function (localtimeOffsetMsec) {9293return Math.floor(exports.now(localtimeOffsetMsec) / 1000);94};959697// Parse Hawk HTTP Authorization header9899exports.parseAuthorizationHeader = function (header, keys) {100101keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];102103if (!header) {104return Boom.unauthorized(null, 'Hawk');105}106107var headerParts = header.match(/^(\w+)(?:\s+(.*))?$/); // Header: scheme[ something]108if (!headerParts) {109return Boom.badRequest('Invalid header syntax');110}111112var scheme = headerParts[1];113if (scheme.toLowerCase() !== 'hawk') {114return Boom.unauthorized(null, 'Hawk');115}116117var attributesString = headerParts[2];118if (!attributesString) {119return Boom.badRequest('Invalid header syntax');120}121122var attributes = {};123var errorMessage = '';124var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {125126// Check valid attribute names127128if (keys.indexOf($1) === -1) {129errorMessage = 'Unknown attribute: ' + $1;130return;131}132133// Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9134135if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {136errorMessage = 'Bad attribute value: ' + $1;137return;138}139140// Check for duplicates141142if (attributes.hasOwnProperty($1)) {143errorMessage = 'Duplicate attribute: ' + $1;144return;145}146147attributes[$1] = $2;148return '';149});150151if (verify !== '') {152return Boom.badRequest(errorMessage || 'Bad header format');153}154155return attributes;156};157158159exports.unauthorized = function (message) {160161return Boom.unauthorized(message, 'Hawk');162};163164165166