flowingts 0.0.0 → 0.19.0
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/LICENSE +15 -0
- package/README.md +74 -3
- package/dist/core/abort.d.ts +23 -0
- package/dist/core/abort.d.ts.map +1 -0
- package/dist/core/abort.js +23 -0
- package/dist/core/abort.js.map +1 -0
- package/dist/core/app/core.d.ts +35 -0
- package/dist/core/app/core.d.ts.map +1 -0
- package/dist/core/app/core.js +2 -0
- package/dist/core/app/core.js.map +1 -0
- package/dist/core/app/options.d.ts +178 -0
- package/dist/core/app/options.d.ts.map +1 -0
- package/dist/core/app/options.js +2 -0
- package/dist/core/app/options.js.map +1 -0
- package/dist/core/app.d.ts +143 -0
- package/dist/core/app.d.ts.map +1 -0
- package/dist/core/app.js +283 -0
- package/dist/core/app.js.map +1 -0
- package/dist/core/body-parser.d.ts +14 -0
- package/dist/core/body-parser.d.ts.map +1 -0
- package/dist/core/body-parser.js +76 -0
- package/dist/core/body-parser.js.map +1 -0
- package/dist/core/compiler.d.ts +104 -0
- package/dist/core/compiler.d.ts.map +1 -0
- package/dist/core/compiler.js +151 -0
- package/dist/core/compiler.js.map +1 -0
- package/dist/core/compose.d.ts +16 -0
- package/dist/core/compose.d.ts.map +1 -0
- package/dist/core/compose.js +41 -0
- package/dist/core/compose.js.map +1 -0
- package/dist/core/context.d.ts +290 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +460 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/contracts.d.ts +76 -0
- package/dist/core/contracts.d.ts.map +1 -0
- package/dist/core/contracts.js +87 -0
- package/dist/core/contracts.js.map +1 -0
- package/dist/core/errors.d.ts +50 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +25 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/guard.d.ts +10 -0
- package/dist/core/guard.d.ts.map +1 -0
- package/dist/core/guard.js +14 -0
- package/dist/core/guard.js.map +1 -0
- package/dist/core/health.d.ts +37 -0
- package/dist/core/health.d.ts.map +1 -0
- package/dist/core/health.js +68 -0
- package/dist/core/health.js.map +1 -0
- package/dist/core/hooks.d.ts +34 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +27 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/index.d.ts +30 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/infer.d.ts +68 -0
- package/dist/core/infer.d.ts.map +1 -0
- package/dist/core/infer.js +2 -0
- package/dist/core/infer.js.map +1 -0
- package/dist/core/inject.d.ts +27 -0
- package/dist/core/inject.d.ts.map +1 -0
- package/dist/core/inject.js +85 -0
- package/dist/core/inject.js.map +1 -0
- package/dist/core/logger.d.ts +57 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +134 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/metadata.d.ts +83 -0
- package/dist/core/metadata.d.ts.map +1 -0
- package/dist/core/metadata.js +91 -0
- package/dist/core/metadata.js.map +1 -0
- package/dist/core/mounted-group.d.ts +77 -0
- package/dist/core/mounted-group.d.ts.map +1 -0
- package/dist/core/mounted-group.js +131 -0
- package/dist/core/mounted-group.js.map +1 -0
- package/dist/core/registry/framework-routes.d.ts +28 -0
- package/dist/core/registry/framework-routes.d.ts.map +1 -0
- package/dist/core/registry/framework-routes.js +83 -0
- package/dist/core/registry/framework-routes.js.map +1 -0
- package/dist/core/registry/registry.d.ts +58 -0
- package/dist/core/registry/registry.d.ts.map +1 -0
- package/dist/core/registry/registry.js +208 -0
- package/dist/core/registry/registry.js.map +1 -0
- package/dist/core/registry/route-program.d.ts +16 -0
- package/dist/core/registry/route-program.d.ts.map +1 -0
- package/dist/core/registry/route-program.js +62 -0
- package/dist/core/registry/route-program.js.map +1 -0
- package/dist/core/request-validation.d.ts +15 -0
- package/dist/core/request-validation.d.ts.map +1 -0
- package/dist/core/request-validation.js +67 -0
- package/dist/core/request-validation.js.map +1 -0
- package/dist/core/response/pipeline.d.ts +51 -0
- package/dist/core/response/pipeline.d.ts.map +1 -0
- package/dist/core/response/pipeline.js +169 -0
- package/dist/core/response/pipeline.js.map +1 -0
- package/dist/core/route-table.d.ts +58 -0
- package/dist/core/route-table.d.ts.map +1 -0
- package/dist/core/route-table.js +108 -0
- package/dist/core/route-table.js.map +1 -0
- package/dist/core/runtime/observer.d.ts +47 -0
- package/dist/core/runtime/observer.d.ts.map +1 -0
- package/dist/core/runtime/observer.js +125 -0
- package/dist/core/runtime/observer.js.map +1 -0
- package/dist/core/runtime/request-handler.d.ts +62 -0
- package/dist/core/runtime/request-handler.d.ts.map +1 -0
- package/dist/core/runtime/request-handler.js +256 -0
- package/dist/core/runtime/request-handler.js.map +1 -0
- package/dist/core/runtime/server.d.ts +59 -0
- package/dist/core/runtime/server.d.ts.map +1 -0
- package/dist/core/runtime/server.js +180 -0
- package/dist/core/runtime/server.js.map +1 -0
- package/dist/core/shutdown.d.ts +41 -0
- package/dist/core/shutdown.d.ts.map +1 -0
- package/dist/core/shutdown.js +53 -0
- package/dist/core/shutdown.js.map +1 -0
- package/dist/core/streaming/sse.d.ts +35 -0
- package/dist/core/streaming/sse.d.ts.map +1 -0
- package/dist/core/streaming/sse.js +121 -0
- package/dist/core/streaming/sse.js.map +1 -0
- package/dist/core/symbols.d.ts +28 -0
- package/dist/core/symbols.d.ts.map +1 -0
- package/dist/core/symbols.js +28 -0
- package/dist/core/symbols.js.map +1 -0
- package/dist/core/telemetry.d.ts +83 -0
- package/dist/core/telemetry.d.ts.map +1 -0
- package/dist/core/telemetry.js +96 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/uploads/receive.d.ts +63 -0
- package/dist/core/uploads/receive.d.ts.map +1 -0
- package/dist/core/uploads/receive.js +342 -0
- package/dist/core/uploads/receive.js.map +1 -0
- package/dist/core/uploads/types.d.ts +79 -0
- package/dist/core/uploads/types.d.ts.map +1 -0
- package/dist/core/uploads/types.js +2 -0
- package/dist/core/uploads/types.js.map +1 -0
- package/dist/decorators/hooks.d.ts +25 -0
- package/dist/decorators/hooks.d.ts.map +1 -0
- package/dist/decorators/hooks.js +36 -0
- package/dist/decorators/hooks.js.map +1 -0
- package/dist/decorators/http.d.ts +21 -0
- package/dist/decorators/http.d.ts.map +1 -0
- package/dist/decorators/http.js +21 -0
- package/dist/decorators/http.js.map +1 -0
- package/dist/decorators/index.d.ts +7 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +7 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/log.d.ts +10 -0
- package/dist/decorators/log.d.ts.map +1 -0
- package/dist/decorators/log.js +32 -0
- package/dist/decorators/log.js.map +1 -0
- package/dist/decorators/middlewares.d.ts +28 -0
- package/dist/decorators/middlewares.d.ts.map +1 -0
- package/dist/decorators/middlewares.js +40 -0
- package/dist/decorators/middlewares.js.map +1 -0
- package/dist/decorators/router.d.ts +12 -0
- package/dist/decorators/router.d.ts.map +1 -0
- package/dist/decorators/router.js +20 -0
- package/dist/decorators/router.js.map +1 -0
- package/dist/decorators/schema.d.ts +8 -0
- package/dist/decorators/schema.d.ts.map +1 -0
- package/dist/decorators/schema.js +14 -0
- package/dist/decorators/schema.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/middlewares/auth.d.ts +41 -0
- package/dist/middlewares/auth.d.ts.map +1 -0
- package/dist/middlewares/auth.js +74 -0
- package/dist/middlewares/auth.js.map +1 -0
- package/dist/middlewares/cors.d.ts +30 -0
- package/dist/middlewares/cors.d.ts.map +1 -0
- package/dist/middlewares/cors.js +69 -0
- package/dist/middlewares/cors.js.map +1 -0
- package/dist/middlewares/csrf.d.ts +42 -0
- package/dist/middlewares/csrf.d.ts.map +1 -0
- package/dist/middlewares/csrf.js +70 -0
- package/dist/middlewares/csrf.js.map +1 -0
- package/dist/middlewares/index.d.ts +6 -0
- package/dist/middlewares/index.d.ts.map +1 -0
- package/dist/middlewares/index.js +6 -0
- package/dist/middlewares/index.js.map +1 -0
- package/dist/middlewares/rate-limit.d.ts +35 -0
- package/dist/middlewares/rate-limit.d.ts.map +1 -0
- package/dist/middlewares/rate-limit.js +45 -0
- package/dist/middlewares/rate-limit.js.map +1 -0
- package/dist/middlewares/security-headers.d.ts +28 -0
- package/dist/middlewares/security-headers.d.ts.map +1 -0
- package/dist/middlewares/security-headers.js +42 -0
- package/dist/middlewares/security-headers.js.map +1 -0
- package/dist/openapi/generate.d.ts +51 -0
- package/dist/openapi/generate.d.ts.map +1 -0
- package/dist/openapi/generate.js +175 -0
- package/dist/openapi/generate.js.map +1 -0
- package/dist/schema/serialization.d.ts +2 -0
- package/dist/schema/serialization.d.ts.map +1 -0
- package/dist/schema/serialization.js +11 -0
- package/dist/schema/serialization.js.map +1 -0
- package/dist/schema/validation.d.ts +22 -0
- package/dist/schema/validation.d.ts.map +1 -0
- package/dist/schema/validation.js +68 -0
- package/dist/schema/validation.js.map +1 -0
- package/dist/server/static.d.ts +45 -0
- package/dist/server/static.d.ts.map +1 -0
- package/dist/server/static.js +204 -0
- package/dist/server/static.js.map +1 -0
- package/dist/server/tls.d.ts +48 -0
- package/dist/server/tls.d.ts.map +1 -0
- package/dist/server/tls.js +60 -0
- package/dist/server/tls.js.map +1 -0
- package/dist/shims/symbol-metadata.d.ts +2 -0
- package/dist/shims/symbol-metadata.d.ts.map +1 -0
- package/dist/shims/symbol-metadata.js +8 -0
- package/dist/shims/symbol-metadata.js.map +1 -0
- package/dist/utils/content-type.d.ts +13 -0
- package/dist/utils/content-type.d.ts.map +1 -0
- package/dist/utils/content-type.js +75 -0
- package/dist/utils/content-type.js.map +1 -0
- package/dist/utils/cookie.d.ts +34 -0
- package/dist/utils/cookie.d.ts.map +1 -0
- package/dist/utils/cookie.js +94 -0
- package/dist/utils/cookie.js.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/mime.d.ts +2 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +52 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/origin-match.d.ts +58 -0
- package/dist/utils/origin-match.d.ts.map +1 -0
- package/dist/utils/origin-match.js +194 -0
- package/dist/utils/origin-match.js.map +1 -0
- package/dist/utils/path.d.ts +10 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +60 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/utils/query.d.ts +28 -0
- package/dist/utils/query.d.ts.map +1 -0
- package/dist/utils/query.js +67 -0
- package/dist/utils/query.js.map +1 -0
- package/dist/utils/request-target.d.ts +31 -0
- package/dist/utils/request-target.d.ts.map +1 -0
- package/dist/utils/request-target.js +80 -0
- package/dist/utils/request-target.js.map +1 -0
- package/dist/utils/safe-json.d.ts +24 -0
- package/dist/utils/safe-json.d.ts.map +1 -0
- package/dist/utils/safe-json.js +83 -0
- package/dist/utils/safe-json.js.map +1 -0
- package/dist/utils/trace-context.d.ts +17 -0
- package/dist/utils/trace-context.d.ts.map +1 -0
- package/dist/utils/trace-context.js +30 -0
- package/dist/utils/trace-context.js.map +1 -0
- package/package.json +85 -6
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { createReadStream, realpathSync, statSync } from 'node:fs';
|
|
2
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, resolve, sep } from 'node:path';
|
|
4
|
+
import { kRawSend } from '../core/symbols.js';
|
|
5
|
+
import { HttpError } from '../core/errors.js';
|
|
6
|
+
import { contentTypeFor } from '../utils/mime.js';
|
|
7
|
+
const UNITS = { s: 1, m: 60, h: 3600, d: 86_400 };
|
|
8
|
+
export function parseMaxAge(value) {
|
|
9
|
+
if (value === undefined)
|
|
10
|
+
return 0;
|
|
11
|
+
if (typeof value === 'number') {
|
|
12
|
+
if (!Number.isFinite(value) || value < 0)
|
|
13
|
+
throw new Error(`[flowing] invalid maxAge ${value}.`);
|
|
14
|
+
return Math.floor(value);
|
|
15
|
+
}
|
|
16
|
+
const m = /^(\d+)\s*([smhd])$/.exec(value.trim());
|
|
17
|
+
if (!m)
|
|
18
|
+
throw new Error(`[flowing] invalid maxAge "${value}"; use seconds or "10s", "30m", "12h", "7d".`);
|
|
19
|
+
return Number(m[1]) * UNITS[m[2]];
|
|
20
|
+
}
|
|
21
|
+
/** Raiz real (symlinks resolvidos), conferida na configuração: um diretório que não existe falha cedo. */
|
|
22
|
+
export function resolveRoot(root) {
|
|
23
|
+
let real;
|
|
24
|
+
try {
|
|
25
|
+
real = realpathSync(resolve(root));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`[flowing] static root "${root}" does not exist.`);
|
|
29
|
+
}
|
|
30
|
+
if (!statSync(real).isDirectory())
|
|
31
|
+
throw new Error(`[flowing] static root "${root}" is not a directory.`);
|
|
32
|
+
return real;
|
|
33
|
+
}
|
|
34
|
+
const notFound = () => new HttpError(404, 'Not Found', 'NOT_FOUND');
|
|
35
|
+
/**
|
|
36
|
+
* Caminho dentro da raiz, ou `undefined` se a requisição tentar sair dela (path traversal) (F-13):
|
|
37
|
+
* byte nulo, barra invertida e segmentos `..` são recusados antes de resolver, e o resultado real
|
|
38
|
+
* (depois de seguir symlinks) precisa continuar dentro da raiz.
|
|
39
|
+
*/
|
|
40
|
+
async function insideRoot(root, relative, dotfiles) {
|
|
41
|
+
if (relative.includes('\0') || relative.includes('\\'))
|
|
42
|
+
return undefined;
|
|
43
|
+
const segments = relative.split('/').filter((s) => s !== '' && s !== '.');
|
|
44
|
+
if (segments.some((s) => s === '..'))
|
|
45
|
+
return undefined;
|
|
46
|
+
if (dotfiles === 'deny' && segments.some((s) => s.startsWith('.')))
|
|
47
|
+
return undefined;
|
|
48
|
+
const candidate = resolve(root, ...segments);
|
|
49
|
+
if (candidate !== root && !candidate.startsWith(root + sep))
|
|
50
|
+
return undefined;
|
|
51
|
+
try {
|
|
52
|
+
const real = await realpath(candidate);
|
|
53
|
+
return real === root || real.startsWith(root + sep) ? real : undefined;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return candidate; // não existe: o stat responde 404 adiante
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function fileStat(path) {
|
|
60
|
+
try {
|
|
61
|
+
return await stat(path);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const etagOf = (s) => `W/"${s.size.toString(16)}-${Math.floor(s.mtimeMs).toString(16)}"`;
|
|
68
|
+
function contentDisposition(name) {
|
|
69
|
+
const ascii = name.replace(/[^\x20-\x7e]/g, '_').replace(/["\\]/g, '_');
|
|
70
|
+
return `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(name)}`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* `bytes=a-b`, `bytes=a-` ou `bytes=-n` sobre `size`. `undefined` = não satisfazível (416); `null` = ignorar
|
|
74
|
+
* e enviar o arquivo inteiro (outra unidade, vários intervalos ou sintaxe que não entendemos, RFC 9110 §14.2).
|
|
75
|
+
*/
|
|
76
|
+
function parseRange(header, size) {
|
|
77
|
+
const value = header.trim();
|
|
78
|
+
if (!/^bytes=/i.test(value) || value.includes(','))
|
|
79
|
+
return null;
|
|
80
|
+
const m = /^bytes=(\d*)-(\d*)$/i.exec(value);
|
|
81
|
+
if (!m)
|
|
82
|
+
return null;
|
|
83
|
+
const [, a, b] = m;
|
|
84
|
+
if (a === '' && b === '')
|
|
85
|
+
return undefined;
|
|
86
|
+
let start;
|
|
87
|
+
let end;
|
|
88
|
+
if (a === '') {
|
|
89
|
+
const n = Number(b);
|
|
90
|
+
if (n === 0)
|
|
91
|
+
return undefined;
|
|
92
|
+
start = Math.max(0, size - n);
|
|
93
|
+
end = size - 1;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
start = Number(a);
|
|
97
|
+
end = b === '' ? size - 1 : Math.min(Number(b), size - 1);
|
|
98
|
+
}
|
|
99
|
+
return start > end || start >= size ? undefined : { start, end };
|
|
100
|
+
}
|
|
101
|
+
/** Envia um arquivo já resolvido e conferido, com cache condicional e `Range` (F-13). */
|
|
102
|
+
export async function sendResolvedFile(ctx, path, s, opts) {
|
|
103
|
+
const res = ctx.res;
|
|
104
|
+
const type = contentTypeFor(path, opts.mimeTypes);
|
|
105
|
+
const etag = opts.etag === false ? undefined : etagOf(s);
|
|
106
|
+
const modified = opts.lastModified === false ? undefined : new Date(Math.floor(s.mtimeMs / 1000) * 1000);
|
|
107
|
+
if (etag)
|
|
108
|
+
res.setHeader('ETag', etag);
|
|
109
|
+
if (modified)
|
|
110
|
+
res.setHeader('Last-Modified', modified.toUTCString());
|
|
111
|
+
const maxAge = parseMaxAge(opts.maxAge);
|
|
112
|
+
res.setHeader('Cache-Control', opts.noCache ? 'no-cache' : `public, max-age=${maxAge}${opts.immutable ? ', immutable' : ''}`);
|
|
113
|
+
res.setHeader('Accept-Ranges', 'bytes');
|
|
114
|
+
if (opts.download) {
|
|
115
|
+
const name = typeof opts.download === 'string' ? opts.download : (path.split(sep).pop() ?? 'download');
|
|
116
|
+
res.setHeader('Content-Disposition', contentDisposition(name));
|
|
117
|
+
}
|
|
118
|
+
// Condicionais (RFC 9110): If-None-Match prevalece sobre If-Modified-Since.
|
|
119
|
+
const inm = ctx.get('if-none-match');
|
|
120
|
+
const ims = ctx.get('if-modified-since');
|
|
121
|
+
const fresh = inm
|
|
122
|
+
? etag !== undefined && inm.split(',').some((t) => t.trim() === '*' || t.trim().replace(/^W\//, '') === etag.replace(/^W\//, ''))
|
|
123
|
+
: ims !== undefined && modified !== undefined && !Number.isNaN(Date.parse(ims)) && modified.getTime() <= Date.parse(ims);
|
|
124
|
+
if (fresh) {
|
|
125
|
+
res.statusCode = 304;
|
|
126
|
+
res.removeHeader('Content-Type');
|
|
127
|
+
return void res.end();
|
|
128
|
+
}
|
|
129
|
+
let start = 0;
|
|
130
|
+
let end = s.size - 1;
|
|
131
|
+
const rangeHeader = ctx.get('range');
|
|
132
|
+
const ifRange = ctx.get('if-range');
|
|
133
|
+
// Range só vale para GET. If-Range exige comparação forte: nossos ETags são fracos e nunca a satisfazem;
|
|
134
|
+
// uma data precisa ser exatamente o Last-Modified (RFC 9110 §13.1.5).
|
|
135
|
+
const ifRangeOk = !ifRange ||
|
|
136
|
+
(!ifRange.startsWith('"') && !ifRange.startsWith('W/') && modified !== undefined && Date.parse(ifRange) === modified.getTime());
|
|
137
|
+
const rangeApplies = ctx.method === 'GET' && rangeHeader !== undefined && ifRangeOk;
|
|
138
|
+
if (rangeApplies && s.size > 0) {
|
|
139
|
+
const range = parseRange(rangeHeader, s.size);
|
|
140
|
+
if (range === undefined) {
|
|
141
|
+
res.statusCode = 416;
|
|
142
|
+
res.setHeader('Content-Range', `bytes */${s.size}`);
|
|
143
|
+
return void res.end();
|
|
144
|
+
}
|
|
145
|
+
if (range) {
|
|
146
|
+
({ start, end } = range);
|
|
147
|
+
res.statusCode = 206;
|
|
148
|
+
res.setHeader('Content-Range', `bytes ${start}-${end}/${s.size}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
res.setHeader('Content-Length', String(s.size === 0 ? 0 : end - start + 1));
|
|
152
|
+
if (ctx.method === 'HEAD' || s.size === 0) {
|
|
153
|
+
res.setHeader('Content-Type', type);
|
|
154
|
+
return void res.end();
|
|
155
|
+
}
|
|
156
|
+
ctx[kRawSend](createReadStream(path, { start, end }), type);
|
|
157
|
+
}
|
|
158
|
+
/** `ctx.sendFile()`: confere o caminho e envia (F-13). */
|
|
159
|
+
export async function sendFile(ctx, path, opts = {}) {
|
|
160
|
+
// Como `ctx.json()`/`ctx.send()`: depois que a resposta saiu, um novo envio é ignorado (sem mexer nos headers).
|
|
161
|
+
if (ctx.sent)
|
|
162
|
+
return;
|
|
163
|
+
let full;
|
|
164
|
+
if (opts.root !== undefined) {
|
|
165
|
+
full = await insideRoot(resolveRoot(opts.root), path, 'deny');
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
if (!isAbsolute(path))
|
|
169
|
+
throw new Error('[flowing] ctx.sendFile(): use an absolute path, or pass { root } with a relative one.');
|
|
170
|
+
full = path;
|
|
171
|
+
}
|
|
172
|
+
const s = full ? await fileStat(full) : undefined;
|
|
173
|
+
if (!full || !s?.isFile())
|
|
174
|
+
throw notFound();
|
|
175
|
+
await sendResolvedFile(ctx, full, s, opts);
|
|
176
|
+
}
|
|
177
|
+
/** Handler de `app.static()`: resolve o resto do path dentro da raiz, com índice e fallback de SPA. */
|
|
178
|
+
export function staticHandler(rootInput, opts) {
|
|
179
|
+
const root = resolveRoot(rootInput);
|
|
180
|
+
parseMaxAge(opts.maxAge); // valida já
|
|
181
|
+
const dotfiles = opts.dotfiles ?? 'deny';
|
|
182
|
+
const index = opts.index === undefined ? 'index.html' : opts.index;
|
|
183
|
+
return async (ctx) => {
|
|
184
|
+
const rest = ctx.params['*'] ?? '';
|
|
185
|
+
let full = await insideRoot(root, rest, dotfiles);
|
|
186
|
+
let s = full ? await fileStat(full) : undefined;
|
|
187
|
+
if (full && s?.isDirectory()) {
|
|
188
|
+
full = index ? await insideRoot(root, `${rest}/${index}`, dotfiles) : undefined;
|
|
189
|
+
s = full ? await fileStat(full) : undefined;
|
|
190
|
+
}
|
|
191
|
+
if (full && s?.isFile())
|
|
192
|
+
return sendResolvedFile(ctx, full, s, opts);
|
|
193
|
+
// SPA: só para paths sem extensão, para um asset que falta continuar 404.
|
|
194
|
+
const last = rest.split('/').pop() ?? '';
|
|
195
|
+
if (opts.fallback && full !== undefined && !last.includes('.')) {
|
|
196
|
+
const fb = await insideRoot(root, opts.fallback, 'allow');
|
|
197
|
+
const fs = fb ? await fileStat(fb) : undefined;
|
|
198
|
+
if (fb && fs?.isFile())
|
|
199
|
+
return sendResolvedFile(ctx, fb, fs, { ...opts, noCache: true });
|
|
200
|
+
}
|
|
201
|
+
throw notFound();
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/server/static.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { SecureContext, SecureContextOptions } from 'node:tls';
|
|
2
|
+
/** Material de um certificado: PEM (`key` + `cert`) ou PKCS#12 (`pfx`). */
|
|
3
|
+
export interface TlsCertificate {
|
|
4
|
+
key?: string | Buffer | (string | Buffer)[];
|
|
5
|
+
cert?: string | Buffer | (string | Buffer)[];
|
|
6
|
+
pfx?: string | Buffer;
|
|
7
|
+
/** Senha da chave ou do `pfx`. */
|
|
8
|
+
passphrase?: string;
|
|
9
|
+
/** CAs intermediárias, se não estiverem no `cert` (fullchain). */
|
|
10
|
+
ca?: string | Buffer | (string | Buffer)[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* HTTPS no `app.listen({ tls })`. TLS 1.2 é o mínimo; SSLv3, TLS 1.0 e 1.1 não são aceitos.
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* await app.listen({ port: 443, host: '0.0.0.0', tls: { key, cert } });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export interface TlsOptions extends TlsCertificate {
|
|
20
|
+
/** Padrão: `'TLSv1.2'`. */
|
|
21
|
+
minVersion?: 'TLSv1.2' | 'TLSv1.3';
|
|
22
|
+
/**
|
|
23
|
+
* Certificados por domínio (SNI), escolhidos no handshake: `{ 'api.exemplo.com': { key, cert } }`.
|
|
24
|
+
* `'*.exemplo.dev'` vale para um nível de subdomínio, como no próprio certificado. Um domínio sem
|
|
25
|
+
* entrada usa o certificado principal (`key`/`cert`/`pfx`); sem ele, o handshake é recusado.
|
|
26
|
+
*/
|
|
27
|
+
sni?: Record<string, TlsCertificate>;
|
|
28
|
+
}
|
|
29
|
+
/** O que o servidor HTTPS precisa: opções do certificado principal e o `SNICallback`. */
|
|
30
|
+
export interface CompiledTls {
|
|
31
|
+
options: SecureContextOptions & {
|
|
32
|
+
SNICallback?: (servername: string, cb: (err: Error | null, ctx?: SecureContext) => void) => void;
|
|
33
|
+
};
|
|
34
|
+
/** Contexto do certificado principal, para `setSecureContext()` na troca. */
|
|
35
|
+
main: SecureContextOptions | undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Valida a configuração e cria os contextos (os certificados são lidos e conferidos aqui, então um PEM
|
|
39
|
+
* inválido falha no `listen()`, e não no primeiro cliente).
|
|
40
|
+
*/
|
|
41
|
+
export declare function compileTls(tls: TlsOptions, lookup?: {
|
|
42
|
+
current: SniTable;
|
|
43
|
+
}): CompiledTls;
|
|
44
|
+
/** Tabela de contextos por domínio: igualdade exata primeiro, depois o curinga de um nível. */
|
|
45
|
+
export interface SniTable {
|
|
46
|
+
find(servername: string): SecureContext | undefined;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=tls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls.d.ts","sourceRoot":"","sources":["../../src/server/tls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGpE,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5C,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC7C,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC5C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,2BAA2B;IAC3B,UAAU,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACnC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACtC;AAUD,yFAAyF;AACzF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,oBAAoB,GAAG;QAAE,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,aAAa,KAAK,IAAI,KAAK,IAAI,CAAA;KAAE,CAAC;IACrI,6EAA6E;IAC7E,IAAI,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACxC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE;IAAE,OAAO,EAAE,QAAQ,CAAA;CAAE,GAAG,WAAW,CAkBvF;AAED,+FAA+F;AAC/F,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;CACrD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createSecureContext } from 'node:tls';
|
|
2
|
+
const ALLOWED_MIN = new Set(['TLSv1.2', 'TLSv1.3']);
|
|
3
|
+
function contextOptions(cert, minVersion) {
|
|
4
|
+
return { ...cert, minVersion: minVersion };
|
|
5
|
+
}
|
|
6
|
+
const hasCert = (c) => (c.key !== undefined && c.cert !== undefined) || c.pfx !== undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Valida a configuração e cria os contextos (os certificados são lidos e conferidos aqui, então um PEM
|
|
9
|
+
* inválido falha no `listen()`, e não no primeiro cliente).
|
|
10
|
+
*/
|
|
11
|
+
export function compileTls(tls, lookup) {
|
|
12
|
+
const minVersion = tls.minVersion ?? 'TLSv1.2';
|
|
13
|
+
if (!ALLOWED_MIN.has(minVersion)) {
|
|
14
|
+
throw new Error(`[flowing] tls.minVersion must be 'TLSv1.2' or 'TLSv1.3' (got '${minVersion}').`);
|
|
15
|
+
}
|
|
16
|
+
const { sni, minVersion: _m, ...mainCert } = tls;
|
|
17
|
+
const main = hasCert(mainCert) ? contextOptions(mainCert, minVersion) : undefined;
|
|
18
|
+
if (!main && !sni)
|
|
19
|
+
throw new Error('[flowing] tls needs a certificate: { key, cert }, { pfx } or { sni }.');
|
|
20
|
+
if (main)
|
|
21
|
+
createSecureContext(main); // valida já
|
|
22
|
+
const table = buildSniTable(sni ?? {}, minVersion);
|
|
23
|
+
if (lookup)
|
|
24
|
+
lookup.current = table;
|
|
25
|
+
const options = { ...(main ?? { minVersion: minVersion }) };
|
|
26
|
+
// Sempre instalado: assim um `reloadTLS()` com `sni` funciona mesmo que o `listen()` não tivesse `sni`.
|
|
27
|
+
// Sem entrada para o domínio, devolve `undefined` e vale o certificado principal.
|
|
28
|
+
const ref = lookup ?? { current: table };
|
|
29
|
+
options.SNICallback = (servername, cb) => cb(null, ref.current.find(servername));
|
|
30
|
+
return { options, main };
|
|
31
|
+
}
|
|
32
|
+
function buildSniTable(entries, minVersion) {
|
|
33
|
+
const exact = new Map();
|
|
34
|
+
const wildcard = new Map();
|
|
35
|
+
for (const [rawName, cert] of Object.entries(entries)) {
|
|
36
|
+
const name = rawName.toLowerCase();
|
|
37
|
+
if (!hasCert(cert))
|
|
38
|
+
throw new Error(`[flowing] tls.sni["${rawName}"] needs { key, cert } or { pfx }.`);
|
|
39
|
+
const valid = /^(\*\.)?([a-z0-9-]+\.)*[a-z0-9-]+$/.test(name);
|
|
40
|
+
if (!valid)
|
|
41
|
+
throw new Error(`[flowing] tls.sni: invalid domain "${rawName}"; use "api.exemplo.com" or "*.exemplo.dev".`);
|
|
42
|
+
const ctx = createSecureContext(contextOptions(cert, minVersion));
|
|
43
|
+
if (name.startsWith('*.'))
|
|
44
|
+
wildcard.set(name.slice(2), ctx);
|
|
45
|
+
else
|
|
46
|
+
exact.set(name, ctx);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
find(servername) {
|
|
50
|
+
const name = servername.toLowerCase().replace(/\.$/, '');
|
|
51
|
+
const hit = exact.get(name);
|
|
52
|
+
if (hit)
|
|
53
|
+
return hit;
|
|
54
|
+
const dot = name.indexOf('.');
|
|
55
|
+
// `*.exemplo.dev` cobre `a.exemplo.dev`, mas não `a.b.exemplo.dev` nem `exemplo.dev`.
|
|
56
|
+
return dot > 0 ? wildcard.get(name.slice(dot + 1)) : undefined;
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=tls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls.js","sourceRoot":"","sources":["../../src/server/tls.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbol-metadata.d.ts","sourceRoot":"","sources":["../../src/shims/symbol-metadata.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// TC39 não cria Symbol.metadata automaticamente em todo runtime.
|
|
2
|
+
// Este arquivo deve ser importado ANTES de qualquer decorator rodar.
|
|
3
|
+
const S = Symbol;
|
|
4
|
+
if (!S.metadata) {
|
|
5
|
+
S.metadata = Symbol.for('Symbol.metadata');
|
|
6
|
+
}
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=symbol-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbol-metadata.js","sourceRoot":"","sources":["../../src/shims/symbol-metadata.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,qEAAqE;AACrE,MAAM,CAAC,GAAG,MAA+B,CAAC;AAC1C,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAChB,CAAC,CAAC,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Media type sem parâmetros e em minúsculas: `"Application/JSON; charset=utf-8"` → `"application/json"`. */
|
|
2
|
+
export declare function mediaType(header: string | undefined): string;
|
|
3
|
+
/**
|
|
4
|
+
* Escolhe, entre os tipos `available` (em ordem de preferência do servidor), o melhor para o
|
|
5
|
+
* header `Accept` (F-31). Respeita q-values e curingas (`text/*`, `*\/*`). Sem `Accept`,
|
|
6
|
+
* devolve o primeiro. Retorna `undefined` quando nenhum é aceitável (→ 406).
|
|
7
|
+
*/
|
|
8
|
+
export declare function negotiate(accept: string | undefined, available: readonly string[]): string | undefined;
|
|
9
|
+
/** Acrescenta `charset=utf-8` a tipos textuais sem charset. */
|
|
10
|
+
export declare function withCharset(type: string): string;
|
|
11
|
+
/** `application/json` ou `application/*+json`, com parâmetros opcionais (B-11). */
|
|
12
|
+
export declare function isJsonContentType(header: string | undefined): boolean;
|
|
13
|
+
//# sourceMappingURL=content-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-type.d.ts","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAU5D;AAGD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAsBtG;AAYD,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYhD;AAGD,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGrE"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** Media type sem parâmetros e em minúsculas: `"Application/JSON; charset=utf-8"` → `"application/json"`. */
|
|
2
|
+
export function mediaType(header) {
|
|
3
|
+
if (!header)
|
|
4
|
+
return '';
|
|
5
|
+
let base = MEDIA_TYPES.get(header);
|
|
6
|
+
if (base === undefined) {
|
|
7
|
+
base = header.split(';', 1)[0].trim().toLowerCase();
|
|
8
|
+
// Memoizado com limite: os tipos vêm da configuração e dos handlers (baixa cardinalidade), mas um
|
|
9
|
+
// Content-Type montado com dado do cliente não pode fazer o mapa crescer sem fim.
|
|
10
|
+
if (MEDIA_TYPES.size < 256)
|
|
11
|
+
MEDIA_TYPES.set(header, base);
|
|
12
|
+
}
|
|
13
|
+
return base;
|
|
14
|
+
}
|
|
15
|
+
const MEDIA_TYPES = new Map();
|
|
16
|
+
/**
|
|
17
|
+
* Escolhe, entre os tipos `available` (em ordem de preferência do servidor), o melhor para o
|
|
18
|
+
* header `Accept` (F-31). Respeita q-values e curingas (`text/*`, `*\/*`). Sem `Accept`,
|
|
19
|
+
* devolve o primeiro. Retorna `undefined` quando nenhum é aceitável (→ 406).
|
|
20
|
+
*/
|
|
21
|
+
export function negotiate(accept, available) {
|
|
22
|
+
if (!accept?.trim())
|
|
23
|
+
return available[0];
|
|
24
|
+
const ranges = accept
|
|
25
|
+
.split(',')
|
|
26
|
+
.map((part, index) => {
|
|
27
|
+
const [range = '', ...params] = part.trim().toLowerCase().split(';');
|
|
28
|
+
const q = Number(params
|
|
29
|
+
.map((p) => p.trim())
|
|
30
|
+
.find((p) => p.startsWith('q='))
|
|
31
|
+
?.slice(2) ?? '1');
|
|
32
|
+
return { range: range.trim(), q: Number.isFinite(q) ? q : 1, index };
|
|
33
|
+
})
|
|
34
|
+
.filter((r) => r.range && r.q > 0)
|
|
35
|
+
.sort((a, b) => b.q - a.q || specificity(b.range) - specificity(a.range) || a.index - b.index);
|
|
36
|
+
for (const { range } of ranges) {
|
|
37
|
+
const match = available.find((type) => matches(range, mediaType(type)));
|
|
38
|
+
if (match)
|
|
39
|
+
return match;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
function specificity(range) {
|
|
44
|
+
if (range === '*/*')
|
|
45
|
+
return 0;
|
|
46
|
+
return range.endsWith('/*') ? 1 : 2;
|
|
47
|
+
}
|
|
48
|
+
function matches(range, type) {
|
|
49
|
+
if (range === '*/*' || range === type)
|
|
50
|
+
return true;
|
|
51
|
+
return range.endsWith('/*') && type.startsWith(range.slice(0, -1));
|
|
52
|
+
}
|
|
53
|
+
/** Acrescenta `charset=utf-8` a tipos textuais sem charset. */
|
|
54
|
+
export function withCharset(type) {
|
|
55
|
+
let out = WITH_CHARSET.get(type);
|
|
56
|
+
if (out === undefined) {
|
|
57
|
+
if (/;\s*charset=/i.test(type))
|
|
58
|
+
out = type;
|
|
59
|
+
else {
|
|
60
|
+
const base = mediaType(type);
|
|
61
|
+
const textual = base.startsWith('text/') || isJsonContentType(base) || /\+xml$|\/xml$|yaml$/.test(base);
|
|
62
|
+
out = textual ? `${type}; charset=utf-8` : type;
|
|
63
|
+
}
|
|
64
|
+
if (WITH_CHARSET.size < 256)
|
|
65
|
+
WITH_CHARSET.set(type, out);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
const WITH_CHARSET = new Map();
|
|
70
|
+
/** `application/json` ou `application/*+json`, com parâmetros opcionais (B-11). */
|
|
71
|
+
export function isJsonContentType(header) {
|
|
72
|
+
const type = mediaType(header);
|
|
73
|
+
return type === 'application/json' || /^application\/[a-z0-9!#$&^_.-]+\+json$/.test(type);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=content-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-type.js","sourceRoot":"","sources":["../../src/utils/content-type.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leitura e escrita de cookies (RFC 6265), seguras por padrão.
|
|
3
|
+
*
|
|
4
|
+
* - **Leitura:** o resultado é um objeto sem protótipo (`__proto__` vira um cookie comum, sem poluir
|
|
5
|
+
* nada); em nomes repetidos vale o primeiro, como nos navegadores; um valor com `%` inválido fica cru.
|
|
6
|
+
* - **Escrita:** `HttpOnly`, `Secure`, `SameSite=Lax` e `Path=/` por padrão. Nome, `Domain` e `Path`
|
|
7
|
+
* são validados (sem `;`, quebra de linha nem caracteres de controle), então não dá para injetar
|
|
8
|
+
* atributos. O valor é codificado com `encodeURIComponent`.
|
|
9
|
+
* - **Prefixos:** `__Host-` exige `Secure`, `Path=/` e nenhum `Domain`; `__Secure-` exige `Secure`.
|
|
10
|
+
* `SameSite=None` exige `Secure`. Violações lançam erro na hora de definir o cookie.
|
|
11
|
+
*/
|
|
12
|
+
export interface CookieOptions {
|
|
13
|
+
/** Padrão: `true`. Impede a leitura por JavaScript no navegador. */
|
|
14
|
+
httpOnly?: boolean;
|
|
15
|
+
/** Padrão: `true`. Os navegadores aceitam cookies `Secure` em `http://localhost`. */
|
|
16
|
+
secure?: boolean;
|
|
17
|
+
/** Padrão: `'Lax'`. `'None'` exige `secure`. */
|
|
18
|
+
sameSite?: 'Strict' | 'Lax' | 'None' | false;
|
|
19
|
+
/** Padrão: `'/'`. */
|
|
20
|
+
path?: string;
|
|
21
|
+
/** Sem `domain`, o cookie vale só para o host atual (o mais restrito). */
|
|
22
|
+
domain?: string;
|
|
23
|
+
/** Duração em segundos. `0` remove o cookie. */
|
|
24
|
+
maxAge?: number;
|
|
25
|
+
expires?: Date;
|
|
26
|
+
/** Cookie particionado (CHIPS), para uso em iframes de terceiros. Exige `secure`. */
|
|
27
|
+
partitioned?: boolean;
|
|
28
|
+
priority?: 'Low' | 'Medium' | 'High';
|
|
29
|
+
}
|
|
30
|
+
/** Lê o header `Cookie` num objeto sem protótipo. */
|
|
31
|
+
export declare function parseCookies(header: string | undefined): Record<string, string>;
|
|
32
|
+
/** Monta o valor de um header `Set-Cookie`, aplicando os padrões seguros. */
|
|
33
|
+
export declare function serializeCookie(name: string, value: string, opts?: CookieOptions): string;
|
|
34
|
+
//# sourceMappingURL=cookie.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookie.d.ts","sourceRoot":"","sources":["../../src/utils/cookie.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qFAAqF;IACrF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IAC7C,qBAAqB;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,qFAAqF;IACrF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACtC;AAQD,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAa/E;AAWD,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,aAAkB,GAAG,MAAM,CAoC7F"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leitura e escrita de cookies (RFC 6265), seguras por padrão.
|
|
3
|
+
*
|
|
4
|
+
* - **Leitura:** o resultado é um objeto sem protótipo (`__proto__` vira um cookie comum, sem poluir
|
|
5
|
+
* nada); em nomes repetidos vale o primeiro, como nos navegadores; um valor com `%` inválido fica cru.
|
|
6
|
+
* - **Escrita:** `HttpOnly`, `Secure`, `SameSite=Lax` e `Path=/` por padrão. Nome, `Domain` e `Path`
|
|
7
|
+
* são validados (sem `;`, quebra de linha nem caracteres de controle), então não dá para injetar
|
|
8
|
+
* atributos. O valor é codificado com `encodeURIComponent`.
|
|
9
|
+
* - **Prefixos:** `__Host-` exige `Secure`, `Path=/` e nenhum `Domain`; `__Secure-` exige `Secure`.
|
|
10
|
+
* `SameSite=None` exige `Secure`. Violações lançam erro na hora de definir o cookie.
|
|
11
|
+
*/
|
|
12
|
+
/** `token` da RFC 7230: o que um nome de cookie pode conter. */
|
|
13
|
+
const TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
14
|
+
/** Domain e Path: nada de `;`, controle (inclui CR/LF) nem DEL. */
|
|
15
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: recusar caracteres de controle é o objetivo (injeção de atributos).
|
|
16
|
+
const ATTR_VALUE = /^[^\x00-\x1f\x7f;]*$/;
|
|
17
|
+
/** Lê o header `Cookie` num objeto sem protótipo. */
|
|
18
|
+
export function parseCookies(header) {
|
|
19
|
+
const out = Object.create(null);
|
|
20
|
+
if (!header)
|
|
21
|
+
return out;
|
|
22
|
+
for (const part of header.split(';')) {
|
|
23
|
+
const eq = part.indexOf('=');
|
|
24
|
+
if (eq === -1)
|
|
25
|
+
continue;
|
|
26
|
+
const name = part.slice(0, eq).trim();
|
|
27
|
+
if (!name || name in out)
|
|
28
|
+
continue;
|
|
29
|
+
let value = part.slice(eq + 1).trim();
|
|
30
|
+
if (value.length >= 2 && value.startsWith('"') && value.endsWith('"'))
|
|
31
|
+
value = value.slice(1, -1);
|
|
32
|
+
out[name] = safeDecode(value);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
function safeDecode(value) {
|
|
37
|
+
if (!value.includes('%'))
|
|
38
|
+
return value;
|
|
39
|
+
try {
|
|
40
|
+
return decodeURIComponent(value);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Monta o valor de um header `Set-Cookie`, aplicando os padrões seguros. */
|
|
47
|
+
export function serializeCookie(name, value, opts = {}) {
|
|
48
|
+
if (!TOKEN.test(name))
|
|
49
|
+
throw new Error(`[flowing] invalid cookie name "${name}".`);
|
|
50
|
+
const httpOnly = opts.httpOnly ?? true;
|
|
51
|
+
const secure = opts.secure ?? true;
|
|
52
|
+
const sameSite = opts.sameSite ?? 'Lax';
|
|
53
|
+
const path = opts.path ?? '/';
|
|
54
|
+
if (!ATTR_VALUE.test(path))
|
|
55
|
+
throw new Error(`[flowing] invalid cookie path "${path}".`);
|
|
56
|
+
if (opts.domain !== undefined && (!opts.domain || !ATTR_VALUE.test(opts.domain))) {
|
|
57
|
+
throw new Error(`[flowing] invalid cookie domain "${opts.domain}".`);
|
|
58
|
+
}
|
|
59
|
+
if (sameSite === 'None' && !secure)
|
|
60
|
+
throw new Error(`[flowing] cookie "${name}": SameSite=None requires secure.`);
|
|
61
|
+
if (opts.partitioned && !secure)
|
|
62
|
+
throw new Error(`[flowing] cookie "${name}": partitioned requires secure.`);
|
|
63
|
+
if (name.startsWith('__Secure-') && !secure)
|
|
64
|
+
throw new Error(`[flowing] cookie "${name}": the __Secure- prefix requires secure.`);
|
|
65
|
+
if (name.startsWith('__Host-') && (!secure || path !== '/' || opts.domain !== undefined)) {
|
|
66
|
+
throw new Error(`[flowing] cookie "${name}": the __Host- prefix requires secure, path "/" and no domain.`);
|
|
67
|
+
}
|
|
68
|
+
let out = `${name}=${encodeURIComponent(value)}`;
|
|
69
|
+
if (opts.maxAge !== undefined) {
|
|
70
|
+
if (!Number.isFinite(opts.maxAge))
|
|
71
|
+
throw new Error(`[flowing] cookie "${name}": invalid maxAge.`);
|
|
72
|
+
out += `; Max-Age=${Math.floor(opts.maxAge)}`;
|
|
73
|
+
}
|
|
74
|
+
if (opts.expires) {
|
|
75
|
+
if (Number.isNaN(opts.expires.getTime()))
|
|
76
|
+
throw new Error(`[flowing] cookie "${name}": invalid expires.`);
|
|
77
|
+
out += `; Expires=${opts.expires.toUTCString()}`;
|
|
78
|
+
}
|
|
79
|
+
if (opts.domain !== undefined)
|
|
80
|
+
out += `; Domain=${opts.domain}`;
|
|
81
|
+
out += `; Path=${path}`;
|
|
82
|
+
if (httpOnly)
|
|
83
|
+
out += '; HttpOnly';
|
|
84
|
+
if (secure)
|
|
85
|
+
out += '; Secure';
|
|
86
|
+
if (sameSite)
|
|
87
|
+
out += `; SameSite=${sameSite}`;
|
|
88
|
+
if (opts.partitioned)
|
|
89
|
+
out += '; Partitioned';
|
|
90
|
+
if (opts.priority)
|
|
91
|
+
out += `; Priority=${opts.priority}`;
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=cookie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookie.js","sourceRoot":"","sources":["../../src/utils/cookie.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAqBH,gEAAgE;AAChE,MAAM,KAAK,GAAG,gCAAgC,CAAC;AAC/C,mEAAmE;AACnE,+HAA+H;AAC/H,MAAM,UAAU,GAAG,sBAAsB,CAAC;AAE1C,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAAC,MAA0B;IACrD,MAAM,GAAG,GAA2B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,CAAC,MAAM;QAAE,OAAO,GAAG,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,SAAS;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG;YAAE,SAAS;QACnC,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClG,GAAG,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAa,EAAE,IAAI,GAAkB,EAAE;IACnF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,IAAI,CAAC,CAAC;IAEnF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC;IAE9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,IAAI,CAAC,CAAC;IACxF,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,QAAQ,KAAK,MAAM,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,mCAAmC,CAAC,CAAC;IAClH,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,iCAAiC,CAAC,CAAC;IAC7G,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,0CAA0C,CAAC,CAAC;IAClI,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,gEAAgE,CAAC,CAAC;IAC7G,CAAC;IAED,IAAI,GAAG,GAAG,GAAG,IAAI,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;IACjD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,oBAAoB,CAAC,CAAC;QAClG,GAAG,IAAI,aAAa,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IAChD,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,qBAAqB,CAAC,CAAC;QAC1G,GAAG,IAAI,aAAa,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;IACnD,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,GAAG,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC;IAChE,GAAG,IAAI,UAAU,IAAI,EAAE,CAAC;IACxB,IAAI,QAAQ;QAAE,GAAG,IAAI,YAAY,CAAC;IAClC,IAAI,MAAM;QAAE,GAAG,IAAI,UAAU,CAAC;IAC9B,IAAI,QAAQ;QAAE,GAAG,IAAI,cAAc,QAAQ,EAAE,CAAC;IAC9C,IAAI,IAAI,CAAC,WAAW;QAAE,GAAG,IAAI,eAAe,CAAC;IAC7C,IAAI,IAAI,CAAC,QAAQ;QAAE,GAAG,IAAI,cAAc,IAAI,CAAC,QAAQ,EAAE,CAAC;IACxD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { isJsonContentType, mediaType, negotiate, withCharset } from './content-type.ts';
|
|
2
|
+
export { joinPaths } from './path.ts';
|
|
3
|
+
export { DEFAULT_MAX_QUERY_KEYS, parseQuery, type ParsedQuery, type QueryParser } from './query.ts';
|
|
4
|
+
export { hostnameOf, isValidHost, parseRequestTarget, pickForwarded } from './request-target.ts';
|
|
5
|
+
export { compileHostMatcher, compileOriginMatcher, normalizeOrigin, toFullMatch, type MatchRule } from './origin-match.ts';
|
|
6
|
+
export { parseCookies, serializeCookie, type CookieOptions } from './cookie.ts';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC3H,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { isJsonContentType, mediaType, negotiate, withCharset } from './content-type.js';
|
|
2
|
+
export { joinPaths } from './path.js';
|
|
3
|
+
export { DEFAULT_MAX_QUERY_KEYS, parseQuery } from './query.js';
|
|
4
|
+
export { hostnameOf, isValidHost, parseRequestTarget, pickForwarded } from './request-target.js';
|
|
5
|
+
export { compileHostMatcher, compileOriginMatcher, normalizeOrigin, toFullMatch } from './origin-match.js';
|
|
6
|
+
export { parseCookies, serializeCookie } from './cookie.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAsC,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,eAAe,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAC3H,OAAO,EAAE,YAAY,EAAE,eAAe,EAAsB,MAAM,aAAa,CAAC"}
|