From 904abea92318570b76d036eaccface3b9562b853 Mon Sep 17 00:00:00 2001 From: Cristian Date: Tue, 28 Jan 2025 18:44:54 -0300 Subject: [PATCH] refactor: res.download lower complexity --- lib/response.js | 61 ++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/lib/response.js b/lib/response.js index f6f5740d2d..7df82a8b88 100644 --- a/lib/response.js +++ b/lib/response.js @@ -417,31 +417,38 @@ res.sendFile = function sendFile(path, options, callback) { * to set the attachment and filename. * * This method uses `res.sendFile()`. - * + * + * Examples: + * + * // Basic usage with path + * res.download('/path/to/file.csv'); + * + * // With filename and callback + * res.download('/path/to/file.csv', 'report.csv', (err) => { ... }); + * + * // With options (no filename) + * res.download('/path/to/file.csv', { headers: { 'Cache-Control': 'no-cache' } }); + * + * @param {String} path + * @param {String|Function|Object} [filename] + * @param {Object|Function} [options] + * @param {Function} [callback] * @public */ res.download = function download (path, filename, options, callback) { - var done = callback; - var name = filename; - var opts = options || null - - // support function as second or third arg - if (typeof filename === 'function') { - done = filename; - name = null; - opts = null - } else if (typeof options === 'function') { - done = options - opts = null - } + // identify the callback among the [filename, options, callback] + const done = [filename, options, callback].find(arg => typeof arg === 'function'); - // support optional filename, where options may be in it's place - if (typeof filename === 'object' && - (typeof options === 'function' || options === undefined)) { - name = null - opts = filename - } + var name = null; + var opts = {}; + + // determine if filename is a object or string + if (typeof filename === 'string') name = filename; + else if (typeof filename === 'object') opts = filename; + + // if options is a function, set it as callback + if (typeof options === 'object') opts = Object.assign({}, opts, options); // set Content-Disposition when file is sent var headers = { @@ -450,13 +457,11 @@ res.download = function download (path, filename, options, callback) { // merge user-provided headers if (opts && opts.headers) { - var keys = Object.keys(opts.headers) - for (var i = 0; i < keys.length; i++) { - var key = keys[i] + Object.keys(opts.headers).forEach(key => { if (key.toLowerCase() !== 'content-disposition') { - headers[key] = opts.headers[key] + headers[key] = opts.headers[key]; } - } + }); } // merge user-provided options @@ -464,9 +469,7 @@ res.download = function download (path, filename, options, callback) { opts.headers = headers // Resolve the full path for sendFile - var fullPath = !opts.root - ? resolve(path) - : path + var fullPath = !opts.root ? resolve(path) : path // send file return this.sendFile(fullPath, opts, done) @@ -865,7 +868,7 @@ res.vary = function(field){ * * - `cache` boolean hinting to the engine it should cache * - `filename` filename of the view being rendered - * + * * @public */