@peaje/proxy 0.2.0 → 0.2.1
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/README.md +5 -0
- package/dist/{chunk-QHUY5N5S.js → chunk-SWB3HJVY.js} +58 -2
- package/dist/express.cjs +53 -1
- package/dist/express.js +5 -2
- package/dist/hono.cjs +67 -3
- package/dist/hono.d.cts +3 -0
- package/dist/hono.d.ts +3 -0
- package/dist/hono.js +10 -2
- package/dist/index.cjs +58 -2
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +1 -1
- package/dist/vercel.cjs +54 -0
- package/dist/vercel.js +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -102,6 +102,10 @@ The forwarded request keeps method, body, query and `authorization` (the MPP cre
|
|
|
102
102
|
|
|
103
103
|
Upgrading from 0.1.x: if your priced routes live outside `/api/` and `/v1/`, add their prefix to `apiPrefixes` before you deploy 0.2.0.
|
|
104
104
|
|
|
105
|
+
## Bot visits (since 0.2.1)
|
|
106
|
+
|
|
107
|
+
When a known AI bot (GPTBot, ClaudeBot, OAI-SearchBot, PerplexityBot, Googlebot) reads a page your app serves itself, such as your home page or a blog post, the proxy tells the gateway in the background, so the read shows up in your agent visits. The gateway never sees those requests otherwise. It sends only the path, without the query string, and the bot's user agent: no IP, no cookies, and visits from people are never reported. The Vercel adapter runs it in `waitUntil`, Hono on Workers in `executionCtx.waitUntil`, and `peajeFetch(request, waitUntil)` takes one; elsewhere it runs alongside the response with a 3 s timeout. Turn it off with `{ slug, reportBotVisits: false }`.
|
|
108
|
+
|
|
105
109
|
## Options
|
|
106
110
|
|
|
107
111
|
| Option | Default |
|
|
@@ -110,6 +114,7 @@ Upgrading from 0.1.x: if your priced routes live outside `/api/` and `/v1/`, add
|
|
|
110
114
|
| `secret` | `process.env.PEAJE_ORIGIN_SECRET` |
|
|
111
115
|
| `gateway` | `process.env.PEAJE_GATEWAY_URL` or `https://api.usepeaje.com` |
|
|
112
116
|
| `apiPrefixes` | `['/api/', '/v1/']`: where your priced API routes live; the root and reserved paths are never accepted |
|
|
117
|
+
| `reportBotVisits` | `true`: tell the gateway when an AI bot reads a page of your app, for your agent visits |
|
|
113
118
|
|
|
114
119
|
## License
|
|
115
120
|
|
|
@@ -55,6 +55,24 @@ var PATHS_RESERVADOS = [
|
|
|
55
55
|
var PEAJE_FETCH_HEADER = "x-peaje-fetch";
|
|
56
56
|
var PEAJE_HOST_HEADER = "x-peaje-forwarded-host";
|
|
57
57
|
|
|
58
|
+
// ../shared/src/kit/bots.ts
|
|
59
|
+
var BOTS_DE_VISITA = [
|
|
60
|
+
{ patron: /OAI-SearchBot/i, tipo: "openai-searchbot" },
|
|
61
|
+
{ patron: /PerplexityBot/i, tipo: "perplexitybot" },
|
|
62
|
+
{ patron: /Googlebot/i, tipo: "googlebot" },
|
|
63
|
+
{ patron: /ClaudeBot|anthropic-ai/i, tipo: "claudebot" },
|
|
64
|
+
{ patron: /GPTBot/i, tipo: "gptbot" }
|
|
65
|
+
];
|
|
66
|
+
function tipoDeBot(ua) {
|
|
67
|
+
if (!ua) return null;
|
|
68
|
+
for (const b of BOTS_DE_VISITA) if (b.patron.test(ua)) return b.tipo;
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
var PEAJE_VERIFICADOR_HEADER = "x-peaje-verificador";
|
|
72
|
+
var NO_ES_PAGINA = /\.(png|jpe?g|gif|webp|avif|svg|ico|css|m?js|map|woff2?|ttf|otf|eot|mp4|webm|mp3|wav)$/i;
|
|
73
|
+
var MAX_PATH_LECTURA = 500;
|
|
74
|
+
var MAX_UA_LECTURA = 300;
|
|
75
|
+
|
|
58
76
|
// ../shared/src/kit/proxy-runtime.ts
|
|
59
77
|
var PEAJE_ORIGIN_HEADER = "x-peaje-origin";
|
|
60
78
|
function iguales(a, b) {
|
|
@@ -131,6 +149,17 @@ function patronReenviable(patron) {
|
|
|
131
149
|
if (segs.length === 0) return false;
|
|
132
150
|
return !(segs.length === 1 && (segs[0] === "*" || segs[0].startsWith(":")));
|
|
133
151
|
}
|
|
152
|
+
function lecturaDeBot(input) {
|
|
153
|
+
const method = input.method.toUpperCase();
|
|
154
|
+
if (method !== "GET" && method !== "HEAD") return null;
|
|
155
|
+
const h = input.headers;
|
|
156
|
+
if (h.has(PEAJE_ORIGIN_HEADER) || h.has(PEAJE_FETCH_HEADER) || h.has(PEAJE_VERIFICADOR_HEADER)) return null;
|
|
157
|
+
const ua = h.get("user-agent");
|
|
158
|
+
if (!ua || !tipoDeBot(ua)) return null;
|
|
159
|
+
const path = input.pathname;
|
|
160
|
+
if (!path.startsWith("/") || path.startsWith("/_next/") || path.startsWith("/_vercel/") || NO_ES_PAGINA.test(path)) return null;
|
|
161
|
+
return { path: path.slice(0, MAX_PATH_LECTURA), method, userAgent: ua.slice(0, MAX_UA_LECTURA) };
|
|
162
|
+
}
|
|
134
163
|
function crearProxyRuntime(opciones) {
|
|
135
164
|
const base = opciones.base.replace(/\/+$/, "");
|
|
136
165
|
const ttl = opciones.ttlMs ?? 6e4;
|
|
@@ -175,6 +204,22 @@ function crearProxyRuntime(opciones) {
|
|
|
175
204
|
},
|
|
176
205
|
/** Fuerza la carga del manifiesto (útil al arrancar o en tests). */
|
|
177
206
|
cargar: () => refrescando ??= refrescar(),
|
|
207
|
+
/**
|
|
208
|
+
* Si la request es un bot leyendo una página del sitio, le avisa al
|
|
209
|
+
* gateway y devuelve la promesa del aviso (para `waitUntil`); si no, null.
|
|
210
|
+
* El aviso nunca lanza ni demora la página: 3 s de tope y se descarta la
|
|
211
|
+
* respuesta.
|
|
212
|
+
*/
|
|
213
|
+
reportarLectura(input) {
|
|
214
|
+
const lectura = lecturaDeBot(input);
|
|
215
|
+
if (!lectura) return null;
|
|
216
|
+
return fetchImpl(`${base}/kit/visita`, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: { "content-type": "application/json" },
|
|
219
|
+
body: JSON.stringify(lectura),
|
|
220
|
+
signal: AbortSignal.timeout(3e3)
|
|
221
|
+
}).then((res) => res.body?.cancel()).catch(() => void 0);
|
|
222
|
+
},
|
|
178
223
|
/**
|
|
179
224
|
* Decide si la request va al gateway. `method` y `pathname` de la request,
|
|
180
225
|
* `search` con el `?` incluido, y los headers para cortar bucles.
|
|
@@ -366,6 +411,7 @@ function crearPeaje(opciones) {
|
|
|
366
411
|
const secreto = opciones.secret ?? env("PEAJE_ORIGIN_SECRET") ?? null;
|
|
367
412
|
const fetchImpl = opciones.fetch ?? ((...a) => fetch(...a));
|
|
368
413
|
const runtime = crearProxyRuntime({ base, secreto, fetchImpl, prefijosApi: opciones.apiPrefixes ?? PREFIJOS_API_POR_DEFECTO });
|
|
414
|
+
const reportar = opciones.reportBotVisits !== false;
|
|
369
415
|
return {
|
|
370
416
|
base,
|
|
371
417
|
async decidir({ method, url, headers }) {
|
|
@@ -393,16 +439,26 @@ function crearPeaje(opciones) {
|
|
|
393
439
|
vuelta.delete("transfer-encoding");
|
|
394
440
|
vuelta.delete("connection");
|
|
395
441
|
return new Response(method === "HEAD" ? null : res.body, { status: res.status, statusText: res.statusText, headers: vuelta });
|
|
442
|
+
},
|
|
443
|
+
reportarLectura({ method, url, headers }) {
|
|
444
|
+
return reportar ? runtime.reportarLectura({ method, pathname: url.pathname, headers }) : null;
|
|
396
445
|
}
|
|
397
446
|
};
|
|
398
447
|
}
|
|
399
448
|
function peajeFetch(opciones) {
|
|
400
449
|
const peaje = crearPeaje(opciones);
|
|
401
|
-
return async (request) => {
|
|
450
|
+
return async (request, waitUntil) => {
|
|
402
451
|
const url = new URL(request.url);
|
|
403
452
|
const entrada = { method: request.method.toUpperCase(), url, headers: request.headers };
|
|
404
453
|
const destino = await peaje.decidir(entrada);
|
|
405
|
-
if (!destino)
|
|
454
|
+
if (!destino) {
|
|
455
|
+
const lectura = peaje.reportarLectura(entrada);
|
|
456
|
+
if (lectura) {
|
|
457
|
+
if (waitUntil) waitUntil(lectura);
|
|
458
|
+
else void lectura;
|
|
459
|
+
}
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
406
462
|
const body = entrada.method === "GET" || entrada.method === "HEAD" ? null : await request.arrayBuffer();
|
|
407
463
|
return peaje.reenviar(destino, { ...entrada, body });
|
|
408
464
|
};
|
package/dist/express.cjs
CHANGED
|
@@ -83,6 +83,24 @@ var PATHS_RESERVADOS = [
|
|
|
83
83
|
var PEAJE_FETCH_HEADER = "x-peaje-fetch";
|
|
84
84
|
var PEAJE_HOST_HEADER = "x-peaje-forwarded-host";
|
|
85
85
|
|
|
86
|
+
// ../shared/src/kit/bots.ts
|
|
87
|
+
var BOTS_DE_VISITA = [
|
|
88
|
+
{ patron: /OAI-SearchBot/i, tipo: "openai-searchbot" },
|
|
89
|
+
{ patron: /PerplexityBot/i, tipo: "perplexitybot" },
|
|
90
|
+
{ patron: /Googlebot/i, tipo: "googlebot" },
|
|
91
|
+
{ patron: /ClaudeBot|anthropic-ai/i, tipo: "claudebot" },
|
|
92
|
+
{ patron: /GPTBot/i, tipo: "gptbot" }
|
|
93
|
+
];
|
|
94
|
+
function tipoDeBot(ua) {
|
|
95
|
+
if (!ua) return null;
|
|
96
|
+
for (const b of BOTS_DE_VISITA) if (b.patron.test(ua)) return b.tipo;
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
var PEAJE_VERIFICADOR_HEADER = "x-peaje-verificador";
|
|
100
|
+
var NO_ES_PAGINA = /\.(png|jpe?g|gif|webp|avif|svg|ico|css|m?js|map|woff2?|ttf|otf|eot|mp4|webm|mp3|wav)$/i;
|
|
101
|
+
var MAX_PATH_LECTURA = 500;
|
|
102
|
+
var MAX_UA_LECTURA = 300;
|
|
103
|
+
|
|
86
104
|
// ../shared/src/kit/proxy-runtime.ts
|
|
87
105
|
var PEAJE_ORIGIN_HEADER = "x-peaje-origin";
|
|
88
106
|
function iguales(a, b) {
|
|
@@ -159,6 +177,17 @@ function patronReenviable(patron) {
|
|
|
159
177
|
if (segs.length === 0) return false;
|
|
160
178
|
return !(segs.length === 1 && (segs[0] === "*" || segs[0].startsWith(":")));
|
|
161
179
|
}
|
|
180
|
+
function lecturaDeBot(input) {
|
|
181
|
+
const method = input.method.toUpperCase();
|
|
182
|
+
if (method !== "GET" && method !== "HEAD") return null;
|
|
183
|
+
const h = input.headers;
|
|
184
|
+
if (h.has(PEAJE_ORIGIN_HEADER) || h.has(PEAJE_FETCH_HEADER) || h.has(PEAJE_VERIFICADOR_HEADER)) return null;
|
|
185
|
+
const ua = h.get("user-agent");
|
|
186
|
+
if (!ua || !tipoDeBot(ua)) return null;
|
|
187
|
+
const path = input.pathname;
|
|
188
|
+
if (!path.startsWith("/") || path.startsWith("/_next/") || path.startsWith("/_vercel/") || NO_ES_PAGINA.test(path)) return null;
|
|
189
|
+
return { path: path.slice(0, MAX_PATH_LECTURA), method, userAgent: ua.slice(0, MAX_UA_LECTURA) };
|
|
190
|
+
}
|
|
162
191
|
function crearProxyRuntime(opciones) {
|
|
163
192
|
const base = opciones.base.replace(/\/+$/, "");
|
|
164
193
|
const ttl = opciones.ttlMs ?? 6e4;
|
|
@@ -203,6 +232,22 @@ function crearProxyRuntime(opciones) {
|
|
|
203
232
|
},
|
|
204
233
|
/** Fuerza la carga del manifiesto (útil al arrancar o en tests). */
|
|
205
234
|
cargar: () => refrescando ??= refrescar(),
|
|
235
|
+
/**
|
|
236
|
+
* Si la request es un bot leyendo una página del sitio, le avisa al
|
|
237
|
+
* gateway y devuelve la promesa del aviso (para `waitUntil`); si no, null.
|
|
238
|
+
* El aviso nunca lanza ni demora la página: 3 s de tope y se descarta la
|
|
239
|
+
* respuesta.
|
|
240
|
+
*/
|
|
241
|
+
reportarLectura(input) {
|
|
242
|
+
const lectura = lecturaDeBot(input);
|
|
243
|
+
if (!lectura) return null;
|
|
244
|
+
return fetchImpl(`${base}/kit/visita`, {
|
|
245
|
+
method: "POST",
|
|
246
|
+
headers: { "content-type": "application/json" },
|
|
247
|
+
body: JSON.stringify(lectura),
|
|
248
|
+
signal: AbortSignal.timeout(3e3)
|
|
249
|
+
}).then((res) => res.body?.cancel()).catch(() => void 0);
|
|
250
|
+
},
|
|
206
251
|
/**
|
|
207
252
|
* Decide si la request va al gateway. `method` y `pathname` de la request,
|
|
208
253
|
* `search` con el `?` incluido, y los headers para cortar bucles.
|
|
@@ -391,6 +436,7 @@ function crearPeaje(opciones) {
|
|
|
391
436
|
const secreto = opciones.secret ?? env("PEAJE_ORIGIN_SECRET") ?? null;
|
|
392
437
|
const fetchImpl = opciones.fetch ?? ((...a) => fetch(...a));
|
|
393
438
|
const runtime = crearProxyRuntime({ base, secreto, fetchImpl, prefijosApi: opciones.apiPrefixes ?? PREFIJOS_API_POR_DEFECTO });
|
|
439
|
+
const reportar = opciones.reportBotVisits !== false;
|
|
394
440
|
return {
|
|
395
441
|
base,
|
|
396
442
|
async decidir({ method, url, headers }) {
|
|
@@ -418,6 +464,9 @@ function crearPeaje(opciones) {
|
|
|
418
464
|
vuelta.delete("transfer-encoding");
|
|
419
465
|
vuelta.delete("connection");
|
|
420
466
|
return new Response(method === "HEAD" ? null : res.body, { status: res.status, statusText: res.statusText, headers: vuelta });
|
|
467
|
+
},
|
|
468
|
+
reportarLectura({ method, url, headers }) {
|
|
469
|
+
return reportar ? runtime.reportarLectura({ method, pathname: url.pathname, headers }) : null;
|
|
421
470
|
}
|
|
422
471
|
};
|
|
423
472
|
}
|
|
@@ -477,7 +526,10 @@ function peajeExpress(opciones) {
|
|
|
477
526
|
const r = req;
|
|
478
527
|
const entrada = { method: (r.method ?? "GET").toUpperCase(), url: urlDe(r), headers: headersDe(r) };
|
|
479
528
|
peaje.decidir(entrada).then(async (destino) => {
|
|
480
|
-
if (!destino)
|
|
529
|
+
if (!destino) {
|
|
530
|
+
void peaje.reportarLectura(entrada);
|
|
531
|
+
return next();
|
|
532
|
+
}
|
|
481
533
|
const body = entrada.method === "GET" || entrada.method === "HEAD" ? null : await bodyDe(r);
|
|
482
534
|
await enviar(res, await peaje.reenviar(destino, { ...entrada, body }));
|
|
483
535
|
}).catch((e) => {
|
package/dist/express.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
crearPeaje
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SWB3HJVY.js";
|
|
4
4
|
|
|
5
5
|
// src/express.ts
|
|
6
6
|
import { Readable } from "stream";
|
|
@@ -58,7 +58,10 @@ function peajeExpress(opciones) {
|
|
|
58
58
|
const r = req;
|
|
59
59
|
const entrada = { method: (r.method ?? "GET").toUpperCase(), url: urlDe(r), headers: headersDe(r) };
|
|
60
60
|
peaje.decidir(entrada).then(async (destino) => {
|
|
61
|
-
if (!destino)
|
|
61
|
+
if (!destino) {
|
|
62
|
+
void peaje.reportarLectura(entrada);
|
|
63
|
+
return next();
|
|
64
|
+
}
|
|
62
65
|
const body = entrada.method === "GET" || entrada.method === "HEAD" ? null : await bodyDe(r);
|
|
63
66
|
await enviar(res, await peaje.reenviar(destino, { ...entrada, body }));
|
|
64
67
|
}).catch((e) => {
|
package/dist/hono.cjs
CHANGED
|
@@ -82,6 +82,24 @@ var PATHS_RESERVADOS = [
|
|
|
82
82
|
var PEAJE_FETCH_HEADER = "x-peaje-fetch";
|
|
83
83
|
var PEAJE_HOST_HEADER = "x-peaje-forwarded-host";
|
|
84
84
|
|
|
85
|
+
// ../shared/src/kit/bots.ts
|
|
86
|
+
var BOTS_DE_VISITA = [
|
|
87
|
+
{ patron: /OAI-SearchBot/i, tipo: "openai-searchbot" },
|
|
88
|
+
{ patron: /PerplexityBot/i, tipo: "perplexitybot" },
|
|
89
|
+
{ patron: /Googlebot/i, tipo: "googlebot" },
|
|
90
|
+
{ patron: /ClaudeBot|anthropic-ai/i, tipo: "claudebot" },
|
|
91
|
+
{ patron: /GPTBot/i, tipo: "gptbot" }
|
|
92
|
+
];
|
|
93
|
+
function tipoDeBot(ua) {
|
|
94
|
+
if (!ua) return null;
|
|
95
|
+
for (const b of BOTS_DE_VISITA) if (b.patron.test(ua)) return b.tipo;
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
var PEAJE_VERIFICADOR_HEADER = "x-peaje-verificador";
|
|
99
|
+
var NO_ES_PAGINA = /\.(png|jpe?g|gif|webp|avif|svg|ico|css|m?js|map|woff2?|ttf|otf|eot|mp4|webm|mp3|wav)$/i;
|
|
100
|
+
var MAX_PATH_LECTURA = 500;
|
|
101
|
+
var MAX_UA_LECTURA = 300;
|
|
102
|
+
|
|
85
103
|
// ../shared/src/kit/proxy-runtime.ts
|
|
86
104
|
var PEAJE_ORIGIN_HEADER = "x-peaje-origin";
|
|
87
105
|
function iguales(a, b) {
|
|
@@ -158,6 +176,17 @@ function patronReenviable(patron) {
|
|
|
158
176
|
if (segs.length === 0) return false;
|
|
159
177
|
return !(segs.length === 1 && (segs[0] === "*" || segs[0].startsWith(":")));
|
|
160
178
|
}
|
|
179
|
+
function lecturaDeBot(input) {
|
|
180
|
+
const method = input.method.toUpperCase();
|
|
181
|
+
if (method !== "GET" && method !== "HEAD") return null;
|
|
182
|
+
const h = input.headers;
|
|
183
|
+
if (h.has(PEAJE_ORIGIN_HEADER) || h.has(PEAJE_FETCH_HEADER) || h.has(PEAJE_VERIFICADOR_HEADER)) return null;
|
|
184
|
+
const ua = h.get("user-agent");
|
|
185
|
+
if (!ua || !tipoDeBot(ua)) return null;
|
|
186
|
+
const path = input.pathname;
|
|
187
|
+
if (!path.startsWith("/") || path.startsWith("/_next/") || path.startsWith("/_vercel/") || NO_ES_PAGINA.test(path)) return null;
|
|
188
|
+
return { path: path.slice(0, MAX_PATH_LECTURA), method, userAgent: ua.slice(0, MAX_UA_LECTURA) };
|
|
189
|
+
}
|
|
161
190
|
function crearProxyRuntime(opciones) {
|
|
162
191
|
const base = opciones.base.replace(/\/+$/, "");
|
|
163
192
|
const ttl = opciones.ttlMs ?? 6e4;
|
|
@@ -202,6 +231,22 @@ function crearProxyRuntime(opciones) {
|
|
|
202
231
|
},
|
|
203
232
|
/** Fuerza la carga del manifiesto (útil al arrancar o en tests). */
|
|
204
233
|
cargar: () => refrescando ??= refrescar(),
|
|
234
|
+
/**
|
|
235
|
+
* Si la request es un bot leyendo una página del sitio, le avisa al
|
|
236
|
+
* gateway y devuelve la promesa del aviso (para `waitUntil`); si no, null.
|
|
237
|
+
* El aviso nunca lanza ni demora la página: 3 s de tope y se descarta la
|
|
238
|
+
* respuesta.
|
|
239
|
+
*/
|
|
240
|
+
reportarLectura(input) {
|
|
241
|
+
const lectura = lecturaDeBot(input);
|
|
242
|
+
if (!lectura) return null;
|
|
243
|
+
return fetchImpl(`${base}/kit/visita`, {
|
|
244
|
+
method: "POST",
|
|
245
|
+
headers: { "content-type": "application/json" },
|
|
246
|
+
body: JSON.stringify(lectura),
|
|
247
|
+
signal: AbortSignal.timeout(3e3)
|
|
248
|
+
}).then((res) => res.body?.cancel()).catch(() => void 0);
|
|
249
|
+
},
|
|
205
250
|
/**
|
|
206
251
|
* Decide si la request va al gateway. `method` y `pathname` de la request,
|
|
207
252
|
* `search` con el `?` incluido, y los headers para cortar bucles.
|
|
@@ -390,6 +435,7 @@ function crearPeaje(opciones) {
|
|
|
390
435
|
const secreto = opciones.secret ?? env("PEAJE_ORIGIN_SECRET") ?? null;
|
|
391
436
|
const fetchImpl = opciones.fetch ?? ((...a) => fetch(...a));
|
|
392
437
|
const runtime = crearProxyRuntime({ base, secreto, fetchImpl, prefijosApi: opciones.apiPrefixes ?? PREFIJOS_API_POR_DEFECTO });
|
|
438
|
+
const reportar = opciones.reportBotVisits !== false;
|
|
393
439
|
return {
|
|
394
440
|
base,
|
|
395
441
|
async decidir({ method, url, headers }) {
|
|
@@ -417,16 +463,26 @@ function crearPeaje(opciones) {
|
|
|
417
463
|
vuelta.delete("transfer-encoding");
|
|
418
464
|
vuelta.delete("connection");
|
|
419
465
|
return new Response(method === "HEAD" ? null : res.body, { status: res.status, statusText: res.statusText, headers: vuelta });
|
|
466
|
+
},
|
|
467
|
+
reportarLectura({ method, url, headers }) {
|
|
468
|
+
return reportar ? runtime.reportarLectura({ method, pathname: url.pathname, headers }) : null;
|
|
420
469
|
}
|
|
421
470
|
};
|
|
422
471
|
}
|
|
423
472
|
function peajeFetch(opciones) {
|
|
424
473
|
const peaje = crearPeaje(opciones);
|
|
425
|
-
return async (request) => {
|
|
474
|
+
return async (request, waitUntil) => {
|
|
426
475
|
const url = new URL(request.url);
|
|
427
476
|
const entrada = { method: request.method.toUpperCase(), url, headers: request.headers };
|
|
428
477
|
const destino = await peaje.decidir(entrada);
|
|
429
|
-
if (!destino)
|
|
478
|
+
if (!destino) {
|
|
479
|
+
const lectura = peaje.reportarLectura(entrada);
|
|
480
|
+
if (lectura) {
|
|
481
|
+
if (waitUntil) waitUntil(lectura);
|
|
482
|
+
else void lectura;
|
|
483
|
+
}
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
430
486
|
const body = entrada.method === "GET" || entrada.method === "HEAD" ? null : await request.arrayBuffer();
|
|
431
487
|
return peaje.reenviar(destino, { ...entrada, body });
|
|
432
488
|
};
|
|
@@ -440,11 +496,19 @@ function peajeHono(opciones) {
|
|
|
440
496
|
...opciones,
|
|
441
497
|
secret: opciones.secret ?? c.env?.PEAJE_ORIGIN_SECRET
|
|
442
498
|
});
|
|
443
|
-
const res = await peaje(c.req.raw);
|
|
499
|
+
const res = await peaje(c.req.raw, esperaDe(c));
|
|
444
500
|
if (res) return res;
|
|
445
501
|
await next();
|
|
446
502
|
};
|
|
447
503
|
}
|
|
504
|
+
function esperaDe(c) {
|
|
505
|
+
try {
|
|
506
|
+
const ctx = c.executionCtx;
|
|
507
|
+
return ctx ? (promesa) => ctx.waitUntil(promesa) : void 0;
|
|
508
|
+
} catch {
|
|
509
|
+
return void 0;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
448
512
|
var hono_default = peajeHono;
|
|
449
513
|
// Annotate the CommonJS export names for ESM import in node:
|
|
450
514
|
0 && (module.exports = {
|
package/dist/hono.d.cts
CHANGED
|
@@ -17,6 +17,9 @@ type ContextoMinimo = {
|
|
|
17
17
|
raw: Request;
|
|
18
18
|
};
|
|
19
19
|
env?: unknown;
|
|
20
|
+
executionCtx?: {
|
|
21
|
+
waitUntil(promesa: Promise<unknown>): void;
|
|
22
|
+
};
|
|
20
23
|
};
|
|
21
24
|
type MiddlewareHono = (c: ContextoMinimo, next: () => Promise<void>) => Promise<Response | void>;
|
|
22
25
|
declare function peajeHono(opciones: OpcionesPeaje): MiddlewareHono;
|
package/dist/hono.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ type ContextoMinimo = {
|
|
|
17
17
|
raw: Request;
|
|
18
18
|
};
|
|
19
19
|
env?: unknown;
|
|
20
|
+
executionCtx?: {
|
|
21
|
+
waitUntil(promesa: Promise<unknown>): void;
|
|
22
|
+
};
|
|
20
23
|
};
|
|
21
24
|
type MiddlewareHono = (c: ContextoMinimo, next: () => Promise<void>) => Promise<Response | void>;
|
|
22
25
|
declare function peajeHono(opciones: OpcionesPeaje): MiddlewareHono;
|
package/dist/hono.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
peajeFetch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SWB3HJVY.js";
|
|
4
4
|
|
|
5
5
|
// src/hono.ts
|
|
6
6
|
function peajeHono(opciones) {
|
|
@@ -10,11 +10,19 @@ function peajeHono(opciones) {
|
|
|
10
10
|
...opciones,
|
|
11
11
|
secret: opciones.secret ?? c.env?.PEAJE_ORIGIN_SECRET
|
|
12
12
|
});
|
|
13
|
-
const res = await peaje(c.req.raw);
|
|
13
|
+
const res = await peaje(c.req.raw, esperaDe(c));
|
|
14
14
|
if (res) return res;
|
|
15
15
|
await next();
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
+
function esperaDe(c) {
|
|
19
|
+
try {
|
|
20
|
+
const ctx = c.executionCtx;
|
|
21
|
+
return ctx ? (promesa) => ctx.waitUntil(promesa) : void 0;
|
|
22
|
+
} catch {
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
18
26
|
var hono_default = peajeHono;
|
|
19
27
|
export {
|
|
20
28
|
hono_default as default,
|
package/dist/index.cjs
CHANGED
|
@@ -86,6 +86,24 @@ var PATHS_RESERVADOS = [
|
|
|
86
86
|
var PEAJE_FETCH_HEADER = "x-peaje-fetch";
|
|
87
87
|
var PEAJE_HOST_HEADER = "x-peaje-forwarded-host";
|
|
88
88
|
|
|
89
|
+
// ../shared/src/kit/bots.ts
|
|
90
|
+
var BOTS_DE_VISITA = [
|
|
91
|
+
{ patron: /OAI-SearchBot/i, tipo: "openai-searchbot" },
|
|
92
|
+
{ patron: /PerplexityBot/i, tipo: "perplexitybot" },
|
|
93
|
+
{ patron: /Googlebot/i, tipo: "googlebot" },
|
|
94
|
+
{ patron: /ClaudeBot|anthropic-ai/i, tipo: "claudebot" },
|
|
95
|
+
{ patron: /GPTBot/i, tipo: "gptbot" }
|
|
96
|
+
];
|
|
97
|
+
function tipoDeBot(ua) {
|
|
98
|
+
if (!ua) return null;
|
|
99
|
+
for (const b of BOTS_DE_VISITA) if (b.patron.test(ua)) return b.tipo;
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
var PEAJE_VERIFICADOR_HEADER = "x-peaje-verificador";
|
|
103
|
+
var NO_ES_PAGINA = /\.(png|jpe?g|gif|webp|avif|svg|ico|css|m?js|map|woff2?|ttf|otf|eot|mp4|webm|mp3|wav)$/i;
|
|
104
|
+
var MAX_PATH_LECTURA = 500;
|
|
105
|
+
var MAX_UA_LECTURA = 300;
|
|
106
|
+
|
|
89
107
|
// ../shared/src/kit/proxy-runtime.ts
|
|
90
108
|
var PEAJE_ORIGIN_HEADER = "x-peaje-origin";
|
|
91
109
|
function iguales(a, b) {
|
|
@@ -162,6 +180,17 @@ function patronReenviable(patron) {
|
|
|
162
180
|
if (segs.length === 0) return false;
|
|
163
181
|
return !(segs.length === 1 && (segs[0] === "*" || segs[0].startsWith(":")));
|
|
164
182
|
}
|
|
183
|
+
function lecturaDeBot(input) {
|
|
184
|
+
const method = input.method.toUpperCase();
|
|
185
|
+
if (method !== "GET" && method !== "HEAD") return null;
|
|
186
|
+
const h = input.headers;
|
|
187
|
+
if (h.has(PEAJE_ORIGIN_HEADER) || h.has(PEAJE_FETCH_HEADER) || h.has(PEAJE_VERIFICADOR_HEADER)) return null;
|
|
188
|
+
const ua = h.get("user-agent");
|
|
189
|
+
if (!ua || !tipoDeBot(ua)) return null;
|
|
190
|
+
const path = input.pathname;
|
|
191
|
+
if (!path.startsWith("/") || path.startsWith("/_next/") || path.startsWith("/_vercel/") || NO_ES_PAGINA.test(path)) return null;
|
|
192
|
+
return { path: path.slice(0, MAX_PATH_LECTURA), method, userAgent: ua.slice(0, MAX_UA_LECTURA) };
|
|
193
|
+
}
|
|
165
194
|
function crearProxyRuntime(opciones) {
|
|
166
195
|
const base = opciones.base.replace(/\/+$/, "");
|
|
167
196
|
const ttl = opciones.ttlMs ?? 6e4;
|
|
@@ -206,6 +235,22 @@ function crearProxyRuntime(opciones) {
|
|
|
206
235
|
},
|
|
207
236
|
/** Fuerza la carga del manifiesto (útil al arrancar o en tests). */
|
|
208
237
|
cargar: () => refrescando ??= refrescar(),
|
|
238
|
+
/**
|
|
239
|
+
* Si la request es un bot leyendo una página del sitio, le avisa al
|
|
240
|
+
* gateway y devuelve la promesa del aviso (para `waitUntil`); si no, null.
|
|
241
|
+
* El aviso nunca lanza ni demora la página: 3 s de tope y se descarta la
|
|
242
|
+
* respuesta.
|
|
243
|
+
*/
|
|
244
|
+
reportarLectura(input) {
|
|
245
|
+
const lectura = lecturaDeBot(input);
|
|
246
|
+
if (!lectura) return null;
|
|
247
|
+
return fetchImpl(`${base}/kit/visita`, {
|
|
248
|
+
method: "POST",
|
|
249
|
+
headers: { "content-type": "application/json" },
|
|
250
|
+
body: JSON.stringify(lectura),
|
|
251
|
+
signal: AbortSignal.timeout(3e3)
|
|
252
|
+
}).then((res) => res.body?.cancel()).catch(() => void 0);
|
|
253
|
+
},
|
|
209
254
|
/**
|
|
210
255
|
* Decide si la request va al gateway. `method` y `pathname` de la request,
|
|
211
256
|
* `search` con el `?` incluido, y los headers para cortar bucles.
|
|
@@ -397,6 +442,7 @@ function crearPeaje(opciones) {
|
|
|
397
442
|
const secreto = opciones.secret ?? env("PEAJE_ORIGIN_SECRET") ?? null;
|
|
398
443
|
const fetchImpl = opciones.fetch ?? ((...a) => fetch(...a));
|
|
399
444
|
const runtime = crearProxyRuntime({ base, secreto, fetchImpl, prefijosApi: opciones.apiPrefixes ?? PREFIJOS_API_POR_DEFECTO });
|
|
445
|
+
const reportar = opciones.reportBotVisits !== false;
|
|
400
446
|
return {
|
|
401
447
|
base,
|
|
402
448
|
async decidir({ method, url, headers }) {
|
|
@@ -424,16 +470,26 @@ function crearPeaje(opciones) {
|
|
|
424
470
|
vuelta.delete("transfer-encoding");
|
|
425
471
|
vuelta.delete("connection");
|
|
426
472
|
return new Response(method === "HEAD" ? null : res.body, { status: res.status, statusText: res.statusText, headers: vuelta });
|
|
473
|
+
},
|
|
474
|
+
reportarLectura({ method, url, headers }) {
|
|
475
|
+
return reportar ? runtime.reportarLectura({ method, pathname: url.pathname, headers }) : null;
|
|
427
476
|
}
|
|
428
477
|
};
|
|
429
478
|
}
|
|
430
479
|
function peajeFetch(opciones) {
|
|
431
480
|
const peaje = crearPeaje(opciones);
|
|
432
|
-
return async (request) => {
|
|
481
|
+
return async (request, waitUntil) => {
|
|
433
482
|
const url = new URL(request.url);
|
|
434
483
|
const entrada = { method: request.method.toUpperCase(), url, headers: request.headers };
|
|
435
484
|
const destino = await peaje.decidir(entrada);
|
|
436
|
-
if (!destino)
|
|
485
|
+
if (!destino) {
|
|
486
|
+
const lectura = peaje.reportarLectura(entrada);
|
|
487
|
+
if (lectura) {
|
|
488
|
+
if (waitUntil) waitUntil(lectura);
|
|
489
|
+
else void lectura;
|
|
490
|
+
}
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
437
493
|
const body = entrada.method === "GET" || entrada.method === "HEAD" ? null : await request.arrayBuffer();
|
|
438
494
|
return peaje.reenviar(destino, { ...entrada, body });
|
|
439
495
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -17,6 +17,12 @@ type OpcionesPeaje = {
|
|
|
17
17
|
* (`/login`, `/auth`, `/api/auth`, `/_next`...) nunca se aceptan.
|
|
18
18
|
*/
|
|
19
19
|
apiPrefixes?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Avisarle al gateway cuando un bot de IA lee una página de la app, para el
|
|
22
|
+
* registro de visitas. Solo viajan la ruta (sin query) y el user-agent del
|
|
23
|
+
* bot. Por defecto `true`.
|
|
24
|
+
*/
|
|
25
|
+
reportBotVisits?: boolean;
|
|
20
26
|
/** Para tests o runtimes sin fetch global. */
|
|
21
27
|
fetch?: typeof fetch;
|
|
22
28
|
};
|
|
@@ -39,15 +45,23 @@ type Peaje = {
|
|
|
39
45
|
reenviar(destino: string, entrada: EntradaDecision & {
|
|
40
46
|
body: BodyInit | null;
|
|
41
47
|
}): Promise<Response>;
|
|
48
|
+
/**
|
|
49
|
+
* Para una request que no fue al gateway: si es un bot de IA leyendo una
|
|
50
|
+
* página, se lo avisa al gateway y devuelve la promesa del aviso (para
|
|
51
|
+
* `waitUntil`). Null si no hay nada que avisar. Nunca lanza.
|
|
52
|
+
*/
|
|
53
|
+
reportarLectura(entrada: EntradaDecision): Promise<void> | null;
|
|
42
54
|
};
|
|
43
55
|
declare function baseDe({ slug, gateway }: Pick<OpcionesPeaje, 'slug' | 'gateway'>): string;
|
|
44
56
|
/** Solo para tests: vuelve a permitir el aviso de secreto faltante. */
|
|
45
57
|
declare function _reiniciarAviso(): void;
|
|
46
58
|
declare function crearPeaje(opciones: OpcionesPeaje): Peaje;
|
|
47
|
-
type PeajeFetch = (request: Request) => Promise<Response | null>;
|
|
59
|
+
type PeajeFetch = (request: Request, waitUntil?: (promesa: Promise<unknown>) => void) => Promise<Response | null>;
|
|
48
60
|
/**
|
|
49
61
|
* `(request) => Response | null`. Null: la request no es de Peaje y la
|
|
50
|
-
* atiende la app. El body se lee (en memoria) solo si va al gateway.
|
|
62
|
+
* atiende la app. El body se lee (en memoria) solo si va al gateway. Con
|
|
63
|
+
* `waitUntil` (Workers, Vercel), el aviso de lectura de un bot corre ahí;
|
|
64
|
+
* sin él, al costado.
|
|
51
65
|
*/
|
|
52
66
|
declare function peajeFetch(opciones: OpcionesPeaje): PeajeFetch;
|
|
53
67
|
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,12 @@ type OpcionesPeaje = {
|
|
|
17
17
|
* (`/login`, `/auth`, `/api/auth`, `/_next`...) nunca se aceptan.
|
|
18
18
|
*/
|
|
19
19
|
apiPrefixes?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Avisarle al gateway cuando un bot de IA lee una página de la app, para el
|
|
22
|
+
* registro de visitas. Solo viajan la ruta (sin query) y el user-agent del
|
|
23
|
+
* bot. Por defecto `true`.
|
|
24
|
+
*/
|
|
25
|
+
reportBotVisits?: boolean;
|
|
20
26
|
/** Para tests o runtimes sin fetch global. */
|
|
21
27
|
fetch?: typeof fetch;
|
|
22
28
|
};
|
|
@@ -39,15 +45,23 @@ type Peaje = {
|
|
|
39
45
|
reenviar(destino: string, entrada: EntradaDecision & {
|
|
40
46
|
body: BodyInit | null;
|
|
41
47
|
}): Promise<Response>;
|
|
48
|
+
/**
|
|
49
|
+
* Para una request que no fue al gateway: si es un bot de IA leyendo una
|
|
50
|
+
* página, se lo avisa al gateway y devuelve la promesa del aviso (para
|
|
51
|
+
* `waitUntil`). Null si no hay nada que avisar. Nunca lanza.
|
|
52
|
+
*/
|
|
53
|
+
reportarLectura(entrada: EntradaDecision): Promise<void> | null;
|
|
42
54
|
};
|
|
43
55
|
declare function baseDe({ slug, gateway }: Pick<OpcionesPeaje, 'slug' | 'gateway'>): string;
|
|
44
56
|
/** Solo para tests: vuelve a permitir el aviso de secreto faltante. */
|
|
45
57
|
declare function _reiniciarAviso(): void;
|
|
46
58
|
declare function crearPeaje(opciones: OpcionesPeaje): Peaje;
|
|
47
|
-
type PeajeFetch = (request: Request) => Promise<Response | null>;
|
|
59
|
+
type PeajeFetch = (request: Request, waitUntil?: (promesa: Promise<unknown>) => void) => Promise<Response | null>;
|
|
48
60
|
/**
|
|
49
61
|
* `(request) => Response | null`. Null: la request no es de Peaje y la
|
|
50
|
-
* atiende la app. El body se lee (en memoria) solo si va al gateway.
|
|
62
|
+
* atiende la app. El body se lee (en memoria) solo si va al gateway. Con
|
|
63
|
+
* `waitUntil` (Workers, Vercel), el aviso de lectura de un bot corre ahí;
|
|
64
|
+
* sin él, al costado.
|
|
51
65
|
*/
|
|
52
66
|
declare function peajeFetch(opciones: OpcionesPeaje): PeajeFetch;
|
|
53
67
|
|
package/dist/index.js
CHANGED
package/dist/vercel.cjs
CHANGED
|
@@ -82,6 +82,24 @@ var PATHS_RESERVADOS = [
|
|
|
82
82
|
var PEAJE_FETCH_HEADER = "x-peaje-fetch";
|
|
83
83
|
var PEAJE_HOST_HEADER = "x-peaje-forwarded-host";
|
|
84
84
|
|
|
85
|
+
// ../shared/src/kit/bots.ts
|
|
86
|
+
var BOTS_DE_VISITA = [
|
|
87
|
+
{ patron: /OAI-SearchBot/i, tipo: "openai-searchbot" },
|
|
88
|
+
{ patron: /PerplexityBot/i, tipo: "perplexitybot" },
|
|
89
|
+
{ patron: /Googlebot/i, tipo: "googlebot" },
|
|
90
|
+
{ patron: /ClaudeBot|anthropic-ai/i, tipo: "claudebot" },
|
|
91
|
+
{ patron: /GPTBot/i, tipo: "gptbot" }
|
|
92
|
+
];
|
|
93
|
+
function tipoDeBot(ua) {
|
|
94
|
+
if (!ua) return null;
|
|
95
|
+
for (const b of BOTS_DE_VISITA) if (b.patron.test(ua)) return b.tipo;
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
var PEAJE_VERIFICADOR_HEADER = "x-peaje-verificador";
|
|
99
|
+
var NO_ES_PAGINA = /\.(png|jpe?g|gif|webp|avif|svg|ico|css|m?js|map|woff2?|ttf|otf|eot|mp4|webm|mp3|wav)$/i;
|
|
100
|
+
var MAX_PATH_LECTURA = 500;
|
|
101
|
+
var MAX_UA_LECTURA = 300;
|
|
102
|
+
|
|
85
103
|
// ../shared/src/kit/proxy-runtime.ts
|
|
86
104
|
var PEAJE_ORIGIN_HEADER = "x-peaje-origin";
|
|
87
105
|
function iguales(a, b) {
|
|
@@ -158,6 +176,17 @@ function patronReenviable(patron) {
|
|
|
158
176
|
if (segs.length === 0) return false;
|
|
159
177
|
return !(segs.length === 1 && (segs[0] === "*" || segs[0].startsWith(":")));
|
|
160
178
|
}
|
|
179
|
+
function lecturaDeBot(input) {
|
|
180
|
+
const method = input.method.toUpperCase();
|
|
181
|
+
if (method !== "GET" && method !== "HEAD") return null;
|
|
182
|
+
const h = input.headers;
|
|
183
|
+
if (h.has(PEAJE_ORIGIN_HEADER) || h.has(PEAJE_FETCH_HEADER) || h.has(PEAJE_VERIFICADOR_HEADER)) return null;
|
|
184
|
+
const ua = h.get("user-agent");
|
|
185
|
+
if (!ua || !tipoDeBot(ua)) return null;
|
|
186
|
+
const path = input.pathname;
|
|
187
|
+
if (!path.startsWith("/") || path.startsWith("/_next/") || path.startsWith("/_vercel/") || NO_ES_PAGINA.test(path)) return null;
|
|
188
|
+
return { path: path.slice(0, MAX_PATH_LECTURA), method, userAgent: ua.slice(0, MAX_UA_LECTURA) };
|
|
189
|
+
}
|
|
161
190
|
function crearProxyRuntime(opciones) {
|
|
162
191
|
const base = opciones.base.replace(/\/+$/, "");
|
|
163
192
|
const ttl = opciones.ttlMs ?? 6e4;
|
|
@@ -202,6 +231,22 @@ function crearProxyRuntime(opciones) {
|
|
|
202
231
|
},
|
|
203
232
|
/** Fuerza la carga del manifiesto (útil al arrancar o en tests). */
|
|
204
233
|
cargar: () => refrescando ??= refrescar(),
|
|
234
|
+
/**
|
|
235
|
+
* Si la request es un bot leyendo una página del sitio, le avisa al
|
|
236
|
+
* gateway y devuelve la promesa del aviso (para `waitUntil`); si no, null.
|
|
237
|
+
* El aviso nunca lanza ni demora la página: 3 s de tope y se descarta la
|
|
238
|
+
* respuesta.
|
|
239
|
+
*/
|
|
240
|
+
reportarLectura(input) {
|
|
241
|
+
const lectura = lecturaDeBot(input);
|
|
242
|
+
if (!lectura) return null;
|
|
243
|
+
return fetchImpl(`${base}/kit/visita`, {
|
|
244
|
+
method: "POST",
|
|
245
|
+
headers: { "content-type": "application/json" },
|
|
246
|
+
body: JSON.stringify(lectura),
|
|
247
|
+
signal: AbortSignal.timeout(3e3)
|
|
248
|
+
}).then((res) => res.body?.cancel()).catch(() => void 0);
|
|
249
|
+
},
|
|
205
250
|
/**
|
|
206
251
|
* Decide si la request va al gateway. `method` y `pathname` de la request,
|
|
207
252
|
* `search` con el `?` incluido, y los headers para cortar bucles.
|
|
@@ -390,6 +435,7 @@ function crearPeaje(opciones) {
|
|
|
390
435
|
const secreto = opciones.secret ?? env("PEAJE_ORIGIN_SECRET") ?? null;
|
|
391
436
|
const fetchImpl = opciones.fetch ?? ((...a) => fetch(...a));
|
|
392
437
|
const runtime = crearProxyRuntime({ base, secreto, fetchImpl, prefijosApi: opciones.apiPrefixes ?? PREFIJOS_API_POR_DEFECTO });
|
|
438
|
+
const reportar = opciones.reportBotVisits !== false;
|
|
393
439
|
return {
|
|
394
440
|
base,
|
|
395
441
|
async decidir({ method, url, headers }) {
|
|
@@ -417,6 +463,9 @@ function crearPeaje(opciones) {
|
|
|
417
463
|
vuelta.delete("transfer-encoding");
|
|
418
464
|
vuelta.delete("connection");
|
|
419
465
|
return new Response(method === "HEAD" ? null : res.body, { status: res.status, statusText: res.statusText, headers: vuelta });
|
|
466
|
+
},
|
|
467
|
+
reportarLectura({ method, url, headers }) {
|
|
468
|
+
return reportar ? runtime.reportarLectura({ method, pathname: url.pathname, headers }) : null;
|
|
420
469
|
}
|
|
421
470
|
};
|
|
422
471
|
}
|
|
@@ -448,6 +497,11 @@ function peajeVercel(opciones, siguiente) {
|
|
|
448
497
|
headers.set("x-forwarded-proto", url.protocol.replace(":", ""));
|
|
449
498
|
return respuestaMiddleware({ "x-middleware-rewrite": destino }, headers);
|
|
450
499
|
}
|
|
500
|
+
const lectura = peaje.reportarLectura(entrada);
|
|
501
|
+
if (lectura) {
|
|
502
|
+
if (context?.waitUntil) context.waitUntil(lectura);
|
|
503
|
+
else void lectura;
|
|
504
|
+
}
|
|
451
505
|
const propia = siguiente ? await siguiente(request, context) : void 0;
|
|
452
506
|
return propia ?? respuestaMiddleware({ "x-middleware-next": "1" });
|
|
453
507
|
};
|
package/dist/vercel.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
HEADERS_NO_REENVIADOS,
|
|
3
3
|
PEAJE_HOST_HEADER,
|
|
4
4
|
crearPeaje
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-SWB3HJVY.js";
|
|
6
6
|
|
|
7
7
|
// src/vercel.ts
|
|
8
8
|
function respuestaMiddleware(control, requestHeaders) {
|
|
@@ -31,6 +31,11 @@ function peajeVercel(opciones, siguiente) {
|
|
|
31
31
|
headers.set("x-forwarded-proto", url.protocol.replace(":", ""));
|
|
32
32
|
return respuestaMiddleware({ "x-middleware-rewrite": destino }, headers);
|
|
33
33
|
}
|
|
34
|
+
const lectura = peaje.reportarLectura(entrada);
|
|
35
|
+
if (lectura) {
|
|
36
|
+
if (context?.waitUntil) context.waitUntil(lectura);
|
|
37
|
+
else void lectura;
|
|
38
|
+
}
|
|
34
39
|
const propia = siguiente ? await siguiente(request, context) : void 0;
|
|
35
40
|
return propia ?? respuestaMiddleware({ "x-middleware-next": "1" });
|
|
36
41
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peaje/proxy",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Peaje for any server: answer HTTP 402 (MPP, x402) for your priced API routes on your own domain. Fetch handler plus Express, Hono and Vercel Routing Middleware adapters.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|