millas 0.2.32 → 0.2.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -197,13 +197,50 @@ class MillasResponse {
|
|
|
197
197
|
});
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
/** File download / serve response
|
|
201
|
-
|
|
200
|
+
/** File download / serve response.
|
|
201
|
+
*
|
|
202
|
+
* filePath can be:
|
|
203
|
+
* - string — path on disk
|
|
204
|
+
* - Buffer — in-memory buffer (requires mimetype)
|
|
205
|
+
* - Readable — Node stream (requires mimetype)
|
|
206
|
+
*
|
|
207
|
+
* Options:
|
|
208
|
+
* download {boolean} — force Content-Disposition: attachment
|
|
209
|
+
* name {string} — filename for Content-Disposition
|
|
210
|
+
* mimetype {string} — override Content-Type
|
|
211
|
+
* maxAge {number} — Cache-Control max-age in seconds
|
|
212
|
+
* lastModified {Date|string} — override Last-Modified header
|
|
213
|
+
*/
|
|
214
|
+
static file(filePath, { download = false, name = null, mimetype = null, maxAge = null, lastModified = null, headers = {} } = {}) {
|
|
215
|
+
const isBuffer = Buffer.isBuffer(filePath);
|
|
216
|
+
const isStream = filePath && typeof filePath.pipe === 'function';
|
|
217
|
+
const isInMemory = isBuffer || isStream;
|
|
218
|
+
|
|
219
|
+
const extraHeaders = {};
|
|
220
|
+
if (mimetype) extraHeaders['Content-Type'] = mimetype;
|
|
221
|
+
if (maxAge !== null) extraHeaders['Cache-Control'] = `public, max-age=${maxAge}`;
|
|
222
|
+
if (lastModified) extraHeaders['Last-Modified'] = new Date(lastModified).toUTCString();
|
|
223
|
+
if (download || name) {
|
|
224
|
+
extraHeaders['Content-Disposition'] =
|
|
225
|
+
`attachment; filename="${name || (typeof filePath === 'string' ? require('path').basename(filePath) : 'download')}"` ;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (isInMemory) {
|
|
229
|
+
const { Readable } = require('stream');
|
|
230
|
+
const readable = isBuffer ? Readable.from(filePath) : filePath;
|
|
231
|
+
return new MillasResponse({
|
|
232
|
+
type: 'stream',
|
|
233
|
+
body: readable,
|
|
234
|
+
status: 200,
|
|
235
|
+
headers: { ...extraHeaders, ...headers },
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
202
239
|
return new MillasResponse({
|
|
203
240
|
type: 'file',
|
|
204
|
-
body: { path: filePath, download, name },
|
|
241
|
+
body: { path: filePath, download, name, mimetype, maxAge, lastModified },
|
|
205
242
|
status: 200,
|
|
206
|
-
headers,
|
|
243
|
+
headers: { ...extraHeaders, ...headers },
|
|
207
244
|
});
|
|
208
245
|
}
|
|
209
246
|
|
|
@@ -211,14 +211,17 @@ class ExpressAdapter extends HttpAdapter {
|
|
|
211
211
|
return expressRes.end();
|
|
212
212
|
|
|
213
213
|
case 'file': {
|
|
214
|
-
const {path: filePath, download, name: fileName} = body;
|
|
214
|
+
const { path: filePath, download, name: fileName, mimetype } = body;
|
|
215
|
+
const sendOpts = {};
|
|
216
|
+
if (mimetype) expressRes.setHeader('Content-Type', mimetype);
|
|
215
217
|
if (download) {
|
|
216
218
|
return expressRes.download(
|
|
217
219
|
filePath,
|
|
218
|
-
fileName || require('path').basename(filePath)
|
|
220
|
+
fileName || require('path').basename(filePath),
|
|
221
|
+
sendOpts
|
|
219
222
|
);
|
|
220
223
|
}
|
|
221
|
-
return expressRes.sendFile(require('path').resolve(filePath));
|
|
224
|
+
return expressRes.sendFile(require('path').resolve(filePath), sendOpts);
|
|
222
225
|
}
|
|
223
226
|
|
|
224
227
|
case 'view': {
|
package/src/http/helpers.js
CHANGED
|
@@ -46,16 +46,21 @@ function text(content, options = {}) {
|
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Serve a file.
|
|
49
|
-
*
|
|
49
|
+
*
|
|
50
|
+
* filePath can be a string path, Buffer, or Readable stream.
|
|
51
|
+
* String paths are validated against app.storageRoot (config/app.js).
|
|
50
52
|
* Any path that escapes the storage root throws a 403.
|
|
53
|
+
*
|
|
54
|
+
* Options: download, name, mimetype, maxAge, lastModified
|
|
51
55
|
*/
|
|
52
56
|
function file(filePath, options = {}) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
if (typeof filePath === 'string') {
|
|
58
|
+
const { resolveStoragePath, SafeFilePath } = require('./SafeFilePath');
|
|
59
|
+
const root = SafeFilePath.getStorageRoot();
|
|
60
|
+
if (root) {
|
|
61
|
+
const safe = resolveStoragePath(filePath, root);
|
|
62
|
+
return MillasResponse.file(safe, options);
|
|
63
|
+
}
|
|
59
64
|
}
|
|
60
65
|
return MillasResponse.file(filePath, options);
|
|
61
66
|
}
|