first commit
This commit is contained in:
194
app_vue/node_modules/sirv/build.js
generated
vendored
Normal file
194
app_vue/node_modules/sirv/build.js
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
const fs = require('fs');
|
||||
const { join, normalize, resolve } = require('path');
|
||||
const { totalist } = require('totalist/sync');
|
||||
const { parse } = require('@polka/url');
|
||||
const { lookup } = require('mrmime');
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
function isMatch(uri, arr) {
|
||||
for (let i=0; i < arr.length; i++) {
|
||||
if (arr[i].test(uri)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
function toAssume(uri, extns) {
|
||||
let i=0, x, len=uri.length - 1;
|
||||
if (uri.charCodeAt(len) === 47) {
|
||||
uri = uri.substring(0, len);
|
||||
}
|
||||
|
||||
let arr=[], tmp=`${uri}/index`;
|
||||
for (; i < extns.length; i++) {
|
||||
x = extns[i] ? `.${extns[i]}` : '';
|
||||
if (uri) arr.push(uri + x);
|
||||
arr.push(tmp + x);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
function viaCache(cache, uri, extns) {
|
||||
let i=0, data, arr=toAssume(uri, extns);
|
||||
for (; i < arr.length; i++) {
|
||||
if (data = cache[arr[i]]) return data;
|
||||
}
|
||||
}
|
||||
|
||||
function viaLocal(dir, isEtag, uri, extns) {
|
||||
let i=0, arr=toAssume(uri, extns);
|
||||
let abs, stats, name, headers;
|
||||
for (; i < arr.length; i++) {
|
||||
abs = normalize(join(dir, name=arr[i]));
|
||||
if (abs.startsWith(dir) && fs.existsSync(abs)) {
|
||||
stats = fs.statSync(abs);
|
||||
if (stats.isDirectory()) continue;
|
||||
headers = toHeaders(name, stats, isEtag);
|
||||
headers['Cache-Control'] = isEtag ? 'no-cache' : 'no-store';
|
||||
return { abs, stats, headers };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function is404(req, res) {
|
||||
return (res.statusCode=404,res.end());
|
||||
}
|
||||
|
||||
function send(req, res, file, stats, headers) {
|
||||
let code=200, tmp, opts={};
|
||||
headers = { ...headers };
|
||||
|
||||
for (let key in headers) {
|
||||
tmp = res.getHeader(key);
|
||||
if (tmp) headers[key] = tmp;
|
||||
}
|
||||
|
||||
if (tmp = res.getHeader('content-type')) {
|
||||
headers['Content-Type'] = tmp;
|
||||
}
|
||||
|
||||
if (req.headers.range) {
|
||||
code = 206;
|
||||
let [x, y] = req.headers.range.replace('bytes=', '').split('-');
|
||||
let end = opts.end = parseInt(y, 10) || stats.size - 1;
|
||||
let start = opts.start = parseInt(x, 10) || 0;
|
||||
|
||||
if (end >= stats.size) {
|
||||
end = stats.size - 1;
|
||||
}
|
||||
|
||||
if (start >= stats.size) {
|
||||
res.setHeader('Content-Range', `bytes */${stats.size}`);
|
||||
res.statusCode = 416;
|
||||
return res.end();
|
||||
}
|
||||
|
||||
headers['Content-Range'] = `bytes ${start}-${end}/${stats.size}`;
|
||||
headers['Content-Length'] = (end - start + 1);
|
||||
headers['Accept-Ranges'] = 'bytes';
|
||||
}
|
||||
|
||||
res.writeHead(code, headers);
|
||||
fs.createReadStream(file, opts).pipe(res);
|
||||
}
|
||||
|
||||
const ENCODING = {
|
||||
'.br': 'br',
|
||||
'.gz': 'gzip',
|
||||
};
|
||||
|
||||
function toHeaders(name, stats, isEtag) {
|
||||
let enc = ENCODING[name.slice(-3)];
|
||||
|
||||
let ctype = lookup(name.slice(0, enc && -3)) || '';
|
||||
if (ctype === 'text/html') ctype += ';charset=utf-8';
|
||||
|
||||
let headers = {
|
||||
'Content-Length': stats.size,
|
||||
'Content-Type': ctype,
|
||||
'Last-Modified': stats.mtime.toUTCString(),
|
||||
};
|
||||
|
||||
if (enc) headers['Content-Encoding'] = enc;
|
||||
if (isEtag) headers['ETag'] = `W/"${stats.size}-${stats.mtime.getTime()}"`;
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
module.exports = function (dir, opts={}) {
|
||||
dir = resolve(dir || '.');
|
||||
|
||||
let isNotFound = opts.onNoMatch || is404;
|
||||
let setHeaders = opts.setHeaders || noop;
|
||||
|
||||
let extensions = opts.extensions || ['html', 'htm'];
|
||||
let gzips = opts.gzip && extensions.map(x => `${x}.gz`).concat('gz');
|
||||
let brots = opts.brotli && extensions.map(x => `${x}.br`).concat('br');
|
||||
|
||||
const FILES = {};
|
||||
|
||||
let fallback = '/';
|
||||
let isEtag = !!opts.etag;
|
||||
let isSPA = !!opts.single;
|
||||
if (typeof opts.single === 'string') {
|
||||
let idx = opts.single.lastIndexOf('.');
|
||||
fallback += !!~idx ? opts.single.substring(0, idx) : opts.single;
|
||||
}
|
||||
|
||||
let ignores = [];
|
||||
if (opts.ignores !== false) {
|
||||
ignores.push(/[/]([A-Za-z\s\d~$._-]+\.\w+){1,}$/); // any extn
|
||||
if (opts.dotfiles) ignores.push(/\/\.\w/);
|
||||
else ignores.push(/\/\.well-known/);
|
||||
[].concat(opts.ignores || []).forEach(x => {
|
||||
ignores.push(new RegExp(x, 'i'));
|
||||
});
|
||||
}
|
||||
|
||||
let cc = opts.maxAge != null && `public,max-age=${opts.maxAge}`;
|
||||
if (cc && opts.immutable) cc += ',immutable';
|
||||
else if (cc && opts.maxAge === 0) cc += ',must-revalidate';
|
||||
|
||||
if (!opts.dev) {
|
||||
totalist(dir, (name, abs, stats) => {
|
||||
if (/\.well-known[\\+\/]/.test(name)) {} // keep
|
||||
else if (!opts.dotfiles && /(^\.|[\\+|\/+]\.)/.test(name)) return;
|
||||
|
||||
let headers = toHeaders(name, stats, isEtag);
|
||||
if (cc) headers['Cache-Control'] = cc;
|
||||
|
||||
FILES['/' + name.normalize().replace(/\\+/g, '/')] = { abs, stats, headers };
|
||||
});
|
||||
}
|
||||
|
||||
let lookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache.bind(0, FILES);
|
||||
|
||||
return function (req, res, next) {
|
||||
let extns = [''];
|
||||
let pathname = parse(req).pathname;
|
||||
let val = req.headers['accept-encoding'] || '';
|
||||
if (gzips && val.includes('gzip')) extns.unshift(...gzips);
|
||||
if (brots && /(br|brotli)/i.test(val)) extns.unshift(...brots);
|
||||
extns.push(...extensions); // [...br, ...gz, orig, ...exts]
|
||||
|
||||
if (pathname.indexOf('%') !== -1) {
|
||||
try { pathname = decodeURI(pathname) }
|
||||
catch (err) { /* malform uri */ }
|
||||
}
|
||||
|
||||
let data = lookup(pathname, extns) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns);
|
||||
if (!data) return next ? next() : isNotFound(req, res);
|
||||
|
||||
if (isEtag && req.headers['if-none-match'] === data.headers['ETag']) {
|
||||
res.writeHead(304);
|
||||
return res.end();
|
||||
}
|
||||
|
||||
if (gzips || brots) {
|
||||
res.setHeader('Vary', 'Accept-Encoding');
|
||||
}
|
||||
|
||||
setHeaders(res, pathname, data.stats);
|
||||
send(req, res, data.abs, data.stats, data.headers);
|
||||
};
|
||||
}
|
194
app_vue/node_modules/sirv/build.mjs
generated
vendored
Normal file
194
app_vue/node_modules/sirv/build.mjs
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
import * as fs from 'fs';
|
||||
import { join, normalize, resolve } from 'path';
|
||||
import { totalist } from 'totalist/sync';
|
||||
import { parse } from '@polka/url';
|
||||
import { lookup } from 'mrmime';
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
function isMatch(uri, arr) {
|
||||
for (let i=0; i < arr.length; i++) {
|
||||
if (arr[i].test(uri)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
function toAssume(uri, extns) {
|
||||
let i=0, x, len=uri.length - 1;
|
||||
if (uri.charCodeAt(len) === 47) {
|
||||
uri = uri.substring(0, len);
|
||||
}
|
||||
|
||||
let arr=[], tmp=`${uri}/index`;
|
||||
for (; i < extns.length; i++) {
|
||||
x = extns[i] ? `.${extns[i]}` : '';
|
||||
if (uri) arr.push(uri + x);
|
||||
arr.push(tmp + x);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
function viaCache(cache, uri, extns) {
|
||||
let i=0, data, arr=toAssume(uri, extns);
|
||||
for (; i < arr.length; i++) {
|
||||
if (data = cache[arr[i]]) return data;
|
||||
}
|
||||
}
|
||||
|
||||
function viaLocal(dir, isEtag, uri, extns) {
|
||||
let i=0, arr=toAssume(uri, extns);
|
||||
let abs, stats, name, headers;
|
||||
for (; i < arr.length; i++) {
|
||||
abs = normalize(join(dir, name=arr[i]));
|
||||
if (abs.startsWith(dir) && fs.existsSync(abs)) {
|
||||
stats = fs.statSync(abs);
|
||||
if (stats.isDirectory()) continue;
|
||||
headers = toHeaders(name, stats, isEtag);
|
||||
headers['Cache-Control'] = isEtag ? 'no-cache' : 'no-store';
|
||||
return { abs, stats, headers };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function is404(req, res) {
|
||||
return (res.statusCode=404,res.end());
|
||||
}
|
||||
|
||||
function send(req, res, file, stats, headers) {
|
||||
let code=200, tmp, opts={};
|
||||
headers = { ...headers };
|
||||
|
||||
for (let key in headers) {
|
||||
tmp = res.getHeader(key);
|
||||
if (tmp) headers[key] = tmp;
|
||||
}
|
||||
|
||||
if (tmp = res.getHeader('content-type')) {
|
||||
headers['Content-Type'] = tmp;
|
||||
}
|
||||
|
||||
if (req.headers.range) {
|
||||
code = 206;
|
||||
let [x, y] = req.headers.range.replace('bytes=', '').split('-');
|
||||
let end = opts.end = parseInt(y, 10) || stats.size - 1;
|
||||
let start = opts.start = parseInt(x, 10) || 0;
|
||||
|
||||
if (end >= stats.size) {
|
||||
end = stats.size - 1;
|
||||
}
|
||||
|
||||
if (start >= stats.size) {
|
||||
res.setHeader('Content-Range', `bytes */${stats.size}`);
|
||||
res.statusCode = 416;
|
||||
return res.end();
|
||||
}
|
||||
|
||||
headers['Content-Range'] = `bytes ${start}-${end}/${stats.size}`;
|
||||
headers['Content-Length'] = (end - start + 1);
|
||||
headers['Accept-Ranges'] = 'bytes';
|
||||
}
|
||||
|
||||
res.writeHead(code, headers);
|
||||
fs.createReadStream(file, opts).pipe(res);
|
||||
}
|
||||
|
||||
const ENCODING = {
|
||||
'.br': 'br',
|
||||
'.gz': 'gzip',
|
||||
};
|
||||
|
||||
function toHeaders(name, stats, isEtag) {
|
||||
let enc = ENCODING[name.slice(-3)];
|
||||
|
||||
let ctype = lookup(name.slice(0, enc && -3)) || '';
|
||||
if (ctype === 'text/html') ctype += ';charset=utf-8';
|
||||
|
||||
let headers = {
|
||||
'Content-Length': stats.size,
|
||||
'Content-Type': ctype,
|
||||
'Last-Modified': stats.mtime.toUTCString(),
|
||||
};
|
||||
|
||||
if (enc) headers['Content-Encoding'] = enc;
|
||||
if (isEtag) headers['ETag'] = `W/"${stats.size}-${stats.mtime.getTime()}"`;
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
export default function (dir, opts={}) {
|
||||
dir = resolve(dir || '.');
|
||||
|
||||
let isNotFound = opts.onNoMatch || is404;
|
||||
let setHeaders = opts.setHeaders || noop;
|
||||
|
||||
let extensions = opts.extensions || ['html', 'htm'];
|
||||
let gzips = opts.gzip && extensions.map(x => `${x}.gz`).concat('gz');
|
||||
let brots = opts.brotli && extensions.map(x => `${x}.br`).concat('br');
|
||||
|
||||
const FILES = {};
|
||||
|
||||
let fallback = '/';
|
||||
let isEtag = !!opts.etag;
|
||||
let isSPA = !!opts.single;
|
||||
if (typeof opts.single === 'string') {
|
||||
let idx = opts.single.lastIndexOf('.');
|
||||
fallback += !!~idx ? opts.single.substring(0, idx) : opts.single;
|
||||
}
|
||||
|
||||
let ignores = [];
|
||||
if (opts.ignores !== false) {
|
||||
ignores.push(/[/]([A-Za-z\s\d~$._-]+\.\w+){1,}$/); // any extn
|
||||
if (opts.dotfiles) ignores.push(/\/\.\w/);
|
||||
else ignores.push(/\/\.well-known/);
|
||||
[].concat(opts.ignores || []).forEach(x => {
|
||||
ignores.push(new RegExp(x, 'i'));
|
||||
});
|
||||
}
|
||||
|
||||
let cc = opts.maxAge != null && `public,max-age=${opts.maxAge}`;
|
||||
if (cc && opts.immutable) cc += ',immutable';
|
||||
else if (cc && opts.maxAge === 0) cc += ',must-revalidate';
|
||||
|
||||
if (!opts.dev) {
|
||||
totalist(dir, (name, abs, stats) => {
|
||||
if (/\.well-known[\\+\/]/.test(name)) {} // keep
|
||||
else if (!opts.dotfiles && /(^\.|[\\+|\/+]\.)/.test(name)) return;
|
||||
|
||||
let headers = toHeaders(name, stats, isEtag);
|
||||
if (cc) headers['Cache-Control'] = cc;
|
||||
|
||||
FILES['/' + name.normalize().replace(/\\+/g, '/')] = { abs, stats, headers };
|
||||
});
|
||||
}
|
||||
|
||||
let lookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache.bind(0, FILES);
|
||||
|
||||
return function (req, res, next) {
|
||||
let extns = [''];
|
||||
let pathname = parse(req).pathname;
|
||||
let val = req.headers['accept-encoding'] || '';
|
||||
if (gzips && val.includes('gzip')) extns.unshift(...gzips);
|
||||
if (brots && /(br|brotli)/i.test(val)) extns.unshift(...brots);
|
||||
extns.push(...extensions); // [...br, ...gz, orig, ...exts]
|
||||
|
||||
if (pathname.indexOf('%') !== -1) {
|
||||
try { pathname = decodeURI(pathname) }
|
||||
catch (err) { /* malform uri */ }
|
||||
}
|
||||
|
||||
let data = lookup(pathname, extns) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns);
|
||||
if (!data) return next ? next() : isNotFound(req, res);
|
||||
|
||||
if (isEtag && req.headers['if-none-match'] === data.headers['ETag']) {
|
||||
res.writeHead(304);
|
||||
return res.end();
|
||||
}
|
||||
|
||||
if (gzips || brots) {
|
||||
res.setHeader('Vary', 'Accept-Encoding');
|
||||
}
|
||||
|
||||
setHeaders(res, pathname, data.stats);
|
||||
send(req, res, data.abs, data.stats, data.headers);
|
||||
};
|
||||
}
|
27
app_vue/node_modules/sirv/package.json
generated
vendored
Normal file
27
app_vue/node_modules/sirv/package.json
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "sirv",
|
||||
"version": "2.0.4",
|
||||
"description": "The optimized & lightweight middleware for serving requests to static assets",
|
||||
"repository": "lukeed/sirv",
|
||||
"module": "build.mjs",
|
||||
"types": "sirv.d.ts",
|
||||
"main": "build.js",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"build.*",
|
||||
"sirv.d.ts"
|
||||
],
|
||||
"author": {
|
||||
"name": "Luke Edwards",
|
||||
"email": "luke@lukeed.com",
|
||||
"url": "https://lukeed.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polka/url": "^1.0.0-next.24",
|
||||
"mrmime": "^2.0.0",
|
||||
"totalist": "^3.0.0"
|
||||
}
|
||||
}
|
238
app_vue/node_modules/sirv/readme.md
generated
vendored
Normal file
238
app_vue/node_modules/sirv/readme.md
generated
vendored
Normal file
@ -0,0 +1,238 @@
|
||||
# sirv 
|
||||
|
||||
> The optimized and lightweight middleware for serving requests to static assets
|
||||
|
||||
You may use `sirv` as a *very* fast and lightweight alternative to [`serve-static`](https://www.npmjs.com/package/serve-static).
|
||||
|
||||
The massive performance advantage over `serve-static` is explained by **not** relying on the file system for existence checks on every request. These are expensive interactions and must be avoided whenever possible! Instead, when not in "dev" mode, `sirv` performs all its file-system operations upfront and then relies on its cache for future operations.
|
||||
|
||||
This middleware will work out of the box for [Polka](https://github.com/lukeed/polka), Express, and other Express-like frameworks. It will also work with the native `http`, `https` and `http2` modules. It requires _very_ little effort to modify/wrap it for servers that don't accept the `(req, res, next)` signature.
|
||||
|
||||
:bulb: For a feature-complete CLI application, check out the sibling [`sirv-cli`](https://github.com/lukeed/sirv/tree/master/packages/sirv-cli) package as an alternative to [`zeit/serve`](https://github.com/zeit/serve)~!
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save sirv
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const sirv = require('sirv');
|
||||
const polka = require('polka');
|
||||
const compress = require('compression')();
|
||||
|
||||
// Init `sirv` handler
|
||||
const assets = sirv('public', {
|
||||
maxAge: 31536000, // 1Y
|
||||
immutable: true
|
||||
});
|
||||
|
||||
polka()
|
||||
.use(compress, assets)
|
||||
.use('/api', require('./api'))
|
||||
.listen(3000, err => {
|
||||
if (err) throw err;
|
||||
console.log('> Ready on localhost:3000~!');
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### sirv(dir, opts={})
|
||||
|
||||
Returns: `Function`
|
||||
|
||||
The returned function is a middleware in the standard Express-like signature: `(req, res, next)`, where `req` is the [`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage), `res` is the [`http.ServerResponse`](https://nodejs.org/dist/latest-v9.x/docs/api/http.html#http_class_http_serverresponse), and `next` (in this case) is the function to call if no file was found for the given path.
|
||||
|
||||
When defined, a `next()` callback is always called _instead of_ the [`opts.onNoMatch`](#optsonnomatch) callback. However, unlike `onNoMatch`, your `next()` is given no arguments.
|
||||
|
||||
#### dir
|
||||
Type: `String`<br>
|
||||
Default: `.`
|
||||
|
||||
The directory from which to read and serve assets. It is resolved to an absolute path — you must provide an absolute path yourself if `process.cwd()` is not the correct assumption.
|
||||
|
||||
#### opts.dev
|
||||
Type: `Boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Enable "dev" mode, which disables/skips caching. Instead, `sirv` will traverse the file system ***on every request***.
|
||||
|
||||
Additionally, `dev` mode will ignore `maxAge` and `immutable` as these options generate a production-oriented `Cache-Control` header value.
|
||||
|
||||
> **Important:** Do not use `dev` mode in production!
|
||||
|
||||
#### opts.etag
|
||||
Type: `Boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Generate and attach an `ETag` header to responses.
|
||||
|
||||
> **Note:** If an incoming request's [`If-None-Match` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) matches the `ETag` value, a `304` response is given.
|
||||
|
||||
#### opts.dotfiles
|
||||
Type: `Boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Allow requests to dotfiles (files or directories beginning with a `.`).
|
||||
|
||||
> **Note:** Requests to [`/.well-known/*`](https://tools.ietf.org/html/rfc8615) are always allowed.
|
||||
|
||||
#### opts.extensions
|
||||
Type: `Array<String>`<br>
|
||||
Default: `['html', 'htm']`
|
||||
|
||||
The file extension fallbacks to check for if a pathame is not initially found. For example, if a `/login` request cannot find a `login` filename, it will then look for `login.html` and `login.htm` before giving up~!
|
||||
|
||||
> **Important:** Actually, `sirv` will **also** look for `login/index.html` and `login/index.htm` before giving up.
|
||||
|
||||
#### opts.gzip
|
||||
Type: `Boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Determine if `sirv` look for **precompiled** `*.gz` files.<br>
|
||||
Must be enabled _and_ the incoming request's [`Accept Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) must include "gzip" in order for `sirv` to search for the gzip'd alternative.
|
||||
|
||||
> **Note:** The `.gz` assumption also applies to the `opts.extensions` list.
|
||||
|
||||
```js
|
||||
// NOTE: PSEUDO CODE
|
||||
// Showing lookup logic
|
||||
|
||||
// Request: [Accept-Encoding: gzip] "/foobar.jpg"
|
||||
lookup([
|
||||
'/foobar.jpg.gz', '/foobar.jpg',
|
||||
'/foobar.jpg.html.gz', '/foobar.jpg/index.html.gz',
|
||||
'/foobar.jpg.htm.gz', '/foobar.jpg/index.htm.gz',
|
||||
'/foobar.jpg.html', '/foobar.jpg/index.html',
|
||||
'/foobar.jpg.htm', '/foobar.jpg/index.htm',
|
||||
]);
|
||||
|
||||
// Request: [Accept-Encoding: gzip] "/"
|
||||
lookup([
|
||||
'/index.html.gz',
|
||||
'/index.htm.gz',
|
||||
'/index.html',
|
||||
'/index.htm',
|
||||
]);
|
||||
```
|
||||
|
||||
|
||||
#### opts.brotli
|
||||
Type: `Boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Determine if `sirv` look for **precompiled** `*.br` files.<br>
|
||||
Must be enabled _and_ the incoming request's [`Accept Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) must include either "br" or "brotli" in order for `sirv` to search for the brotli-compressed alternative.
|
||||
|
||||
> **Note:** The `.br` assumption also applies to the `opts.extensions` list.
|
||||
|
||||
When both `opts.broli` and `opts.gzip` are enabled — and all conditions are equal — then the brotli variant always takes priority.
|
||||
|
||||
```js
|
||||
// NOTE: PSEUDO CODE
|
||||
// Showing lookup logic
|
||||
|
||||
// Request: [Accept-Encoding: br] "/foobar.jpg"
|
||||
lookup([
|
||||
'/foobar.jpg.br', '/foobar.jpg',
|
||||
'/foobar.jpg.html.br', '/foobar.jpg/index.html.br',
|
||||
'/foobar.jpg.htm.br', '/foobar.jpg/index.htm.br',
|
||||
'/foobar.jpg.html', '/foobar.jpg/index.html',
|
||||
'/foobar.jpg.htm', '/foobar.jpg/index.htm',
|
||||
]);
|
||||
|
||||
// Request: [Accept-Encoding: br,gz] "/"
|
||||
lookup([
|
||||
'/index.html.br'
|
||||
'/index.htm.br'
|
||||
'/index.html.gz'
|
||||
'/index.htm.gz'
|
||||
'/index.html'
|
||||
'/index.htm'
|
||||
]);
|
||||
```
|
||||
|
||||
#### opts.maxAge
|
||||
Type: `Number`<br>
|
||||
Default: `undefined`
|
||||
|
||||
Enables the `Cache-Control` header on responses and sets the `max-age` value (in seconds).<br>
|
||||
For example, `maxAge: 31536000` is equivalent to one year.
|
||||
|
||||
#### opts.immutable
|
||||
Type: `Boolean`<br>
|
||||
Default: `false`
|
||||
|
||||
Appends the [`immutable` directive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Revalidation_and_reloading) on your `Cache-Control` header, used for uniquely-named assets that will not change!
|
||||
|
||||
> **Important:** Will only work if `opts.maxAge` has a value defined!
|
||||
|
||||
#### opts.single
|
||||
Type: `Boolean` or `String`<br>
|
||||
Default: `false`
|
||||
|
||||
Treat the directory as a single-page application.
|
||||
|
||||
When `true`, the directory's index page (default `index.html`) will be sent if the request asset does not exist.<br>
|
||||
You may pass a `string` value to use a file _instead of_ `index.html` as your fallback.
|
||||
|
||||
For example, if "/about" is requested but no variants of that file exist, then the response for "/" is sent instead:
|
||||
|
||||
```js
|
||||
// Note: This is psuedo code to illustrate what's happening
|
||||
|
||||
// Request: "/about"
|
||||
let file = find(['/about', '/about.html', '/about.htm', '/about/index.html', '/about.htm']);
|
||||
if (file) {
|
||||
send(file);
|
||||
} else if (opts.single === true) {
|
||||
file = find(['/', '/index.html', '/index.htm']);
|
||||
send(file);
|
||||
} else if (typeof opts.single === 'string') {
|
||||
file = find([opts.single]);
|
||||
send(file);
|
||||
} else {
|
||||
// next() or 404
|
||||
}
|
||||
```
|
||||
|
||||
#### opts.ignores
|
||||
Type: `false` or `Array<String | RegExp>`
|
||||
|
||||
Specify paths/patterns that should ignore the fallback behavior that `opts.single` provides.
|
||||
|
||||
By default, any asset-like path (URLs that end with an extension) will be ignored. This means that, for example, if `/foobar.jpg` is not found, a `404` response is sent instead of the `index.html` fallback.
|
||||
|
||||
Additionally, any `/.well-known/*` pathname ignores the fallback – as do all other dotfile requests when `opts.dotfiles` is enabled.
|
||||
|
||||
Any string value(s) will be passed through `new RegExp(value, 'i')` directly.
|
||||
|
||||
Finally, you may set `ignores: false` to disable ***all*** ignores, including the defaults. Put differently, this will fallback ***all*** unknown pathnames to your `index.html` (or custom `opts.single` value).
|
||||
|
||||
> **Important:** Only has an effect if `opts.single` is enabled.
|
||||
|
||||
#### opts.onNoMatch
|
||||
Type: `Function`
|
||||
|
||||
A custom function to run if a file cannot be found for a given request. <br>By default, `sirv` will send a basic `(404) Not found` response.
|
||||
|
||||
The function receives the current `req <IncomingMessage>, res <ServerResponse>` pair for as its two arguments.
|
||||
|
||||
> **Note:** This won't run if a `next` callback has been provided to the middleware; see [`sirv`](#sirvdir-opts) description.
|
||||
|
||||
#### opts.setHeaders
|
||||
Type: `Function`
|
||||
|
||||
A custom function to append or change any headers on the outgoing response. There is no default.
|
||||
|
||||
Its signature is `(res, pathname, stats)`, where `res` is the `ServerResponse`, `pathname` is incoming request path (stripped of queries), and `stats` is the file's result from [`fs.statSync`](https://nodejs.org/api/fs.html#fs_fs_statsync_path).
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Luke Edwards](https://lukeed.com)
|
25
app_vue/node_modules/sirv/sirv.d.ts
generated
vendored
Normal file
25
app_vue/node_modules/sirv/sirv.d.ts
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
declare module 'sirv' {
|
||||
import type { Stats } from 'fs';
|
||||
import type { IncomingMessage, ServerResponse } from 'http';
|
||||
|
||||
type Arrayable<T> = T | T[];
|
||||
export type NextHandler = () => void | Promise<void>;
|
||||
export type RequestHandler = (req: IncomingMessage, res: ServerResponse, next?: NextHandler) => void;
|
||||
|
||||
export interface Options {
|
||||
dev?: boolean;
|
||||
etag?: boolean;
|
||||
maxAge?: number;
|
||||
immutable?: boolean;
|
||||
single?: string | boolean;
|
||||
ignores?: false | Arrayable<string | RegExp>;
|
||||
extensions?: string[];
|
||||
dotfiles?: boolean;
|
||||
brotli?: boolean;
|
||||
gzip?: boolean;
|
||||
onNoMatch?: (req: IncomingMessage, res: ServerResponse) => void;
|
||||
setHeaders?: (res: ServerResponse, pathname: string, stats: Stats) => void;
|
||||
}
|
||||
|
||||
export default function(dir?: string, opts?: Options): RequestHandler;
|
||||
}
|
Reference in New Issue
Block a user