123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /*!
- * type-is
- * Copyright(c) 2014 Jonathan Ong
- * Copyright(c) 2014-2015 Douglas Christopher Wilson
- * MIT Licensed
- */
- 'use strict'
- /**
- * Module dependencies.
- * @private
- */
- var typer = require('media-typer')
- var mime = require('mime-types')
- /**
- * Module exports.
- * @public
- */
- module.exports = typeofrequest
- module.exports.is = typeis
- module.exports.hasBody = hasbody
- module.exports.normalize = normalize
- module.exports.match = mimeMatch
- /**
- * Compare a `value` content-type with `types`.
- * Each `type` can be an extension like `html`,
- * a special shortcut like `multipart` or `urlencoded`,
- * or a mime type.
- *
- * If no types match, `false` is returned.
- * Otherwise, the first `type` that matches is returned.
- *
- * @param {String} value
- * @param {Array} types
- * @public
- */
- function typeis (value, types_) {
- var i
- var types = types_
- // remove parameters and normalize
- var val = tryNormalizeType(value)
- // no type or invalid
- if (!val) {
- return false
- }
- // support flattened arguments
- if (types && !Array.isArray(types)) {
- types = new Array(arguments.length - 1)
- for (i = 0; i < types.length; i++) {
- types[i] = arguments[i + 1]
- }
- }
- // no types, return the content type
- if (!types || !types.length) {
- return val
- }
- var type
- for (i = 0; i < types.length; i++) {
- if (mimeMatch(normalize(type = types[i]), val)) {
- return type[0] === '+' || type.indexOf('*') !== -1
- ? val
- : type
- }
- }
- // no matches
- return false
- }
- /**
- * Check if a request has a request body.
- * A request with a body __must__ either have `transfer-encoding`
- * or `content-length` headers set.
- * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
- *
- * @param {Object} request
- * @return {Boolean}
- * @public
- */
- function hasbody (req) {
- return req.headers['transfer-encoding'] !== undefined ||
- !isNaN(req.headers['content-length'])
- }
- /**
- * Check if the incoming request contains the "Content-Type"
- * header field, and it contains any of the give mime `type`s.
- * If there is no request body, `null` is returned.
- * If there is no content type, `false` is returned.
- * Otherwise, it returns the first `type` that matches.
- *
- * Examples:
- *
- * // With Content-Type: text/html; charset=utf-8
- * this.is('html'); // => 'html'
- * this.is('text/html'); // => 'text/html'
- * this.is('text/*', 'application/json'); // => 'text/html'
- *
- * // When Content-Type is application/json
- * this.is('json', 'urlencoded'); // => 'json'
- * this.is('application/json'); // => 'application/json'
- * this.is('html', 'application/*'); // => 'application/json'
- *
- * this.is('html'); // => false
- *
- * @param {String|Array} types...
- * @return {String|false|null}
- * @public
- */
- function typeofrequest (req, types_) {
- var types = types_
- // no body
- if (!hasbody(req)) {
- return null
- }
- // support flattened arguments
- if (arguments.length > 2) {
- types = new Array(arguments.length - 1)
- for (var i = 0; i < types.length; i++) {
- types[i] = arguments[i + 1]
- }
- }
- // request content type
- var value = req.headers['content-type']
- return typeis(value, types)
- }
- /**
- * Normalize a mime type.
- * If it's a shorthand, expand it to a valid mime type.
- *
- * In general, you probably want:
- *
- * var type = is(req, ['urlencoded', 'json', 'multipart']);
- *
- * Then use the appropriate body parsers.
- * These three are the most common request body types
- * and are thus ensured to work.
- *
- * @param {String} type
- * @private
- */
- function normalize (type) {
- if (typeof type !== 'string') {
- // invalid type
- return false
- }
- switch (type) {
- case 'urlencoded':
- return 'application/x-www-form-urlencoded'
- case 'multipart':
- return 'multipart/*'
- }
- if (type[0] === '+') {
- // "+json" -> "*/*+json" expando
- return '*/*' + type
- }
- return type.indexOf('/') === -1
- ? mime.lookup(type)
- : type
- }
- /**
- * Check if `expected` mime type
- * matches `actual` mime type with
- * wildcard and +suffix support.
- *
- * @param {String} expected
- * @param {String} actual
- * @return {Boolean}
- * @private
- */
- function mimeMatch (expected, actual) {
- // invalid type
- if (expected === false) {
- return false
- }
- // split types
- var actualParts = actual.split('/')
- var expectedParts = expected.split('/')
- // invalid format
- if (actualParts.length !== 2 || expectedParts.length !== 2) {
- return false
- }
- // validate type
- if (expectedParts[0] !== '*' && expectedParts[0] !== actualParts[0]) {
- return false
- }
- // validate suffix wildcard
- if (expectedParts[1].substr(0, 2) === '*+') {
- return expectedParts[1].length <= actualParts[1].length + 1 &&
- expectedParts[1].substr(1) === actualParts[1].substr(1 - expectedParts[1].length)
- }
- // validate subtype
- if (expectedParts[1] !== '*' && expectedParts[1] !== actualParts[1]) {
- return false
- }
- return true
- }
- /**
- * Normalize a type and remove parameters.
- *
- * @param {string} value
- * @return {string}
- * @private
- */
- function normalizeType (value) {
- // parse the type
- var type = typer.parse(value)
- // remove the parameters
- type.parameters = undefined
- // reformat it
- return typer.format(type)
- }
- /**
- * Try to normalize a type and remove parameters.
- *
- * @param {string} value
- * @return {string}
- * @private
- */
- function tryNormalizeType (value) {
- if (!value) {
- return null
- }
- try {
- return normalizeType(value)
- } catch (err) {
- return null
- }
- }
|