second
[josuexyz/.git] / node_modules / accepts / index.js
1 /*!
2  * accepts
3  * Copyright(c) 2014 Jonathan Ong
4  * Copyright(c) 2015 Douglas Christopher Wilson
5  * MIT Licensed
6  */
7
8 'use strict'
9
10 /**
11  * Module dependencies.
12  * @private
13  */
14
15 var Negotiator = require('negotiator')
16 var mime = require('mime-types')
17
18 /**
19  * Module exports.
20  * @public
21  */
22
23 module.exports = Accepts
24
25 /**
26  * Create a new Accepts object for the given req.
27  *
28  * @param {object} req
29  * @public
30  */
31
32 function Accepts (req) {
33   if (!(this instanceof Accepts)) {
34     return new Accepts(req)
35   }
36
37   this.headers = req.headers
38   this.negotiator = new Negotiator(req)
39 }
40
41 /**
42  * Check if the given `type(s)` is acceptable, returning
43  * the best match when true, otherwise `undefined`, in which
44  * case you should respond with 406 "Not Acceptable".
45  *
46  * The `type` value may be a single mime type string
47  * such as "application/json", the extension name
48  * such as "json" or an array `["json", "html", "text/plain"]`. When a list
49  * or array is given the _best_ match, if any is returned.
50  *
51  * Examples:
52  *
53  *     // Accept: text/html
54  *     this.types('html');
55  *     // => "html"
56  *
57  *     // Accept: text/*, application/json
58  *     this.types('html');
59  *     // => "html"
60  *     this.types('text/html');
61  *     // => "text/html"
62  *     this.types('json', 'text');
63  *     // => "json"
64  *     this.types('application/json');
65  *     // => "application/json"
66  *
67  *     // Accept: text/*, application/json
68  *     this.types('image/png');
69  *     this.types('png');
70  *     // => undefined
71  *
72  *     // Accept: text/*;q=.5, application/json
73  *     this.types(['html', 'json']);
74  *     this.types('html', 'json');
75  *     // => "json"
76  *
77  * @param {String|Array} types...
78  * @return {String|Array|Boolean}
79  * @public
80  */
81
82 Accepts.prototype.type =
83 Accepts.prototype.types = function (types_) {
84   var types = types_
85
86   // support flattened arguments
87   if (types && !Array.isArray(types)) {
88     types = new Array(arguments.length)
89     for (var i = 0; i < types.length; i++) {
90       types[i] = arguments[i]
91     }
92   }
93
94   // no types, return all requested types
95   if (!types || types.length === 0) {
96     return this.negotiator.mediaTypes()
97   }
98
99   // no accept header, return first given type
100   if (!this.headers.accept) {
101     return types[0]
102   }
103
104   var mimes = types.map(extToMime)
105   var accepts = this.negotiator.mediaTypes(mimes.filter(validMime))
106   var first = accepts[0]
107
108   return first
109     ? types[mimes.indexOf(first)]
110     : false
111 }
112
113 /**
114  * Return accepted encodings or best fit based on `encodings`.
115  *
116  * Given `Accept-Encoding: gzip, deflate`
117  * an array sorted by quality is returned:
118  *
119  *     ['gzip', 'deflate']
120  *
121  * @param {String|Array} encodings...
122  * @return {String|Array}
123  * @public
124  */
125
126 Accepts.prototype.encoding =
127 Accepts.prototype.encodings = function (encodings_) {
128   var encodings = encodings_
129
130   // support flattened arguments
131   if (encodings && !Array.isArray(encodings)) {
132     encodings = new Array(arguments.length)
133     for (var i = 0; i < encodings.length; i++) {
134       encodings[i] = arguments[i]
135     }
136   }
137
138   // no encodings, return all requested encodings
139   if (!encodings || encodings.length === 0) {
140     return this.negotiator.encodings()
141   }
142
143   return this.negotiator.encodings(encodings)[0] || false
144 }
145
146 /**
147  * Return accepted charsets or best fit based on `charsets`.
148  *
149  * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
150  * an array sorted by quality is returned:
151  *
152  *     ['utf-8', 'utf-7', 'iso-8859-1']
153  *
154  * @param {String|Array} charsets...
155  * @return {String|Array}
156  * @public
157  */
158
159 Accepts.prototype.charset =
160 Accepts.prototype.charsets = function (charsets_) {
161   var charsets = charsets_
162
163   // support flattened arguments
164   if (charsets && !Array.isArray(charsets)) {
165     charsets = new Array(arguments.length)
166     for (var i = 0; i < charsets.length; i++) {
167       charsets[i] = arguments[i]
168     }
169   }
170
171   // no charsets, return all requested charsets
172   if (!charsets || charsets.length === 0) {
173     return this.negotiator.charsets()
174   }
175
176   return this.negotiator.charsets(charsets)[0] || false
177 }
178
179 /**
180  * Return accepted languages or best fit based on `langs`.
181  *
182  * Given `Accept-Language: en;q=0.8, es, pt`
183  * an array sorted by quality is returned:
184  *
185  *     ['es', 'pt', 'en']
186  *
187  * @param {String|Array} langs...
188  * @return {Array|String}
189  * @public
190  */
191
192 Accepts.prototype.lang =
193 Accepts.prototype.langs =
194 Accepts.prototype.language =
195 Accepts.prototype.languages = function (languages_) {
196   var languages = languages_
197
198   // support flattened arguments
199   if (languages && !Array.isArray(languages)) {
200     languages = new Array(arguments.length)
201     for (var i = 0; i < languages.length; i++) {
202       languages[i] = arguments[i]
203     }
204   }
205
206   // no languages, return all requested languages
207   if (!languages || languages.length === 0) {
208     return this.negotiator.languages()
209   }
210
211   return this.negotiator.languages(languages)[0] || false
212 }
213
214 /**
215  * Convert extnames to mime.
216  *
217  * @param {String} type
218  * @return {String}
219  * @private
220  */
221
222 function extToMime (type) {
223   return type.indexOf('/') === -1
224     ? mime.lookup(type)
225     : type
226 }
227
228 /**
229  * Check if mime is valid.
230  *
231  * @param {String} type
232  * @return {String}
233  * @private
234  */
235
236 function validMime (type) {
237   return typeof type === 'string'
238 }