amenbo 0.1.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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -0
  3. package/dist/adapters/index.d.ts +22 -0
  4. package/dist/adapters/index.js +51 -0
  5. package/dist/adapters/index.js.map +1 -0
  6. package/dist/adapters/types.d.ts +21 -0
  7. package/dist/adapters/types.js +2 -0
  8. package/dist/adapters/types.js.map +1 -0
  9. package/dist/cache.d.ts +90 -0
  10. package/dist/cache.js +286 -0
  11. package/dist/cache.js.map +1 -0
  12. package/dist/cli.d.ts +46 -0
  13. package/dist/cli.js +327 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/core.d.ts +78 -0
  16. package/dist/core.js +649 -0
  17. package/dist/core.js.map +1 -0
  18. package/dist/diff.d.ts +20 -0
  19. package/dist/diff.js +44 -0
  20. package/dist/diff.js.map +1 -0
  21. package/dist/errors.d.ts +97 -0
  22. package/dist/errors.js +209 -0
  23. package/dist/errors.js.map +1 -0
  24. package/dist/extract/dataSources.d.ts +10 -0
  25. package/dist/extract/dataSources.js +115 -0
  26. package/dist/extract/dataSources.js.map +1 -0
  27. package/dist/extract/geometry.d.ts +63 -0
  28. package/dist/extract/geometry.js +77 -0
  29. package/dist/extract/geometry.js.map +1 -0
  30. package/dist/extract/markdown.d.ts +24 -0
  31. package/dist/extract/markdown.js +221 -0
  32. package/dist/extract/markdown.js.map +1 -0
  33. package/dist/extract/outline.d.ts +33 -0
  34. package/dist/extract/outline.js +128 -0
  35. package/dist/extract/outline.js.map +1 -0
  36. package/dist/extract/pdf.d.ts +22 -0
  37. package/dist/extract/pdf.js +95 -0
  38. package/dist/extract/pdf.js.map +1 -0
  39. package/dist/extract/preview.d.ts +19 -0
  40. package/dist/extract/preview.js +94 -0
  41. package/dist/extract/preview.js.map +1 -0
  42. package/dist/extract/pruning.d.ts +61 -0
  43. package/dist/extract/pruning.js +101 -0
  44. package/dist/extract/pruning.js.map +1 -0
  45. package/dist/extract/qualityScore.d.ts +67 -0
  46. package/dist/extract/qualityScore.js +98 -0
  47. package/dist/extract/qualityScore.js.map +1 -0
  48. package/dist/fetcher/browser.d.ts +85 -0
  49. package/dist/fetcher/browser.js +343 -0
  50. package/dist/fetcher/browser.js.map +1 -0
  51. package/dist/fetcher/http.d.ts +105 -0
  52. package/dist/fetcher/http.js +538 -0
  53. package/dist/fetcher/http.js.map +1 -0
  54. package/dist/fetcher/index.d.ts +41 -0
  55. package/dist/fetcher/index.js +92 -0
  56. package/dist/fetcher/index.js.map +1 -0
  57. package/dist/jp/consentBanner.d.ts +27 -0
  58. package/dist/jp/consentBanner.js +48 -0
  59. package/dist/jp/consentBanner.js.map +1 -0
  60. package/dist/jp/normalize.d.ts +30 -0
  61. package/dist/jp/normalize.js +65 -0
  62. package/dist/jp/normalize.js.map +1 -0
  63. package/dist/links.d.ts +20 -0
  64. package/dist/links.js +223 -0
  65. package/dist/links.js.map +1 -0
  66. package/dist/politeness.d.ts +66 -0
  67. package/dist/politeness.js +170 -0
  68. package/dist/politeness.js.map +1 -0
  69. package/dist/screenshot.d.ts +38 -0
  70. package/dist/screenshot.js +90 -0
  71. package/dist/screenshot.js.map +1 -0
  72. package/dist/server.d.ts +3 -0
  73. package/dist/server.js +111 -0
  74. package/dist/server.js.map +1 -0
  75. package/dist/templateLearning.d.ts +11 -0
  76. package/dist/templateLearning.js +42 -0
  77. package/dist/templateLearning.js.map +1 -0
  78. package/dist/tokens.d.ts +47 -0
  79. package/dist/tokens.js +141 -0
  80. package/dist/tokens.js.map +1 -0
  81. package/package.json +61 -0
