/
websites
/
operateit-node
/
node_modules123123
/
node-res
/
Upload File
HOME
'use strict' /* * node-res * * (c) Harminder Virk <virk@adonisjs.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const mime = require('mime-types') const etag = require('etag') const contentDisposition = require('content-disposition') const vary = require('vary') const send = require('send') const methods = require('./methods') const returnContentAndType = function (body) { /** * Return the body and it's type when * body is a string. */ if (typeof (body) === 'string') { return { body, type: /^\s*</.test(body) ? 'text/html' : 'text/plain' } } /** * If body is a buffer, return the exact copy * and type as bin. */ if (Buffer.isBuffer(body)) { return { body, type: 'application/octet-stream' } } /** * If body is a number or boolean. Convert it to * a string and return the type as text. */ if (typeof (body) === 'number' || typeof (body) === 'boolean') { return { body: String(body), type: 'text/plain' } } /** * Otherwise check whether body is an object or not. If yes * stringify it and otherwise return the exact copy. */ return typeof (body) === 'object' ? { body: JSON.stringify(body), type: 'application/json' } : { body } } /** * A simple IO module to make consistent HTTP response, without * worrying about underlying details. * * @module Response */ const Response = exports = module.exports = {} Response.descriptiveMethods = Object.keys(methods).map((method) => { Response[method] = function (req, res, body) { Response.status(res, methods[method]) Response.send(req, res, body) } return method }) /** * Returns the value of an existing header on * the response object * * @method getHeader * * @param {ServerResponse} res * @param {String} key * * @return {Array|String} Return type depends upon the header existing value * * @example * ```js * nodeRes.getHeader(res, 'Content-type') * ``` */ Response.getHeader = function (res, key) { return res.getHeader(key) } /** * Sets header on the response object. This method will wipe off * existing values. To append to existing values, use `append`. * * @method header * * @param {http.ServerResponse} res * @param {String} key * @param {String|Array} value * * @return {void} * * @example * ```js * nodeRes.header(res, 'Content-type', 'application/json') * * // or set an array of headers * nodeRes.header(res, 'Link', ['<http://localhost/>', '<http://localhost:3000/>']) * ``` */ Response.header = function (res, key, value) { const values = Array.isArray(value) ? value.map(String) : value res.setHeader(key, values) } /** * Appends value to the header existing values. * * @method append * * @param {http.ServerResponse} res * @param {String} key * @param {String|Array} value * * @return {void} * * @example * ```js * nodeRes.append(res, 'Content-type', 'application/json') * * // or append an array of headers * nodeRes.append(res, 'Link', ['<http://localhost/>', '<http://localhost:3000/>']) * ``` */ Response.append = function (res, key, value) { const previousValue = Response.getHeader(res, key) const headers = previousValue ? (Array.isArray(previousValue) ? previousValue.concat(value) : [previousValue].concat(value)) : value Response.header(res, key, headers) } /** * Set status on the HTTP res object * * @method status * * @param {http.ServerResponse} res * @param {Number} code * * @return {void} * * @example * ```js * nodeRes.status(res, 200) * ``` */ Response.status = function (res, code) { res.statusCode = code } /** * Sets the header on response object, only if it * does not exists. * * @method safeHeader * * @param {http.ServerResponse} res * @param {String} key * @param {String|Array} value * * @return {void} * * @example * ```js * nodeRes.safeHeader(res, 'Content-type', 'application/json') * ``` */ Response.safeHeader = function (res, key, value) { if (!res.getHeader(key)) { Response.header(res, key, value) } } /** * Removes the header from response * * @method removeHeader * * @param {http.ServerResponse} res * @param {String} key * * @return {void} * * @example * ```js * nodeRes.removeHeader(res, 'Content-type') * ``` */ Response.removeHeader = function (res, key) { res.removeHeader(key) } /** * Write string or buffer to the response object. * * @method write * * @param {http.ServerResponse} res * @param {String|Buffer} body * * @return {void} * * @example * ```js * nodeRes.write(res, 'Hello world') * ``` */ Response.write = function (res, body) { res.write(body) } /** * Explictly end HTTP response * * @method end * * @param {http.ServerResponse} res * @param {String|Buffer} [payload] * * @return {void} * * @example * ```js * nodeRes.end(res, 'Hello world') * ``` */ Response.end = function (res, payload) { res.end(payload) } /** * Send body as the HTTP response and end it. Also * this method will set the appropriate `Content-type` * and `Content-length`. * * If body is set to null, this method will end the response * as 204. * * @method send * * @param {http.ServerRequest} req * @param {http.ServerResponse} res * @param {Mixed} body * @param {Boolean} [generateEtag = true] * * @return {void} * * @example * ```js * nodeRes.send(req, res, 'Hello world') * * // or html * nodeRes.send(req, res, '<h2> Hello world </h2>') * * // or JSON * nodeRes.send(req, res, { greeting: 'Hello world' }) * * // or Buffer * nodeRes.send(req, res, Buffer.from('Hello world', 'utf-8')) * * // Ignore etag * nodeRes.send(req, res, 'Hello world', false) * ``` */ Response.send = function (req, res, body = null, generateEtag = true) { const chunk = Response.prepare(res, body) if (chunk === null || req.method === 'HEAD') { Response.end(res) return } /** * Generate etag when instructured for */ if (generateEtag) { Response.etag(res, chunk) } Response.end(res, chunk) } /** * Sets the Etag header for a given body chunk * * @method etag * * @param {http.ServerResponse} res * @param {String|Buffer} body * * @return {void} * * @example * ```js * nodeRes.etag(res, 'Hello world') * ``` */ Response.etag = function (res, body) { Response.header(res, 'ETag', etag(body)) } /** * Prepares the response body by encoding it properly. Also * sets appropriate headers based upn the body content type. * * This method is used internally by `send`, so you should * never use it when calling `send`. * * It is helpful when you want to get the final payload and end the * response at a later stage. * * @method prepare * * @param {http.ServerResponse} res * @param {Mixed} body * * @return {String} * * @example * ```js * const chunk = nodeRes.prepare(res, '<h2> Hello </h2>') * * if (chunk) { * nodeRes.etag(res, chunk) * * if (nodeReq.fresh(req, res)) { * chunk = null * nodeRes.status(304) * } * * nodeRes.end(chunk) * } * ``` */ Response.prepare = function (res, body) { if (body === null) { Response.status(res, 204) Response.removeHeader(res, 'Content-Type') Response.removeHeader(res, 'Content-Length') Response.removeHeader(res, 'Transfer-Encoding') return null } let { body: chunk, type } = returnContentAndType(body) /** * Remove unwanted headers when statuscode is 204 or 304 */ if (res.statusCode === 204 || res.statusCode === 304) { Response.removeHeader(res, 'Content-Type') Response.removeHeader(res, 'Content-Length') Response.removeHeader(res, 'Transfer-Encoding') return chunk } const headers = typeof res.getHeaders === 'function' ? res.getHeaders() : (res._headers || {}) /** * Setting content type. Ideally we can use `Response.type`, which * sets the right charset too. But we will be doing extra * processing for no reasons. */ if (type && !headers['content-type']) { Response.header(res, 'Content-Type', `${type}; charset=utf-8`) } /** * setting up content length as response header */ if (chunk && !headers['content-length']) { Response.header(res, 'Content-Length', Buffer.byteLength(chunk)) } return chunk } /** * Prepares response for JSONP * * @method prepareJsonp * * @param {http.ServerResponse} res * @param {Object} body * @param {String} callbackFn * * @return {String} * * @example * ```js * const chunk = nodeRes.prepareJsonp(res, '<h2> Hello </h2>', 'callback') * * if (chunk) { * nodeRes.etag(res, chunk) * * if (nodeReq.fresh(req, res)) { * chunk = null * nodeRes.status(304) * } * * nodeRes.end(chunk) * } * ``` */ Response.prepareJsonp = function (res, body, callbackFn) { Response.header(res, 'X-Content-Type-Options', 'nosniff') Response.safeHeader(res, 'Content-Type', 'text/javascript; charset=utf-8') const parsedBody = JSON .stringify(body) .replace(/\u2028/g, '\\u2028') .replace(/\u2029/g, '\\u2029') /** * setting up callbackFn on response body , typeof will make * sure not to throw error of client if callbackFn is not * a function */ return '/**/ typeof ' + callbackFn + " === 'function' && " + callbackFn + '(' + parsedBody + ');' } /** * Returns the HTTP response with `Content-type` * set to `application/json`. * * @method json * * @param {http.IncomingMessage} req * @param {http.ServerResponse} res * @param {Object} body * @param {Boolean} [generateEtag = true] * * @return {void} * * @example * ```js * nodeRes.json(req, res, { name: 'virk' }) * nodeRes.json(req, res, [ 'virk', 'joe' ]) * ``` */ Response.json = function (req, res, body, generateEtag) { Response.safeHeader(res, 'Content-Type', 'application/json; charset=utf-8') Response.send(req, res, body, generateEtag) } /** * Make JSONP response with `Content-type` set to * `text/javascript`. * * @method jsonp * * @param {http.IncomingMessage} req * @param {http.ServerResponse} res * @param {Object} body * @param {String} [callbackFn = 'callback'] * @param {Boolean} [generateEtag = true] * * @return {void} * * @example * ```js * nodeRes.jsonp(req, res, { name: 'virk' }, 'callback') * ``` */ Response.jsonp = function (req, res, body, callbackFn = 'callback', generateEtag) { Response.send(req, res, Response.prepareJsonp(res, body, callbackFn), generateEtag) } /** * Download file as a stream. Stream will be closed once * download is finished. * * Options are passed directly to [send](https://www.npmjs.com/package/send) * * @method download * * @param {http.IncomingMessage} req * @param {http.ServerResponse} res * @param {String} filePath * @param {Object} [options = {}] * * @return {void} * * @example * ```js * nodeRes.download(req, res, '/storage/data.txt') * ``` */ Response.download = function (req, res, filePath, options = {}) { send(req, filePath, options).pipe(res) } /** * Send file as a stream with Content-Disposition of attachment * which forces the download of the file. * * @method attachment * * @param {http.IncomingMessage} req * @param {http.ServerResponse} res * @param {String} filePath * @param {String} [name = filePath] * @param {String} [disposition = 'attachment'] * @param {Object} [options] * * @return {void} * * @example * ```js * nodeRes.attachment(req, res, '/storage/data.txt', 'data.txt') * ``` */ Response.attachment = function (req, res, filePath, name = filePath, disposition = 'attachment', options) { Response.header(res, 'Content-Disposition', contentDisposition(name, {type: disposition})) send(req, filePath, options).pipe(res) } /** * Set `Location` header on the HTTP response. * * @method location * * @param {http.ServerResponse} res * @param {String} url * * @return {void} */ Response.location = function (res, url) { Response.header(res, 'Location', url) } /** * Redirect the HTTP request to the given url. * * @method redirect * * @param {http.IncomingMessage} req * @param {http.ServerResponse} res * @param {String} url * @param {Number} [status = 302] * * @return {void} * * @example * ```js * nodeRes.redirect(req, res, '/') * ``` */ Response.redirect = function (req, res, url, status = 302) { const body = '' Response.status(res, status) Response.location(res, url) Response.send(req, res, body) } /** * Add vary header to the HTTP response. * * @method vary * * @param {http.ServerResponse} res * @param {String} field * * @return {void} */ Response.vary = function (res, field) { vary(res, field) } /** * Set content type header by looking up the actual * type and setting charset to utf8. * * ### Note * When defining custom charset, you must set pass the complete * content type, otherwise `false` will be set as the * content-type header. * * @method type * * @param {http.IncomingMessage} req * @param {http.ServerResponse} res * @param {String} [charset] * @return {void} * * @example * ```js * nodeRes.type(res, 'html') * * nodeRes.type(res, 'json') * * nodeRes.type(res, 'text/html', 'ascii') * ``` */ Response.type = function (res, type, charset) { type = charset ? `${type}; charset=${charset}` : type Response.safeHeader(res, 'Content-Type', mime.contentType(type)) }