@@ -0,0 +1,538 @@
1
+ /**
2
+ * fetcher/http.ts — 素のHTTP GET(グローバルfetch)。
3
+ *
4
+ * - UA: 正直に amenbo であることを明示する
5
+ * - J1: エンコーディング検出(Content-Typeヘッダ→metaタグ→encoding-japanese自動判定)
6
+ * - SSRF防止: http(s)以外拒否、DNS解決してprivate/loopback/link-local IPを拒否
7
+ * (リダイレクト先も含めて毎ホップ検証する)。加えてDNS rebinding(TOCTOU)対策として、
8
+ * 実接続時のDNS解決そのものにも検証を組み込む(下記「TOCTOU対策」節参照)
9
+ * - タイムアウト(既定15秒)
10
+ * - M1: レスポンスボディにサイズ上限を設ける(OOM DoS対策。既定値は環境変数で調整可)
11
+ */
12
+ import { lookup as dnsCallbackLookup } from "node:dns";
13
+ import { lookup as dnsLookup } from "node:dns/promises";
14
+ import { isIP } from "node:net";
15
+ // 注意: encoding-japaneseはCJS製で、Node ESMのcjs-module-lexerによる named export静的解析が
16
+ // この実装(module.exports = {...}を後段で組み立てる形)を検出できない。
17
+ // `import * as Encoding` はNode実行時にconvert/detectがundefinedになる実バグを踏むため、
18
+ // 常に真の module.exports を指すdefault importを使う(vitestは緩いCJS interopのため
19
+ // namespace importでも動いてしまい、この不整合はユニットテストでは検出できなかった)。
20
+ import Encoding from "encoding-japanese";
21
+ import { Agent as UndiciAgent } from "undici";
22
+ import { AmenboError, FetchTimeoutError, HttpStatusError, InvalidUrlError, NetworkError, PayloadTooLargeError, PrivateAddressError } from "../errors.js";
23
+ export const USER_AGENT = "amenbo/0.1 (+https://github.com/Rererr/amenbo)";
24
+ const DEFAULT_TIMEOUT_MS = 15_000;
25
+ const MAX_REDIRECTS = 5;
26
+ const META_SNIFF_BYTES = 2048;
27
+ // ---- SSRF防止: private/loopback/link-local等の予約アドレス判定 ----
28
+ function ipv4ToInt(ip) {
29
+ const parts = ip.split(".").map((p) => Number(p));
30
+ return (((parts[0] ?? 0) << 24) | ((parts[1] ?? 0) << 16) | ((parts[2] ?? 0) << 8) | (parts[3] ?? 0)) >>> 0;
31
+ }
32
+ const IPV4_RESERVED_RANGES = [
33
+ ["0.0.0.0", 8], // "この"ネットワーク
34
+ ["10.0.0.0", 8], // プライベート
35
+ ["100.64.0.0", 10], // CGNAT
36
+ ["127.0.0.0", 8], // ループバック
37
+ ["169.254.0.0", 16], // リンクローカル
38
+ ["172.16.0.0", 12], // プライベート
39
+ ["192.0.0.0", 24], // IETFプロトコル割当
40
+ ["192.0.2.0", 24], // TEST-NET-1
41
+ ["192.168.0.0", 16], // プライベート
42
+ ["198.18.0.0", 15], // ベンチマーク
43
+ ["198.51.100.0", 24], // TEST-NET-2
44
+ ["203.0.113.0", 24], // TEST-NET-3
45
+ ["224.0.0.0", 4], // マルチキャスト
46
+ ["240.0.0.0", 4], // 予約/ブロードキャスト
47
+ ];
48
+ function isPrivateIpv4(ip) {
49
+ const n = ipv4ToInt(ip);
50
+ return IPV4_RESERVED_RANGES.some(([base, prefix]) => {
51
+ const mask = prefix === 0 ? 0 : (~0 << (32 - prefix)) >>> 0;
52
+ return (n & mask) === (ipv4ToInt(base) & mask);
53
+ });
54
+ }
55
+ /** IPv6アドレス文字列を128bit整数(BigInt)へ変換する(IPv4-mapped表記にも対応)。 */
56
+ function ipv6ToBigInt(ip) {
57
+ const clean = (ip.split("%")[0] ?? ip).toLowerCase();
58
+ const expand = (parts) => parts.flatMap((part) => {
59
+ if (!part.includes("."))
60
+ return [part];
61
+ const octets = part.split(".").map(Number);
62
+ const hi = (((octets[0] ?? 0) << 8) | (octets[1] ?? 0)).toString(16);
63
+ const lo = (((octets[2] ?? 0) << 8) | (octets[3] ?? 0)).toString(16);
64
+ return [hi, lo];
65
+ });
66
+ let headStr = clean;
67
+ let tailStr = "";
68
+ const doubleColonIndex = clean.indexOf("::");
69
+ if (doubleColonIndex !== -1) {
70
+ headStr = clean.slice(0, doubleColonIndex);
71
+ tailStr = clean.slice(doubleColonIndex + 2);
72
+ }
73
+ const headParts = expand(headStr ? headStr.split(":") : []);
74
+ const tailParts = expand(tailStr ? tailStr.split(":") : []);
75
+ const missing = 8 - headParts.length - tailParts.length;
76
+ const fullParts = [...headParts, ...Array(Math.max(missing, 0)).fill("0"), ...tailParts];
77
+ let result = 0n;
78
+ for (const part of fullParts) {
79
+ result = (result << 16n) | BigInt(parseInt(part || "0", 16));
80
+ }
81
+ return result;
82
+ }
83
+ function isInIpv6Range(n, baseHex, prefixBits) {
84
+ const base = ipv6ToBigInt(baseHex);
85
+ const shift = 128n - BigInt(prefixBits);
86
+ return n >> shift === base >> shift;
87
+ }
88
+ function isPrivateIpv6(ip) {
89
+ const n = ipv6ToBigInt(ip);
90
+ if (n === 0n || n === 1n)
91
+ return true; // :: (未指定) / ::1 (ループバック)
92
+ if (isInIpv6Range(n, "fc00::", 7))
93
+ return true; // ユニークローカル
94
+ if (isInIpv6Range(n, "fe80::", 10))
95
+ return true; // リンクローカル
96
+ if (isInIpv6Range(n, "::ffff:0:0", 96)) {
97
+ // IPv4-mapped IPv6: 埋め込みIPv4側を再判定する
98
+ const v4 = [Number((n >> 24n) & 0xffn), Number((n >> 16n) & 0xffn), Number((n >> 8n) & 0xffn), Number(n & 0xffn)].join(".");
99
+ return isPrivateIpv4(v4);
100
+ }
101
+ return false;
102
+ }
103
+ /** IPアドレス(v4/v6)がprivate/loopback/link-local等の予約アドレスかどうか判定する。 */
104
+ export function isPrivateOrReservedIp(ip) {
105
+ const version = isIP(ip);
106
+ if (version === 4)
107
+ return isPrivateIpv4(ip);
108
+ if (version === 6)
109
+ return isPrivateIpv6(ip);
110
+ return true; // 判定不能なものは安全側(拒否)に倒す
111
+ }
112
+ /**
113
+ * URLがhttp(s)スキームかどうかだけを検証する軽量チェック(DNS解決は行わない)。
114
+ *
115
+ * server.ts(fetch/screenshotツール)・links.tsの各エントリポイントで、
116
+ * politeness.guard(robots.txt取得)やブラウザ起動より前に最初に呼ぶことを想定している。
117
+ * これを怠ると、例えば file:// のようなURLに対して politeness 側が
118
+ * `new URL(url).origin` (file:等では "null" になる)から不正なrobots URL
119
+ * (`null/robots.txt`)を組み立ててしまい、guardPublicAddress内の `new URL()` が
120
+ * 生のTypeErrorを投げてスタックトレースがstderrに漏れる問題があった(公開品質バグ)。
121
+ */
122
+ export function assertHttpScheme(urlStr) {
123
+ const url = new URL(urlStr);
124
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
125
+ throw new InvalidUrlError(urlStr, `サポート対象外のスキームです: ${url.protocol}`);
126
+ }
127
+ return url;
128
+ }
129
+ /**
130
+ * URLのホストを解決し、private/予約アドレスであれば拒否する(SSRF対策)。
131
+ * http(s)以外のスキーム(file:等)も拒否する。
132
+ *
133
+ * fetcher/browser.ts・screenshot.tsのPlaywrightナビゲーション(page.goto前・
134
+ * リダイレクト再検証)からも共通利用する(C1: screenshot/browser層がSSRF/スキーム
135
+ * 検証を経由していなかった問題への対応)。
136
+ *
137
+ * 注意(TOCTOU): この関数の検証と実際の接続(fetch/ブラウザのTCP接続)は別のDNS解決を
138
+ * 行うため、その間にDNS rebindingが起きると理論上すり抜けうる。httpGet/httpGetBinaryの
139
+ * 実接続については下記「TOCTOU対策」のssrfSafeLookupで接続時点そのものを検証しており、
140
+ * この関数はスキーム検証と早期の分かりやすいエラーメッセージのための一次防御にあたる。
141
+ */
142
+ export async function guardPublicAddress(urlStr) {
143
+ const url = assertHttpScheme(urlStr);
144
+ const hostname = url.hostname.replace(/^\[|\]$/g, "");
145
+ const literalVersion = isIP(hostname);
146
+ let addresses;
147
+ if (literalVersion) {
148
+ addresses = [hostname];
149
+ }
150
+ else {
151
+ try {
152
+ addresses = (await dnsLookup(hostname, { all: true })).map((entry) => entry.address);
153
+ }
154
+ catch (cause) {
155
+ // CLI併設対応で発覚した既存の穴: この関数はguardedFetch(実fetch呼び出し)より前段で
156
+ // 呼ばれるため、DNS解決失敗(ENOTFOUND等)がここで起きると生のNode dnsエラーが
157
+ // AmenboErrorでラップされないまま上位へ素通りしていた(呼び出し元のcatchが
158
+ // `error instanceof AmenboError`で分岐しているため、スタックトレース付きでstderrに
159
+ // 漏れる/CLIがexit code 1で握り潰さず処理する、という設計が機能しない)。
160
+ // guardedFetch内のfetch()自体のDNS失敗と同じ分類(NetworkError.fromCause)に揃える。
161
+ throw NetworkError.fromCause(urlStr, cause);
162
+ }
163
+ }
164
+ for (const address of addresses) {
165
+ if (isPrivateOrReservedIp(address)) {
166
+ throw new PrivateAddressError(urlStr, address);
167
+ }
168
+ }
169
+ }
170
+ // ---- C2: TOCTOU対策(DNS rebinding) ----
171
+ //
172
+ // guardPublicAddressによる事前検証と実際の接続は別々のDNS解決になるため、検証直後に
173
+ // DNSレコードが private IP へ書き換わる(rebinding)と素通りしうる。これを塞ぐため、
174
+ // 実接続の名前解決そのものに検証を組み込んだundici Agentを作り、fetch()のdispatcherとして
175
+ // 渡す。検証で使ったIPアドレスへそのまま接続する(Host/SNIは元のホスト名のまま undici が
176
+ // 設定するため変わらない)ので、検証時点と接続時点のアドレスが必ず一致する。
177
+ /**
178
+ * undiciのconnect.lookupはnet.connectと同様、呼び出し元がoptions.all=trueを渡した場合
179
+ * `(err, addresses[])` 形式でコールバックする実装になっているが、Node公式の
180
+ * `LookupFunction` 型定義はこの挙動をカバーしていない(上流の型定義の既知の制限)。
181
+ * 実行時の挙動に合わせて型アサーションで対応する。
182
+ */
183
+ const ssrfSafeLookup = (hostname, options, callback) => {
184
+ dnsCallbackLookup(hostname, { all: true }, (err, addresses) => {
185
+ if (err) {
186
+ callback(err, "", 0);
187
+ return;
188
+ }
189
+ const safeAddresses = addresses.filter((entry) => !isPrivateOrReservedIp(entry.address));
190
+ if (safeAddresses.length === 0) {
191
+ const blockedAddress = addresses[0]?.address ?? hostname;
192
+ callback(new PrivateAddressError(hostname, blockedAddress), "", 0);
193
+ return;
194
+ }
195
+ const wantsAll = options?.all === true;
196
+ if (wantsAll) {
197
+ callback(null, safeAddresses);
198
+ return;
199
+ }
200
+ const [first] = safeAddresses;
201
+ callback(null, first.address, first.family);
202
+ });
203
+ };
204
+ let ssrfSafeDispatcher = null;
205
+ /** httpGet/httpGetBinaryのfetch()に渡す、接続時点でSSRF検証を行うdispatcher(遅延生成・使い回し)。 */
206
+ function getSsrfSafeDispatcher() {
207
+ ssrfSafeDispatcher ??= new UndiciAgent({ connect: { lookup: ssrfSafeLookup } });
208
+ return ssrfSafeDispatcher;
209
+ }
210
+ /**
211
+ * fetch失敗時、原因チェーン(.cause)を辿ってssrfSafeLookupが投げたPrivateAddressErrorを探す。
212
+ * undiciはconnector由来のエラーを `TypeError: fetch failed` でラップして投げるため、
213
+ * そのままでは型情報が失われ、呼び出し側が「SSRFで拒否された」と判別できなくなる。
214
+ */
215
+ function findPrivateAddressError(error) {
216
+ let current = error;
217
+ for (let depth = 0; depth < 5 && current instanceof Error; depth++) {
218
+ if (current instanceof PrivateAddressError)
219
+ return current;
220
+ current = current.cause;
221
+ }
222
+ return undefined;
223
+ }
224
+ const CHARSET_ALIASES = {
225
+ "utf-8": { encoding: "UTF8", displayName: "UTF-8" },
226
+ utf8: { encoding: "UTF8", displayName: "UTF-8" },
227
+ shift_jis: { encoding: "SJIS", displayName: "Shift_JIS" },
228
+ "shift-jis": { encoding: "SJIS", displayName: "Shift_JIS" },
229
+ sjis: { encoding: "SJIS", displayName: "Shift_JIS" },
230
+ "x-sjis": { encoding: "SJIS", displayName: "Shift_JIS" },
231
+ "windows-31j": { encoding: "SJIS", displayName: "Shift_JIS" },
232
+ cp932: { encoding: "SJIS", displayName: "Shift_JIS" },
233
+ ms932: { encoding: "SJIS", displayName: "Shift_JIS" },
234
+ "euc-jp": { encoding: "EUCJP", displayName: "EUC-JP" },
235
+ eucjp: { encoding: "EUCJP", displayName: "EUC-JP" },
236
+ "x-euc-jp": { encoding: "EUCJP", displayName: "EUC-JP" },
237
+ "iso-2022-jp": { encoding: "JIS", displayName: "ISO-2022-JP" },
238
+ iso2022jp: { encoding: "JIS", displayName: "ISO-2022-JP" },
239
+ };
240
+ const AUTO_DETECT_DISPLAY_NAME = {
241
+ SJIS: "Shift_JIS",
242
+ EUCJP: "EUC-JP",
243
+ JIS: "ISO-2022-JP",
244
+ };
245
+ function charsetFromContentType(contentType) {
246
+ if (!contentType)
247
+ return null;
248
+ const match = /charset\s*=\s*"?([\w-]+)"?/i.exec(contentType);
249
+ return match?.[1] ?? null;
250
+ }
251
+ function charsetFromMetaTag(bytes) {
252
+ // 先頭バイト列をASCII安全なlatin1として読み、metaタグの宣言を探す(この段階では文字化けしても問題ない)
253
+ const head = Buffer.from(bytes.subarray(0, META_SNIFF_BYTES)).toString("latin1");
254
+ const metaCharset = /<meta[^>]+charset\s*=\s*["']?([\w-]+)/i.exec(head);
255
+ if (metaCharset?.[1])
256
+ return metaCharset[1];
257
+ const httpEquiv = /<meta[^>]+http-equiv=["']?content-type["'][^>]*content=["'][^"']*charset=([\w-]+)/i.exec(head);
258
+ return httpEquiv?.[1] ?? null;
259
+ }
260
+ function decodeWithEncoding(bytes, encoding) {
261
+ if (encoding === "UTF8")
262
+ return new TextDecoder("utf-8").decode(bytes);
263
+ const codes = Encoding.convert(bytes, "UNICODE", encoding);
264
+ return Encoding.codeToString(codes);
265
+ }
266
+ /** J1: Content-Typeヘッダ→metaタグ→encoding-japanese自動判定の順でHTMLをデコードする。 */
267
+ export function decodeHtmlBytes(bytes, contentTypeHeader) {
268
+ const declaredCharset = charsetFromContentType(contentTypeHeader) ?? charsetFromMetaTag(bytes);
269
+ const declared = declaredCharset ? CHARSET_ALIASES[declaredCharset.toLowerCase()] : undefined;
270
+ if (declared) {
271
+ return { text: decodeWithEncoding(bytes, declared.encoding), encoding: declared.displayName };
272
+ }
273
+ const detected = Encoding.detect(bytes);
274
+ if (detected === "SJIS" || detected === "EUCJP" || detected === "JIS") {
275
+ return { text: decodeWithEncoding(bytes, detected), encoding: AUTO_DETECT_DISPLAY_NAME[detected] };
276
+ }
277
+ return { text: new TextDecoder("utf-8").decode(bytes), encoding: "UTF-8" };
278
+ }
279
+ // ---- M1: レスポンスボディのサイズ上限(OOM DoS対策) ----
280
+ const DEFAULT_MAX_BODY_BYTES = 20 * 1024 * 1024; // 20MB
281
+ /** 環境変数 AMENBO_MAX_BODY_BYTES で既定のボディサイズ上限を調整できる。 */
282
+ export function resolveDefaultMaxBodyBytes() {
283
+ const raw = process.env.AMENBO_MAX_BODY_BYTES;
284
+ if (!raw)
285
+ return DEFAULT_MAX_BODY_BYTES;
286
+ const parsed = Number(raw);
287
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_BODY_BYTES;
288
+ }
289
+ /**
290
+ * レスポンスボディをmaxBytes上限付きで読み切る。
291
+ * Content-Lengthヘッダでの事前チェックに加え、ヘッダ詐称・chunked転送対策として
292
+ * ストリーミング中の実受信バイト数も逐次チェックする(超過時点で読み取りを打ち切る)。
293
+ */
294
+ async function readBodyWithLimit(response, url, maxBytes) {
295
+ const declaredLength = response.headers.get("content-length");
296
+ if (declaredLength && Number(declaredLength) > maxBytes) {
297
+ throw new PayloadTooLargeError(url, Number(declaredLength), maxBytes);
298
+ }
299
+ // 機能A(実機検証での追加修正): ヘッダ受信後のストリーミング読み取り中に接続断等が起きた場合、
300
+ // 生のエラーを素通りさせずNetworkErrorへ分類する(意図的に投げているPayloadTooLargeError等の
301
+ // AmenboErrorはそのまま再送出する)。
302
+ try {
303
+ if (!response.body) {
304
+ const buffer = new Uint8Array(await response.arrayBuffer());
305
+ if (buffer.length > maxBytes) {
306
+ throw new PayloadTooLargeError(url, buffer.length, maxBytes);
307
+ }
308
+ return buffer;
309
+ }
310
+ const reader = response.body.getReader();
311
+ const chunks = [];
312
+ let total = 0;
313
+ for (;;) {
314
+ const { done, value } = await reader.read();
315
+ if (done)
316
+ break;
317
+ if (!value)
318
+ continue;
319
+ total += value.length;
320
+ if (total > maxBytes) {
321
+ await reader.cancel().catch(() => { });
322
+ throw new PayloadTooLargeError(url, total, maxBytes);
323
+ }
324
+ chunks.push(value);
325
+ }
326
+ const result = new Uint8Array(total);
327
+ let offset = 0;
328
+ for (const chunk of chunks) {
329
+ result.set(chunk, offset);
330
+ offset += chunk.length;
331
+ }
332
+ return result;
333
+ }
334
+ catch (error) {
335
+ if (error instanceof AmenboError)
336
+ throw error;
337
+ throw NetworkError.fromCause(url, error);
338
+ }
339
+ }
340
+ /**
341
+ * SSRF対策付きの手動リダイレクト追跡fetch。httpGet/httpGetBinaryの共通部分。
342
+ * 呼び出し側がstatus 304/非2xxの扱いとボディの読み方(テキスト/バイナリ)を決める。
343
+ */
344
+ async function guardedFetch(url, options, controller) {
345
+ let currentUrl = url;
346
+ for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {
347
+ await guardPublicAddress(currentUrl);
348
+ let response;
349
+ try {
350
+ response = await fetch(currentUrl, {
351
+ method: "GET",
352
+ redirect: "manual",
353
+ signal: controller.signal,
354
+ headers: { "User-Agent": USER_AGENT, ...options.headers },
355
+ // C2: 事前検証(guardPublicAddress)とは別に、実接続の名前解決そのものを検証する
356
+ // dispatcherを使う(DNS rebindingのTOCTOU対策)。
357
+ dispatcher: getSsrfSafeDispatcher(),
358
+ });
359
+ }
360
+ catch (cause) {
361
+ const privateAddressError = findPrivateAddressError(cause);
362
+ if (privateAddressError) {
363
+ throw privateAddressError;
364
+ }
365
+ if (controller.signal.aborted) {
366
+ throw new FetchTimeoutError(url, options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
367
+ }
368
+ // 機能A: undiciのcauseチェーン(error.cause.code等)からdns/tls/connection/unknownを
369
+ // 分類した型付きエラーにして投げる(以前は生の"TypeError: fetch failed"が素通りしていた)。
370
+ throw NetworkError.fromCause(currentUrl, cause);
371
+ }
372
+ // 304 (Not Modified) は300-399の数値レンジに含まれるが、リダイレクトではなく
373
+ // 条件付きGETの再検証結果であり、Locationヘッダを伴わない。ここで先に除外しないと
374
+ // 「Locationヘッダの無いリダイレクト」として誤ってHttpStatusErrorになってしまう。
375
+ if (response.status >= 300 && response.status < 400 && response.status !== 304) {
376
+ const location = response.headers.get("location");
377
+ if (!location) {
378
+ throw new HttpStatusError(currentUrl, response.status, response.statusText);
379
+ }
380
+ // N3: Locationヘッダが不正な形式の場合、new URL()の生例外ではなく型付きエラーにする
381
+ let nextUrl;
382
+ try {
383
+ nextUrl = new URL(location, currentUrl);
384
+ }
385
+ catch {
386
+ throw new InvalidUrlError(location, "リダイレクト先URLの形式が不正です");
387
+ }
388
+ currentUrl = nextUrl.toString();
389
+ continue;
390
+ }
391
+ return { finalUrl: currentUrl, response };
392
+ }
393
+ throw new HttpStatusError(url, 310, "Too Many Redirects");
394
+ }
395
+ /**
396
+ * SSRF対策付きの素のHTTP GET(テキスト/HTML用)。リダイレクトは手動で追跡し、毎ホップでSSRFガードを行う。
397
+ * status 304(未変更)はエラーにせずそのまま返す(キャッシュ再検証用)。
398
+ * 200以外(304を除く)の非2xxはHttpStatusErrorを投げる。
399
+ */
400
+ export async function httpGet(url, options = {}) {
401
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
402
+ const controller = new AbortController();
403
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
404
+ try {
405
+ const { finalUrl, response } = await guardedFetch(url, options, controller);
406
+ if (response.status === 304) {
407
+ return { finalUrl, status: 304, headers: response.headers, html: "", encoding: "" };
408
+ }
409
+ if (!response.ok) {
410
+ throw new HttpStatusError(finalUrl, response.status, response.statusText);
411
+ }
412
+ const buffer = await readBodyWithLimit(response, finalUrl, options.maxBytes ?? resolveDefaultMaxBodyBytes());
413
+ const decoded = decodeHtmlBytes(buffer, response.headers.get("content-type"));
414
+ return {
415
+ finalUrl,
416
+ status: response.status,
417
+ headers: response.headers,
418
+ html: decoded.text,
419
+ encoding: decoded.encoding,
420
+ };
421
+ }
422
+ finally {
423
+ clearTimeout(timer);
424
+ }
425
+ }
426
+ /**
427
+ * SSRF対策付きの素のHTTP GET(バイナリ用、PDF等)。デコードせずバイト列のまま返す。
428
+ * Content-Lengthヘッダ・実バイト数の両方でmaxBytesを検証する(ヘッダ詐称対策として実サイズも確認)。
429
+ * status 304(未変更)はhttpGetと同様エラーにせずそのまま返す(条件付きGETを行う将来の呼び出し元向け)。
430
+ */
431
+ export async function httpGetBinary(url, options = {}) {
432
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
433
+ const controller = new AbortController();
434
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
435
+ try {
436
+ const { finalUrl, response } = await guardedFetch(url, options, controller);
437
+ if (response.status === 304) {
438
+ return { finalUrl, status: 304, headers: response.headers, bytes: new Uint8Array(0), contentType: null };
439
+ }
440
+ if (!response.ok) {
441
+ throw new HttpStatusError(finalUrl, response.status, response.statusText);
442
+ }
443
+ const bytes = await readBodyWithLimit(response, finalUrl, options.maxBytes ?? resolveDefaultMaxBodyBytes());
444
+ return { finalUrl, status: response.status, headers: response.headers, bytes, contentType: response.headers.get("content-type") };
445
+ }
446
+ finally {
447
+ clearTimeout(timer);
448
+ }
449
+ }
450
+ // ---- 機能B: 非HTMLコンテンツのハンドオフ応答用ルーティング ----
451
+ const HTML_CONTENT_TYPE_RE = /text\/html|application\/xhtml\+xml/i;
452
+ /**
453
+ * ハンドオフ応答のプレビュー用に読み取るボディの上限(バイト)。CSV/JSON等のプレビュー
454
+ * (ヘッダ+先頭数行、または既定max_tokens相当のテキスト)には十分な量である一方、
455
+ * 数百MB〜GB級のオープンデータファイルの全体取得は避ける(politeness優先)。
456
+ */
457
+ const HANDOFF_PREVIEW_BYTES = 256 * 1024; // 256KB
458
+ /**
459
+ * readBodyWithLimitと異なり上限超過をエラーにせず「truncated」として扱う
460
+ * (機能B: 非HTMLコンテンツのプレビュー用。ボディ全体は取得せず必要な分だけ読んで切断する)。
461
+ */
462
+ async function readBodyPreview(response, url, maxBytes) {
463
+ // 機能A(実機検証での追加修正): 読み取り中の接続断等をNetworkErrorへ分類する(readBodyWithLimitと同様)。
464
+ try {
465
+ if (!response.body) {
466
+ const buffer = new Uint8Array(await response.arrayBuffer());
467
+ if (buffer.length <= maxBytes)
468
+ return { bytes: buffer, truncated: false };
469
+ return { bytes: buffer.subarray(0, maxBytes), truncated: true };
470
+ }
471
+ const reader = response.body.getReader();
472
+ const chunks = [];
473
+ let total = 0;
474
+ let truncated = false;
475
+ for (;;) {
476
+ const { done, value } = await reader.read();
477
+ if (done)
478
+ break;
479
+ if (!value)
480
+ continue;
481
+ if (total + value.length > maxBytes) {
482
+ chunks.push(value.subarray(0, maxBytes - total));
483
+ total = maxBytes;
484
+ truncated = true;
485
+ await reader.cancel().catch(() => { });
486
+ break;
487
+ }
488
+ chunks.push(value);
489
+ total += value.length;
490
+ }
491
+ const result = new Uint8Array(total);
492
+ let offset = 0;
493
+ for (const chunk of chunks) {
494
+ result.set(chunk, offset);
495
+ offset += chunk.length;
496
+ }
497
+ return { bytes: result, truncated };
498
+ }
499
+ catch (error) {
500
+ if (error instanceof AmenboError)
501
+ throw error;
502
+ throw NetworkError.fromCause(url, error);
503
+ }
504
+ }
505
+ /**
506
+ * 機能B: content-typeを見て、HTML本文の全体読み取り(既存のhttpGetと同じ挙動)か、
507
+ * 非HTMLハンドオフ用のプレビュー読み取り(既定256KBで打ち切り)かを1回のfetchで振り分ける。
508
+ * リダイレクト先を含め毎ホップでcontent-typeが確定するのは最終応答のみなので、
509
+ * guardedFetchで得たヘッダを見てから初めてボディの読み方を決める。
510
+ */
511
+ export async function httpGetRouted(url, options = {}) {
512
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
513
+ const controller = new AbortController();
514
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
515
+ try {
516
+ const { finalUrl, response } = await guardedFetch(url, options, controller);
517
+ if (response.status === 304) {
518
+ return { kind: "notModified", status: 304, finalUrl, headers: response.headers };
519
+ }
520
+ if (!response.ok) {
521
+ throw new HttpStatusError(finalUrl, response.status, response.statusText);
522
+ }
523
+ const contentType = response.headers.get("content-type");
524
+ if (!contentType || HTML_CONTENT_TYPE_RE.test(contentType)) {
525
+ const buffer = await readBodyWithLimit(response, finalUrl, options.maxBytes ?? resolveDefaultMaxBodyBytes());
526
+ const decoded = decodeHtmlBytes(buffer, contentType);
527
+ return { kind: "html", status: response.status, finalUrl, headers: response.headers, html: decoded.text, encoding: decoded.encoding };
528
+ }
529
+ const declaredLengthHeader = response.headers.get("content-length");
530
+ const declaredSize = declaredLengthHeader && Number.isFinite(Number(declaredLengthHeader)) ? Number(declaredLengthHeader) : null;
531
+ const { bytes, truncated } = await readBodyPreview(response, finalUrl, HANDOFF_PREVIEW_BYTES);
532
+ return { kind: "handoff", status: response.status, finalUrl, headers: response.headers, contentType, bytes, declaredSize, truncated };
533
+ }
534
+ finally {
535
+ clearTimeout(timer);
536
+ }
537
+ }
538
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/fetcher/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { PageGeometrySnapshot } from "../extract/geometry.js";
2
+ import { type HttpGetOptions } from "./http.js";
3
+ export type FetchTier = "http" | "browser";
4
+ export interface FetchResult {
5
+ finalUrl: string;
6
+ html: string;
7
+ tier: FetchTier;
8
+ status: number;
9
+ /** HTTP tierのみ有効な値(ブラウザ tier はレンダリング結果がUTF-8文字列として得られるため常にUTF-8)。 */
10
+ encoding: string;
11
+ /** キャッシュ再検証用のバリデータ(HTTP tierのみ)。 */
12
+ etag: string | null;
13
+ lastModified: string | null;
14
+ /** SPA判定でブラウザへ昇格した場合、その理由。 */
15
+ escalationReason: string | null;
16
+ /** Phase 4 ジオメトリ抽出用データ。browser tierのみ非null。 */
17
+ geometry: PageGeometrySnapshot | null;
18
+ }
19
+ export interface NotModifiedResult {
20
+ notModified: true;
21
+ finalUrl: string;
22
+ }
23
+ /** 機能B: HTML/PDF以外のコンテンツタイプのハンドオフ応答用データ(メタデータ+プレビュー用バイト列)。 */
24
+ export interface HandoffResult {
25
+ handoff: true;
26
+ finalUrl: string;
27
+ status: number;
28
+ contentType: string | null;
29
+ /** プレビュー用に読み取ったボディ(既定256KB上限。ファイル全体ではない)。 */
30
+ bytes: Uint8Array;
31
+ /** Content-Lengthヘッダ由来の宣言サイズ(無ければnull)。 */
32
+ declaredSize: number | null;
33
+ /** プレビュー上限で本文を打ち切った場合true(ファイル全体は取得していない)。 */
34
+ truncated: boolean;
35
+ }
36
+ export interface FetchPageOptions extends HttpGetOptions {
37
+ /** trueの場合、SPA判定を行わず常にブラウザで取得する(将来のmode指定等で利用)。 */
38
+ forceBrowser?: boolean;
39
+ }
40
+ /** 二段フェッチ本体。条件付きGETでstatus 304が返った場合はNotModifiedResultを返す。 */
41
+ export declare function fetchPage(url: string, options?: FetchPageOptions): Promise<FetchResult | NotModifiedResult | HandoffResult>;