@yanglaofish/fishtools 0.5.2 → 0.6.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/README.md +24 -12
- package/manual/README.md +24 -12
- package/manual/docs/deployment.md +3 -3
- package/manual/docs/examples/action-plugin/package.json +1 -1
- package/manual/docs/modules.md +2 -0
- package/manual/docs/plans/2026-10-13-effective-inputs-and-tables.md +39 -0
- package/manual/docs/plans/2026-10-13-plugin-defaults.md +45 -0
- package/manual/docs/plans/2026-10-14-issue7-recovery.md +33 -0
- package/manual/docs/plans/2026-10-14-issue8-10-workflows.md +26 -0
- package/manual/docs/plans/2026-10-14-issue9-completion.md +47 -0
- package/manual/docs/plans/2026-10-14-managed-execution.md +58 -0
- package/manual/docs/plans/2026-10-14-plugin-discovery-history.md +41 -0
- package/manual/docs/plans/2026-10-14-structured-reports.md +77 -0
- package/manual/docs/plans/2026-10-14-unreleased-review.md +47 -0
- package/manual/docs/plugin-development.md +175 -11
- package/manual/docs/releases.md +49 -6
- package/manual/docs/superpowers/plans/2026-10-13-command-shortcuts.md +3 -2
- package/manual/docs/superpowers/plans/2026-10-13-global-plugins.md +56 -0
- package/manual/docs/superpowers/plans/2026-10-13-tui-readable-sessions.md +21 -0
- package/manual/docs/superpowers/reviews/2026-10-13-0.5.3-review.md +28 -0
- package/manual/docs/superpowers/reviews/2026-10-13-command-shortcuts-review.md +7 -0
- package/manual/docs/superpowers/reviews/2026-10-13-tui-sessions-review.md +57 -0
- package/manual/docs/superpowers/reviews/2026-10-14-0.6.0-release-review.md +19 -0
- package/manual/docs/superpowers/specs/2026-10-13-issue-4-workflow-menu.md +23 -0
- package/manual/docs/superpowers/specs/2026-10-13-issue-5-results-and-history.md +20 -0
- package/manual/docs/terminal-commands.md +8 -0
- package/manual/docs/verification.md +47 -0
- package/manual/packages/core/README.md +8 -0
- package/manual/packages/core/package.json +1 -1
- package/manual/packages/core/src/application.js +108 -53
- package/manual/packages/core/src/development-watch-worker.js +10 -1
- package/manual/packages/core/src/development.js +1 -1
- package/manual/packages/core/src/plugin-catalog.js +60 -0
- package/manual/packages/core/src/plugin-loading.js +24 -0
- package/manual/packages/core/src/version.js +1 -1
- package/manual/packages/fst-cli/README.md +8 -0
- package/manual/packages/fst-cli/bin/fst.js +7 -6
- package/manual/packages/fst-cli/package.json +1 -1
- package/manual/packages/fst-cli/src/development.js +6 -1
- package/manual/packages/fst-cli/src/terminal/command-menu.js +11 -5
- package/manual/packages/fst-cli/src/terminal/file-autocomplete.js +106 -0
- package/manual/packages/fst-cli/src/terminal/log-viewer.js +4 -3
- package/manual/packages/fst-cli/src/terminal/navigation.js +25 -1
- package/manual/packages/fst-cli/src/terminal/presentation.js +5 -3
- package/manual/packages/fst-cli/src/terminal/report-presentation.js +38 -0
- package/manual/packages/fst-cli/src/terminal/result-table.js +66 -0
- package/manual/packages/fst-cli/src/terminal/run-feed.js +104 -23
- package/manual/packages/fst-cli/src/terminal/run-presentation.js +91 -14
- package/manual/packages/fst-cli/src/terminal/run-viewer.js +34 -15
- package/manual/packages/fst-cli/src/terminal/schema.js +114 -4
- package/manual/packages/fst-cli/src/terminal/session-history.js +82 -0
- package/manual/packages/fst-cli/src/terminal/session.js +158 -54
- package/manual/packages/fst-cli/src/terminal/view.js +108 -73
- package/manual/packages/fst-cli/src/terminal/workflow-menu.js +17 -10
- package/manual/packages/fst-devtools/README.md +2 -0
- package/manual/packages/fst-devtools/package.json +2 -2
- package/manual/packages/fst-devtools/src/plugin-quality.js +4 -1
- package/manual/packages/fst-devtools/src/plugin-tools.js +2 -1
- package/manual/packages/fst-devtools/src/process-usage.js +62 -0
- package/manual/packages/fst-logs/README.md +23 -2
- package/manual/packages/fst-logs/package.json +2 -1
- package/manual/packages/fst-logs/src/file-identity.js +23 -0
- package/manual/packages/fst-logs/src/markdown-log.js +4 -3
- package/manual/packages/fst-logs/src/run-logs.js +3 -2
- package/manual/packages/fst-logs/src/session-history.js +180 -0
- package/manual/packages/fst-platform/README.md +9 -0
- package/manual/packages/fst-platform/package.json +4 -3
- package/manual/packages/fst-platform/src/managed-process.js +36 -0
- package/manual/packages/fst-platform/src/process.js +11 -3
- package/manual/packages/fst-platform/src/shell.js +46 -1
- package/manual/packages/fst-plugin/README.md +4 -0
- package/manual/packages/fst-plugin/package.json +1 -1
- package/manual/packages/fst-plugin/src/contracts.js +3 -0
- package/manual/packages/fst-plugin/src/host.js +54 -31
- package/manual/packages/fst-plugin/src/runtime.js +14 -8
- package/manual/packages/fst-workflow/package.json +1 -1
- package/manual/packages/fst-workflow/src/engine.js +1 -1
- package/manual/packages/fst-workspace/README.md +6 -0
- package/manual/packages/fst-workspace/package.json +2 -1
- package/manual/packages/fst-workspace/src/plugin-registry.js +58 -0
- package/manual/packages/fst-workspace/src/plugins.js +10 -5
- package/manual/packages/fst-workspace/src/workflows.js +32 -12
- package/manual/packages/pack/package.json +3 -3
- package/manual/packages/pack/runtime-cache.js +26 -0
- package/manual/packages/pack/runtime.js +6 -10
- package/manual/packages/sdk/README.md +10 -0
- package/manual/packages/sdk/inputs.js +53 -0
- package/manual/packages/sdk/package.json +2 -0
- package/manual/packages/sdk/reports.js +53 -0
- package/manual/plugins/commands/package.json +1 -1
- package/node_modules/@mytools/commands/package.json +1 -1
- package/node_modules/@mytools/core/README.md +8 -0
- package/node_modules/@mytools/core/package.json +1 -1
- package/node_modules/@mytools/core/src/application.js +108 -53
- package/node_modules/@mytools/core/src/development-watch-worker.js +10 -1
- package/node_modules/@mytools/core/src/development.js +1 -1
- package/node_modules/@mytools/core/src/plugin-catalog.js +60 -0
- package/node_modules/@mytools/core/src/plugin-loading.js +24 -0
- package/node_modules/@mytools/core/src/version.js +1 -1
- package/node_modules/@mytools/fst-cli/README.md +8 -0
- package/node_modules/@mytools/fst-cli/bin/fst.js +7 -6
- package/node_modules/@mytools/fst-cli/package.json +1 -1
- package/node_modules/@mytools/fst-cli/src/development.js +6 -1
- package/node_modules/@mytools/fst-cli/src/terminal/command-menu.js +11 -5
- package/node_modules/@mytools/fst-cli/src/terminal/file-autocomplete.js +106 -0
- package/node_modules/@mytools/fst-cli/src/terminal/log-viewer.js +4 -3
- package/node_modules/@mytools/fst-cli/src/terminal/navigation.js +25 -1
- package/node_modules/@mytools/fst-cli/src/terminal/presentation.js +5 -3
- package/node_modules/@mytools/fst-cli/src/terminal/report-presentation.js +38 -0
- package/node_modules/@mytools/fst-cli/src/terminal/result-table.js +66 -0
- package/node_modules/@mytools/fst-cli/src/terminal/run-feed.js +104 -23
- package/node_modules/@mytools/fst-cli/src/terminal/run-presentation.js +91 -14
- package/node_modules/@mytools/fst-cli/src/terminal/run-viewer.js +34 -15
- package/node_modules/@mytools/fst-cli/src/terminal/schema.js +114 -4
- package/node_modules/@mytools/fst-cli/src/terminal/session-history.js +82 -0
- package/node_modules/@mytools/fst-cli/src/terminal/session.js +158 -54
- package/node_modules/@mytools/fst-cli/src/terminal/view.js +108 -73
- package/node_modules/@mytools/fst-cli/src/terminal/workflow-menu.js +17 -10
- package/node_modules/@mytools/fst-devtools/README.md +2 -0
- package/node_modules/@mytools/fst-devtools/package.json +2 -2
- package/node_modules/@mytools/fst-devtools/src/plugin-quality.js +4 -1
- package/node_modules/@mytools/fst-devtools/src/plugin-tools.js +2 -1
- package/node_modules/@mytools/fst-devtools/src/process-usage.js +62 -0
- package/node_modules/@mytools/fst-logs/README.md +23 -2
- package/node_modules/@mytools/fst-logs/package.json +2 -1
- package/node_modules/@mytools/fst-logs/src/file-identity.js +23 -0
- package/node_modules/@mytools/fst-logs/src/markdown-log.js +4 -3
- package/node_modules/@mytools/fst-logs/src/run-logs.js +3 -2
- package/node_modules/@mytools/fst-logs/src/session-history.js +180 -0
- package/node_modules/@mytools/fst-platform/README.md +9 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/LICENSE +21 -0
- package/node_modules/{undici/docs/docs/index.md → @mytools/fst-platform/node_modules/undici/README.md} +85 -137
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Agent.md +84 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Client.md +288 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Connector.md +115 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/ContentType.md +57 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Cookies.md +128 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Debug.md +62 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +317 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Dispatcher.md +1393 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Errors.md +49 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/EventSource.md +45 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Fetch.md +60 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/GlobalInstallation.md +139 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/H2CClient.md +263 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockClient.md +81 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/MockPool.md +555 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Pool.md +84 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/ProxyAgent.md +229 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RedirectHandler.md +93 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RetryAgent.md +50 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RetryHandler.md +118 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/RoundRobinPool.md +145 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/SnapshotAgent.md +616 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +275 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/Util.md +25 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/WebSocket.md +141 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/docs/docs/best-practices/crawling.md +1 -3
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/docs/docs/best-practices/undici-vs-builtin-fetch.md +8 -10
- package/node_modules/@mytools/fst-platform/node_modules/undici/docs/docs/best-practices/writing-tests.md +63 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/index-fetch.js +65 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/index.d.ts +3 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/index.js +234 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/abort-signal.js +59 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-connect.js +110 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-pipeline.js +252 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-request.js +214 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-stream.js +209 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/api-upgrade.js +111 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/index.js +7 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/api/readable.js +580 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/cache/memory-cache-store.js +3 -3
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/cache/sqlite-cache-store.js +1 -3
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/connect.js +153 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/constants.js +143 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/diagnostics.js +227 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/errors.js +477 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/request.js +485 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/symbols.js +75 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/tree.js +160 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/core/util.js +992 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/agent.js +158 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/balanced-pool.js +221 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/client-h1.js +1746 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/client-h2.js +1060 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/client.js +668 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/dispatcher-base.js +184 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/dispatcher/h2c-client.js +4 -4
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/pool.js +118 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/proxy-agent.js +319 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/dispatcher/round-robin-pool.js +10 -32
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/dispatcher/socks5-proxy-agent.js +63 -153
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/global.js +59 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/handler/cache-handler.js +7 -49
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/handler/cache-revalidation-handler.js +0 -10
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/decorator-handler.js +67 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/handler/deduplication-handler.js +10 -29
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/redirect-handler.js +238 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/retry-handler.js +504 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/unwrap-handler.js +106 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/handler/wrap-handler.js +105 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/interceptor/cache.js +26 -79
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/interceptor/decompress.js +3 -13
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/interceptor/deduplicate.js +4 -5
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/dns.js +571 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/dump.js +99 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/redirect.js +21 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/response-error.js +95 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/interceptor/retry.js +19 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/.gitkeep +0 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/constants.js +531 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/llhttp/utils.js +12 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-agent.js +232 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/mock-call-history.js +1 -1
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-client.js +68 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-errors.js +29 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-pool.js +68 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-symbols.js +32 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/mock-utils.js +486 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/snapshot-agent.js +7 -25
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/snapshot-recorder.js +3 -38
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/cache.js +10 -92
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/util/promise.js +28 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/runtime-features.js +34 -3
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/util/timers.js +425 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cache/cache.js +864 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cache/util.js +45 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/constants.js +12 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/index.js +199 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/parse.js +314 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/cookies/util.js +352 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/eventsource/eventsource-stream.js +494 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/eventsource/util.js +29 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/LICENSE +21 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/body.js +509 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/constants.js +131 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/data-url.js +596 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/formdata-parser.js +586 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/formdata.js +259 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/global.js +40 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/headers.js +719 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/index.js +2413 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/request.js +1115 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/response.js +641 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/fetch/util.js +1522 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/infra/index.js +1 -16
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/webidl/index.js +21 -7
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/connection.js +339 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/constants.js +126 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/events.js +331 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/frame.js +133 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/permessage-deflate.js +105 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/receiver.js +507 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/sender.js +109 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/websocket/stream/websocketerror.js +10 -13
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/websocket/stream/websocketstream.js +14 -29
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/util.js +347 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/lib/web/websocket/websocket.js +758 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/package.json +152 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/scripts/strip-comments.js +10 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/README.md +6 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/agent.d.ts +32 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/api.d.ts +43 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/balanced-pool.d.ts +30 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/cache.d.ts +36 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/client.d.ts +139 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/connector.d.ts +36 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/content-type.d.ts +21 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/cookies.d.ts +30 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/diagnostics-channel.d.ts +74 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/dispatcher.d.ts +275 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/env-http-proxy-agent.d.ts +22 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/errors.d.ts +177 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/eventsource.d.ts +66 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/fetch.d.ts +231 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/formdata.d.ts +114 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/global-dispatcher.d.ts +9 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/global-origin.d.ts +7 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/h2c-client.d.ts +6 -6
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/handlers.d.ts +14 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/header.d.ts +160 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/index.d.ts +91 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/interceptors.d.ts +82 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-agent.d.ts +68 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-client.d.ts +27 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-errors.d.ts +12 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-interceptor.d.ts +94 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/mock-pool.d.ts +27 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/patch.d.ts +29 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/pool-stats.d.ts +19 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/pool.d.ts +41 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/proxy-agent.d.ts +29 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/readable.d.ts +68 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/retry-agent.d.ts +8 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/retry-handler.d.ts +125 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/round-robin-pool.d.ts +2 -0
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/snapshot-agent.d.ts +0 -4
- package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/socks5-proxy-agent.d.ts +2 -4
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/util.d.ts +18 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/webidl.d.ts +347 -0
- package/node_modules/@mytools/fst-platform/node_modules/undici/types/websocket.d.ts +188 -0
- package/node_modules/@mytools/fst-platform/package.json +4 -3
- package/node_modules/@mytools/fst-platform/src/managed-process.js +36 -0
- package/node_modules/@mytools/fst-platform/src/process.js +11 -3
- package/node_modules/@mytools/fst-platform/src/shell.js +46 -1
- package/node_modules/@mytools/fst-plugin/README.md +4 -0
- package/node_modules/@mytools/fst-plugin/package.json +1 -1
- package/node_modules/@mytools/fst-plugin/src/contracts.js +3 -0
- package/node_modules/@mytools/fst-plugin/src/host.js +54 -31
- package/node_modules/@mytools/fst-plugin/src/runtime.js +14 -8
- package/node_modules/@mytools/fst-workflow/package.json +1 -1
- package/node_modules/@mytools/fst-workflow/src/engine.js +1 -1
- package/node_modules/@mytools/fst-workspace/README.md +6 -0
- package/node_modules/@mytools/fst-workspace/package.json +2 -1
- package/node_modules/@mytools/fst-workspace/src/plugin-registry.js +58 -0
- package/node_modules/@mytools/fst-workspace/src/plugins.js +10 -5
- package/node_modules/@mytools/fst-workspace/src/workflows.js +32 -12
- package/node_modules/@mytools/pack/package.json +3 -3
- package/node_modules/@mytools/pack/runtime-cache.js +26 -0
- package/node_modules/@mytools/pack/runtime.js +6 -10
- package/node_modules/@mytools/sdk/README.md +10 -0
- package/node_modules/@mytools/sdk/inputs.js +53 -0
- package/node_modules/@mytools/sdk/package.json +2 -0
- package/node_modules/@mytools/sdk/reports.js +53 -0
- package/node_modules/@mytools/web/public/THIRD_PARTY_NOTICES.txt +1197 -1207
- package/node_modules/@npmcli/agent/lib/agents.js +0 -10
- package/node_modules/@npmcli/agent/package.json +12 -11
- package/node_modules/@npmcli/arborist/README.md +2 -2
- package/node_modules/@npmcli/arborist/bin/index.js +2 -1
- package/node_modules/@npmcli/arborist/bin/shrinkwrap.js +7 -0
- package/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js +25 -159
- package/node_modules/@npmcli/arborist/lib/arborist/isolated-reifier.js +49 -11
- package/node_modules/@npmcli/arborist/lib/arborist/load-actual.js +0 -67
- package/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js +37 -5
- package/node_modules/@npmcli/arborist/lib/arborist/rebuild.js +8 -15
- package/node_modules/@npmcli/arborist/lib/arborist/reify.js +42 -59
- package/node_modules/@npmcli/arborist/lib/consistent-resolve.js +1 -1
- package/node_modules/@npmcli/arborist/lib/diff.js +22 -17
- package/node_modules/@npmcli/arborist/lib/edge.js +2 -22
- package/node_modules/@npmcli/arborist/lib/index.js +0 -2
- package/node_modules/@npmcli/arborist/lib/isolated-classes.js +1 -4
- package/node_modules/@npmcli/arborist/lib/node.js +9 -13
- package/node_modules/@npmcli/arborist/lib/place-dep.js +0 -6
- package/node_modules/@npmcli/arborist/lib/printable.js +5 -0
- package/node_modules/@npmcli/arborist/lib/shrinkwrap.js +32 -55
- package/node_modules/@npmcli/arborist/package.json +26 -32
- package/node_modules/@npmcli/fs/lib/move-file.js +5 -5
- package/node_modules/@npmcli/fs/package.json +5 -5
- package/node_modules/@npmcli/git/package.json +12 -13
- package/node_modules/@npmcli/installed-package-contents/package.json +7 -7
- package/node_modules/@npmcli/map-workspaces/package.json +7 -7
- package/node_modules/@npmcli/metavuln-calculator/package.json +16 -10
- package/node_modules/@npmcli/name-from-folder/package.json +16 -13
- package/node_modules/@npmcli/node-gyp/package.json +5 -5
- package/node_modules/@npmcli/package-json/lib/index.js +1 -2
- package/node_modules/@npmcli/package-json/lib/normalize.js +22 -23
- package/node_modules/@npmcli/package-json/package.json +10 -11
- package/node_modules/@npmcli/promise-spawn/README.md +2 -1
- package/node_modules/@npmcli/promise-spawn/package.json +5 -5
- package/node_modules/@npmcli/redact/package.json +4 -4
- package/node_modules/@npmcli/run-script/lib/is-server-package.js +11 -0
- package/node_modules/@npmcli/run-script/lib/make-spawn-args.js +6 -5
- package/node_modules/@npmcli/run-script/lib/run-script-pkg.js +13 -4
- package/node_modules/@npmcli/run-script/lib/run-script.js +2 -1
- package/node_modules/@npmcli/run-script/package.json +11 -12
- package/node_modules/@sigstore/bundle/README.md +1 -1
- package/node_modules/@sigstore/bundle/dist/error.js +0 -1
- package/node_modules/@sigstore/bundle/package.json +2 -2
- package/node_modules/@sigstore/core/README.md +1 -1
- package/node_modules/@sigstore/core/dist/asn1/length.js +1 -12
- package/node_modules/@sigstore/core/dist/asn1/obj.js +7 -25
- package/node_modules/@sigstore/core/dist/asn1/parse.js +5 -24
- package/node_modules/@sigstore/core/package.json +2 -2
- package/node_modules/@sigstore/sign/README.md +1 -1
- package/node_modules/@sigstore/sign/dist/signer/fulcio/ephemeral.js +1 -1
- package/node_modules/@sigstore/sign/package.json +9 -9
- package/node_modules/@sigstore/tuf/README.md +1 -1
- package/node_modules/@sigstore/tuf/package.json +4 -4
- package/node_modules/@sigstore/tuf/seeds.json +1 -1
- package/node_modules/@sigstore/verify/README.md +1 -1
- package/node_modules/@sigstore/verify/dist/bundle/dsse.d.ts +0 -1
- package/node_modules/@sigstore/verify/dist/bundle/dsse.js +0 -6
- package/node_modules/@sigstore/verify/dist/bundle/message.d.ts +0 -1
- package/node_modules/@sigstore/verify/dist/bundle/message.js +0 -5
- package/node_modules/@sigstore/verify/dist/policy.d.ts +1 -1
- package/node_modules/@sigstore/verify/dist/policy.js +2 -0
- package/node_modules/@sigstore/verify/dist/shared.types.d.ts +1 -6
- package/node_modules/@sigstore/verify/dist/tlog/checkpoint.js +3 -17
- package/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js +4 -4
- package/node_modules/@sigstore/verify/dist/tlog/index.js +1 -13
- package/node_modules/@sigstore/verify/dist/tlog/merkle.js +1 -12
- package/node_modules/@sigstore/verify/dist/verifier.js +5 -13
- package/node_modules/@sigstore/verify/package.json +5 -5
- package/node_modules/@tufjs/models/package.json +3 -3
- package/node_modules/abbrev/package.json +8 -9
- package/node_modules/agent-base/dist/helpers.d.ts +5 -0
- package/node_modules/agent-base/dist/helpers.d.ts.map +1 -1
- package/node_modules/agent-base/dist/helpers.js +34 -5
- package/node_modules/agent-base/dist/helpers.js.map +1 -1
- package/node_modules/agent-base/dist/index.d.ts +5 -1
- package/node_modules/agent-base/dist/index.d.ts.map +1 -1
- package/node_modules/agent-base/dist/index.js +40 -8
- package/node_modules/agent-base/dist/index.js.map +1 -1
- package/node_modules/agent-base/package.json +12 -12
- package/node_modules/bin-links/README.md +4 -5
- package/node_modules/bin-links/lib/fix-bin.js +1 -3
- package/node_modules/bin-links/lib/index.js +16 -8
- package/node_modules/bin-links/lib/link-mans.js +53 -0
- package/node_modules/bin-links/package.json +12 -11
- package/node_modules/cacache/lib/content/write.js +0 -2
- package/node_modules/cacache/lib/entry-index.js +0 -3
- package/node_modules/cacache/lib/rm.js +0 -1
- package/node_modules/cacache/lib/util/tmp.js +1 -5
- package/node_modules/cacache/lib/verify.js +2 -2
- package/node_modules/cacache/package.json +7 -7
- package/node_modules/cmd-shim/lib/index.js +32 -67
- package/node_modules/cmd-shim/package.json +5 -5
- package/node_modules/hosted-git-info/README.md +1 -1
- package/node_modules/hosted-git-info/lib/parse-url.js +3 -1
- package/node_modules/hosted-git-info/package.json +4 -4
- package/node_modules/http-proxy-agent/dist/index.d.ts +5 -8
- package/node_modules/http-proxy-agent/dist/index.d.ts.map +1 -1
- package/node_modules/http-proxy-agent/dist/index.js +42 -26
- package/node_modules/http-proxy-agent/dist/index.js.map +1 -1
- package/node_modules/http-proxy-agent/package.json +14 -15
- package/node_modules/https-proxy-agent/dist/index.d.ts +5 -9
- package/node_modules/https-proxy-agent/dist/index.d.ts.map +1 -1
- package/node_modules/https-proxy-agent/dist/index.js +44 -98
- package/node_modules/https-proxy-agent/dist/index.js.map +1 -1
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts +3 -0
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts.map +1 -1
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js +10 -3
- package/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map +1 -1
- package/node_modules/https-proxy-agent/package.json +15 -16
- package/node_modules/ignore-walk/package.json +4 -4
- package/node_modules/ini/package.json +5 -5
- package/node_modules/ip-address/README.md +70 -70
- package/node_modules/ip-address/dist/ipv6.js +7 -4
- package/node_modules/ip-address/dist/ipv6.js.map +1 -1
- package/node_modules/ip-address/dist/v6/constants.d.ts +3 -0
- package/node_modules/ip-address/dist/v6/constants.js +3 -0
- package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
- package/node_modules/ip-address/package.json +2 -1
- package/node_modules/json-parse-even-better-errors/lib/index.js +1 -3
- package/node_modules/json-parse-even-better-errors/package.json +17 -13
- package/node_modules/make-fetch-happen/package.json +11 -11
- package/node_modules/minipass-fetch/package.json +4 -4
- package/node_modules/node-gyp/.release-please-manifest.json +1 -1
- package/node_modules/node-gyp/CHANGELOG.md +0 -102
- package/node_modules/node-gyp/README.md +2 -3
- package/node_modules/node-gyp/eslint.config.js +1 -4
- package/node_modules/node-gyp/gyp/.release-please-manifest.json +1 -1
- package/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +19 -14
- package/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +2 -7
- package/node_modules/node-gyp/gyp/pyproject.toml +1 -1
- package/node_modules/node-gyp/lib/build.js +6 -18
- package/node_modules/node-gyp/lib/create-config-gypi.js +0 -5
- package/node_modules/node-gyp/lib/node-gyp.js +2 -9
- package/node_modules/node-gyp/lib/rebuild.js +3 -3
- package/node_modules/node-gyp/package.json +9 -11
- package/node_modules/nopt/README.md +4 -2
- package/node_modules/nopt/lib/debug.js +5 -0
- package/node_modules/nopt/lib/nopt-lib.js +43 -7
- package/node_modules/nopt/lib/nopt.js +4 -2
- package/node_modules/nopt/lib/type-defs.js +13 -8
- package/node_modules/nopt/package.json +17 -15
- package/node_modules/npm-bundled/package.json +6 -6
- package/node_modules/npm-install-checks/package.json +5 -5
- package/node_modules/npm-normalize-package-bin/package.json +16 -13
- package/node_modules/npm-package-arg/package.json +7 -7
- package/node_modules/npm-packlist/README.md +30 -45
- package/node_modules/npm-packlist/lib/index.js +47 -115
- package/node_modules/npm-packlist/package.json +8 -10
- package/node_modules/npm-pick-manifest/package.json +19 -15
- package/node_modules/npm-registry-fetch/lib/errors.js +3 -8
- package/node_modules/npm-registry-fetch/package.json +12 -12
- package/node_modules/pacote/lib/dir.js +5 -60
- package/node_modules/pacote/lib/fetcher.js +0 -4
- package/node_modules/pacote/lib/git.js +3 -11
- package/node_modules/pacote/lib/util/add-git-sha.js +1 -1
- package/node_modules/pacote/package.json +18 -19
- package/node_modules/parse-conflict-json/package.json +6 -6
- package/node_modules/proc-log/package.json +4 -4
- package/node_modules/read-cmd-shim/lib/index.js +1 -1
- package/node_modules/read-cmd-shim/package.json +18 -14
- package/node_modules/sigstore/README.md +1 -1
- package/node_modules/sigstore/package.json +10 -10
- package/node_modules/socks-proxy-agent/dist/index.d.ts +3 -1
- package/node_modules/socks-proxy-agent/dist/index.d.ts.map +1 -1
- package/node_modules/socks-proxy-agent/dist/index.js +43 -17
- package/node_modules/socks-proxy-agent/dist/index.js.map +1 -1
- package/node_modules/socks-proxy-agent/package.json +15 -15
- package/node_modules/ssri/package.json +4 -4
- package/node_modules/tuf-js/dist/config.d.ts +2 -2
- package/node_modules/tuf-js/dist/fetcher.d.ts +4 -4
- package/node_modules/tuf-js/dist/fetcher.js +16 -55
- package/node_modules/tuf-js/dist/updater.js +2 -2
- package/node_modules/tuf-js/package.json +8 -8
- package/node_modules/undici/README.md +72 -405
- package/node_modules/undici/docs/docs/api/Agent.md +41 -252
- package/node_modules/undici/docs/docs/api/BalancedPool.md +48 -246
- package/node_modules/undici/docs/docs/api/CacheStorage.md +13 -171
- package/node_modules/undici/docs/docs/api/Client.md +139 -395
- package/node_modules/undici/docs/docs/api/Connector.md +35 -118
- package/node_modules/undici/docs/docs/api/ContentType.md +25 -65
- package/node_modules/undici/docs/docs/api/Cookies.md +47 -125
- package/node_modules/undici/docs/docs/api/Debug.md +31 -47
- package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +97 -409
- package/node_modules/undici/docs/docs/api/DispatchInterceptor.md +60 -0
- package/node_modules/undici/docs/docs/api/Dispatcher.md +1011 -500
- package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +96 -105
- package/node_modules/undici/docs/docs/api/Errors.md +28 -528
- package/node_modules/undici/docs/docs/api/EventSource.md +13 -326
- package/node_modules/undici/docs/docs/api/Fetch.md +24 -693
- package/node_modules/undici/docs/docs/api/MockAgent.md +264 -346
- package/node_modules/undici/docs/docs/api/MockClient.md +31 -153
- package/node_modules/undici/docs/docs/api/MockErrors.md +5 -56
- package/node_modules/undici/docs/docs/api/MockPool.md +253 -324
- package/node_modules/undici/docs/docs/api/Pool.md +41 -235
- package/node_modules/undici/docs/docs/api/PoolStats.md +13 -119
- package/node_modules/undici/docs/docs/api/ProxyAgent.md +81 -198
- package/node_modules/undici/docs/docs/api/RedirectHandler.md +58 -238
- package/node_modules/undici/docs/docs/api/RetryAgent.md +28 -119
- package/node_modules/undici/docs/docs/api/RetryHandler.md +78 -161
- package/node_modules/undici/docs/docs/api/Util.md +11 -68
- package/node_modules/undici/docs/docs/api/WebSocket.md +24 -509
- package/node_modules/undici/docs/docs/api/api-lifecycle.md +33 -101
- package/node_modules/undici/docs/docs/best-practices/client-certificate.md +0 -2
- package/node_modules/undici/docs/docs/best-practices/mocking-request.md +2 -58
- package/node_modules/undici/docs/docs/best-practices/proxy.md +1 -3
- package/node_modules/undici/docs/docs/best-practices/writing-tests.md +0 -45
- package/node_modules/undici/index-fetch.js +4 -34
- package/node_modules/undici/index.d.ts +1 -1
- package/node_modules/undici/index.js +20 -87
- package/node_modules/undici/lib/api/abort-signal.js +0 -2
- package/node_modules/undici/lib/api/api-connect.js +11 -15
- package/node_modules/undici/lib/api/api-pipeline.js +19 -33
- package/node_modules/undici/lib/api/api-request.js +59 -89
- package/node_modules/undici/lib/api/api-stream.js +64 -114
- package/node_modules/undici/lib/api/api-upgrade.js +13 -26
- package/node_modules/undici/lib/api/readable.js +87 -317
- package/node_modules/undici/lib/api/util.js +93 -0
- package/node_modules/undici/lib/core/connect.js +125 -77
- package/node_modules/undici/lib/core/constants.js +9 -11
- package/node_modules/undici/lib/core/diagnostics.js +129 -154
- package/node_modules/undici/lib/core/errors.js +50 -122
- package/node_modules/undici/lib/core/request.js +87 -172
- package/node_modules/undici/lib/core/symbols.js +2 -14
- package/node_modules/undici/lib/core/tree.js +2 -10
- package/node_modules/undici/lib/core/util.js +190 -481
- package/node_modules/undici/lib/dispatcher/agent.js +35 -83
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +38 -46
- package/node_modules/undici/lib/dispatcher/client-h1.js +199 -492
- package/node_modules/undici/lib/dispatcher/client-h2.js +380 -1409
- package/node_modules/undici/lib/dispatcher/client.js +130 -253
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +52 -50
- package/node_modules/undici/lib/dispatcher/dispatcher.js +24 -17
- package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +45 -75
- package/node_modules/undici/lib/dispatcher/fixed-queue.js +50 -68
- package/node_modules/undici/lib/dispatcher/pool-base.js +54 -153
- package/node_modules/undici/lib/dispatcher/pool-stats.js +34 -0
- package/node_modules/undici/lib/dispatcher/pool.js +16 -135
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +41 -175
- package/node_modules/undici/lib/dispatcher/retry-agent.js +0 -3
- package/node_modules/undici/lib/global.js +9 -59
- package/node_modules/undici/lib/handler/decorator-handler.js +15 -43
- package/node_modules/undici/lib/handler/redirect-handler.js +116 -127
- package/node_modules/undici/lib/handler/retry-handler.js +182 -398
- package/node_modules/undici/lib/interceptor/dns.js +47 -254
- package/node_modules/undici/lib/interceptor/dump.js +56 -32
- package/node_modules/undici/lib/interceptor/redirect-interceptor.js +21 -0
- package/node_modules/undici/lib/interceptor/redirect.js +14 -11
- package/node_modules/undici/lib/interceptor/response-error.js +22 -31
- package/node_modules/undici/lib/llhttp/.gitkeep +0 -0
- package/node_modules/undici/lib/llhttp/constants.js +193 -446
- package/node_modules/undici/lib/llhttp/llhttp-wasm.js +1 -11
- package/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +1 -11
- package/node_modules/undici/lib/llhttp/utils.js +12 -9
- package/node_modules/undici/lib/mock/mock-agent.js +22 -106
- package/node_modules/undici/lib/mock/mock-client.js +4 -13
- package/node_modules/undici/lib/mock/mock-errors.js +2 -3
- package/node_modules/undici/lib/mock/mock-interceptor.js +13 -33
- package/node_modules/undici/lib/mock/mock-pool.js +4 -13
- package/node_modules/undici/lib/mock/mock-symbols.js +1 -10
- package/node_modules/undici/lib/mock/mock-utils.js +51 -404
- package/node_modules/undici/lib/mock/pluralizer.js +29 -0
- package/node_modules/undici/lib/util/timers.js +9 -11
- package/node_modules/undici/lib/web/cache/cache.js +51 -63
- package/node_modules/undici/lib/web/cache/cachestorage.js +7 -13
- package/node_modules/undici/lib/web/cache/symbols.js +5 -0
- package/node_modules/undici/lib/web/cookies/index.js +18 -45
- package/node_modules/undici/lib/web/cookies/parse.js +149 -157
- package/node_modules/undici/lib/web/cookies/util.js +2 -4
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +9 -37
- package/node_modules/undici/lib/web/eventsource/eventsource.js +64 -108
- package/node_modules/undici/lib/web/eventsource/util.js +5 -28
- package/node_modules/undici/lib/web/fetch/body.js +148 -173
- package/node_modules/undici/lib/web/fetch/constants.js +6 -13
- package/node_modules/undici/lib/web/fetch/data-url.js +167 -19
- package/node_modules/undici/lib/web/fetch/dispatcher-weakref.js +46 -0
- package/node_modules/undici/lib/web/fetch/file.js +126 -0
- package/node_modules/undici/lib/web/fetch/formdata-parser.js +117 -229
- package/node_modules/undici/lib/web/fetch/formdata.js +65 -85
- package/node_modules/undici/lib/web/fetch/headers.js +108 -143
- package/node_modules/undici/lib/web/fetch/index.js +446 -627
- package/node_modules/undici/lib/web/fetch/request.js +115 -217
- package/node_modules/undici/lib/web/fetch/response.js +82 -110
- package/node_modules/undici/lib/web/fetch/symbols.js +9 -0
- package/node_modules/undici/lib/web/fetch/util.js +393 -291
- package/node_modules/undici/lib/web/fetch/webidl.js +695 -0
- package/node_modules/undici/lib/web/fileapi/encoding.js +290 -0
- package/node_modules/undici/lib/web/fileapi/filereader.js +344 -0
- package/node_modules/undici/lib/web/fileapi/progressevent.js +78 -0
- package/node_modules/undici/lib/web/fileapi/symbols.js +10 -0
- package/node_modules/undici/lib/web/fileapi/util.js +391 -0
- package/node_modules/undici/lib/web/websocket/connection.js +160 -139
- package/node_modules/undici/lib/web/websocket/constants.js +10 -70
- package/node_modules/undici/lib/web/websocket/events.js +30 -49
- package/node_modules/undici/lib/web/websocket/frame.js +20 -51
- package/node_modules/undici/lib/web/websocket/receiver.js +87 -83
- package/node_modules/undici/lib/web/websocket/sender.js +13 -18
- package/node_modules/undici/lib/web/websocket/symbols.js +12 -0
- package/node_modules/undici/lib/web/websocket/util.js +90 -115
- package/node_modules/undici/lib/web/websocket/websocket.js +171 -359
- package/node_modules/undici/package.json +57 -49
- package/node_modules/undici/scripts/strip-comments.js +1 -3
- package/node_modules/undici/types/agent.d.ts +13 -12
- package/node_modules/undici/types/api.d.ts +26 -26
- package/node_modules/undici/types/balanced-pool.d.ts +12 -13
- package/node_modules/undici/types/client.d.ts +39 -98
- package/node_modules/undici/types/connector.d.ts +2 -5
- package/node_modules/undici/types/cookies.d.ts +1 -3
- package/node_modules/undici/types/diagnostics-channel.d.ts +11 -20
- package/node_modules/undici/types/dispatcher.d.ts +139 -136
- package/node_modules/undici/types/env-http-proxy-agent.d.ts +3 -4
- package/node_modules/undici/types/errors.d.ts +54 -86
- package/node_modules/undici/types/eventsource.d.ts +4 -9
- package/node_modules/undici/types/fetch.d.ts +25 -51
- package/node_modules/undici/types/file.d.ts +39 -0
- package/node_modules/undici/types/filereader.d.ts +54 -0
- package/node_modules/undici/types/formdata.d.ts +7 -7
- package/node_modules/undici/types/global-dispatcher.d.ts +4 -4
- package/node_modules/undici/types/global-origin.d.ts +5 -5
- package/node_modules/undici/types/handlers.d.ts +9 -10
- package/node_modules/undici/types/header.d.ts +1 -162
- package/node_modules/undici/types/index.d.ts +47 -69
- package/node_modules/undici/types/interceptors.d.ts +12 -62
- package/node_modules/undici/types/mock-agent.d.ts +27 -46
- package/node_modules/undici/types/mock-client.d.ts +4 -6
- package/node_modules/undici/types/mock-errors.d.ts +3 -3
- package/node_modules/undici/types/mock-interceptor.d.ts +21 -26
- package/node_modules/undici/types/mock-pool.d.ts +4 -6
- package/node_modules/undici/types/patch.d.ts +4 -0
- package/node_modules/undici/types/pool-stats.d.ts +8 -8
- package/node_modules/undici/types/pool.d.ts +14 -14
- package/node_modules/undici/types/proxy-agent.d.ts +6 -13
- package/node_modules/undici/types/readable.d.ts +16 -19
- package/node_modules/undici/types/retry-agent.d.ts +1 -1
- package/node_modules/undici/types/retry-handler.d.ts +9 -18
- package/node_modules/undici/types/util.d.ts +3 -3
- package/node_modules/undici/types/webidl.d.ts +32 -156
- package/node_modules/undici/types/websocket.d.ts +10 -48
- package/node_modules/validate-npm-package-name/package.json +4 -4
- package/node_modules/which/package.json +4 -4
- package/node_modules/write-file-atomic/package.json +4 -4
- package/package.json +56 -60
- package/node_modules/@npmcli/arborist/lib/npm-extension.js +0 -237
- package/node_modules/@npmcli/arborist/lib/package-extensions.js +0 -236
- package/node_modules/@npmcli/arborist/lib/patch.js +0 -111
- package/node_modules/@npmcli/arborist/lib/patched-dependencies.js +0 -168
- package/node_modules/cacache/lib/util/cache-dir.js +0 -29
- package/node_modules/diff/CONTRIBUTING.md +0 -28
- package/node_modules/diff/LICENSE +0 -29
- package/node_modules/diff/README.md +0 -388
- package/node_modules/diff/dist/diff.js +0 -1782
- package/node_modules/diff/dist/diff.min.js +0 -1
- package/node_modules/diff/eslint.config.mjs +0 -182
- package/node_modules/diff/libcjs/convert/dmp.d.ts +0 -8
- package/node_modules/diff/libcjs/convert/dmp.d.ts.map +0 -1
- package/node_modules/diff/libcjs/convert/dmp.js +0 -24
- package/node_modules/diff/libcjs/convert/xml.d.ts +0 -6
- package/node_modules/diff/libcjs/convert/xml.d.ts.map +0 -1
- package/node_modules/diff/libcjs/convert/xml.js +0 -34
- package/node_modules/diff/libcjs/diff/array.d.ts +0 -19
- package/node_modules/diff/libcjs/diff/array.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/array.js +0 -40
- package/node_modules/diff/libcjs/diff/base.d.ts +0 -20
- package/node_modules/diff/libcjs/diff/base.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/base.js +0 -265
- package/node_modules/diff/libcjs/diff/character.d.ts +0 -19
- package/node_modules/diff/libcjs/diff/character.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/character.js +0 -31
- package/node_modules/diff/libcjs/diff/css.d.ts +0 -18
- package/node_modules/diff/libcjs/diff/css.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/css.js +0 -34
- package/node_modules/diff/libcjs/diff/json.d.ts +0 -24
- package/node_modules/diff/libcjs/diff/json.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/json.js +0 -105
- package/node_modules/diff/libcjs/diff/line.d.ts +0 -24
- package/node_modules/diff/libcjs/diff/line.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/line.js +0 -89
- package/node_modules/diff/libcjs/diff/sentence.d.ts +0 -21
- package/node_modules/diff/libcjs/diff/sentence.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/sentence.js +0 -67
- package/node_modules/diff/libcjs/diff/word.d.ts +0 -35
- package/node_modules/diff/libcjs/diff/word.d.ts.map +0 -1
- package/node_modules/diff/libcjs/diff/word.js +0 -312
- package/node_modules/diff/libcjs/index.d.ts +0 -20
- package/node_modules/diff/libcjs/index.d.ts.map +0 -1
- package/node_modules/diff/libcjs/index.js +0 -64
- package/node_modules/diff/libcjs/package.json +0 -1
- package/node_modules/diff/libcjs/patch/apply.d.ts +0 -62
- package/node_modules/diff/libcjs/patch/apply.d.ts.map +0 -1
- package/node_modules/diff/libcjs/patch/apply.js +0 -267
- package/node_modules/diff/libcjs/patch/create.d.ts +0 -122
- package/node_modules/diff/libcjs/patch/create.d.ts.map +0 -1
- package/node_modules/diff/libcjs/patch/create.js +0 -251
- package/node_modules/diff/libcjs/patch/line-endings.d.ts +0 -17
- package/node_modules/diff/libcjs/patch/line-endings.d.ts.map +0 -1
- package/node_modules/diff/libcjs/patch/line-endings.js +0 -61
- package/node_modules/diff/libcjs/patch/parse.d.ts +0 -8
- package/node_modules/diff/libcjs/patch/parse.d.ts.map +0 -1
- package/node_modules/diff/libcjs/patch/parse.js +0 -150
- package/node_modules/diff/libcjs/patch/reverse.d.ts +0 -9
- package/node_modules/diff/libcjs/patch/reverse.d.ts.map +0 -1
- package/node_modules/diff/libcjs/patch/reverse.js +0 -37
- package/node_modules/diff/libcjs/types.d.ts +0 -213
- package/node_modules/diff/libcjs/types.d.ts.map +0 -1
- package/node_modules/diff/libcjs/types.js +0 -2
- package/node_modules/diff/libcjs/util/array.d.ts +0 -3
- package/node_modules/diff/libcjs/util/array.d.ts.map +0 -1
- package/node_modules/diff/libcjs/util/array.js +0 -21
- package/node_modules/diff/libcjs/util/distance-iterator.d.ts +0 -2
- package/node_modules/diff/libcjs/util/distance-iterator.d.ts.map +0 -1
- package/node_modules/diff/libcjs/util/distance-iterator.js +0 -40
- package/node_modules/diff/libcjs/util/params.d.ts +0 -4
- package/node_modules/diff/libcjs/util/params.d.ts.map +0 -1
- package/node_modules/diff/libcjs/util/params.js +0 -17
- package/node_modules/diff/libcjs/util/string.d.ts +0 -30
- package/node_modules/diff/libcjs/util/string.d.ts.map +0 -1
- package/node_modules/diff/libcjs/util/string.js +0 -200
- package/node_modules/diff/libesm/convert/dmp.d.ts +0 -8
- package/node_modules/diff/libesm/convert/dmp.d.ts.map +0 -1
- package/node_modules/diff/libesm/convert/dmp.js +0 -21
- package/node_modules/diff/libesm/convert/xml.d.ts +0 -6
- package/node_modules/diff/libesm/convert/xml.d.ts.map +0 -1
- package/node_modules/diff/libesm/convert/xml.js +0 -31
- package/node_modules/diff/libesm/diff/array.d.ts +0 -19
- package/node_modules/diff/libesm/diff/array.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/array.js +0 -16
- package/node_modules/diff/libesm/diff/base.d.ts +0 -20
- package/node_modules/diff/libesm/diff/base.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/base.js +0 -253
- package/node_modules/diff/libesm/diff/character.d.ts +0 -19
- package/node_modules/diff/libesm/diff/character.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/character.js +0 -7
- package/node_modules/diff/libesm/diff/css.d.ts +0 -18
- package/node_modules/diff/libesm/diff/css.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/css.js +0 -10
- package/node_modules/diff/libesm/diff/json.d.ts +0 -24
- package/node_modules/diff/libesm/diff/json.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/json.js +0 -78
- package/node_modules/diff/libesm/diff/line.d.ts +0 -24
- package/node_modules/diff/libesm/diff/line.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/line.js +0 -65
- package/node_modules/diff/libesm/diff/sentence.d.ts +0 -21
- package/node_modules/diff/libesm/diff/sentence.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/sentence.js +0 -43
- package/node_modules/diff/libesm/diff/word.d.ts +0 -35
- package/node_modules/diff/libesm/diff/word.d.ts.map +0 -1
- package/node_modules/diff/libesm/diff/word.js +0 -281
- package/node_modules/diff/libesm/index.d.ts +0 -20
- package/node_modules/diff/libesm/index.d.ts.map +0 -1
- package/node_modules/diff/libesm/index.js +0 -30
- package/node_modules/diff/libesm/package.json +0 -1
- package/node_modules/diff/libesm/patch/apply.d.ts +0 -62
- package/node_modules/diff/libesm/patch/apply.d.ts.map +0 -1
- package/node_modules/diff/libesm/patch/apply.js +0 -257
- package/node_modules/diff/libesm/patch/create.d.ts +0 -122
- package/node_modules/diff/libesm/patch/create.d.ts.map +0 -1
- package/node_modules/diff/libesm/patch/create.js +0 -228
- package/node_modules/diff/libesm/patch/line-endings.d.ts +0 -17
- package/node_modules/diff/libesm/patch/line-endings.d.ts.map +0 -1
- package/node_modules/diff/libesm/patch/line-endings.js +0 -44
- package/node_modules/diff/libesm/patch/parse.d.ts +0 -8
- package/node_modules/diff/libesm/patch/parse.d.ts.map +0 -1
- package/node_modules/diff/libesm/patch/parse.js +0 -147
- package/node_modules/diff/libesm/patch/reverse.d.ts +0 -9
- package/node_modules/diff/libesm/patch/reverse.d.ts.map +0 -1
- package/node_modules/diff/libesm/patch/reverse.js +0 -23
- package/node_modules/diff/libesm/types.d.ts +0 -213
- package/node_modules/diff/libesm/types.d.ts.map +0 -1
- package/node_modules/diff/libesm/types.js +0 -1
- package/node_modules/diff/libesm/util/array.d.ts +0 -3
- package/node_modules/diff/libesm/util/array.d.ts.map +0 -1
- package/node_modules/diff/libesm/util/array.js +0 -17
- package/node_modules/diff/libesm/util/distance-iterator.d.ts +0 -2
- package/node_modules/diff/libesm/util/distance-iterator.d.ts.map +0 -1
- package/node_modules/diff/libesm/util/distance-iterator.js +0 -37
- package/node_modules/diff/libesm/util/params.d.ts +0 -4
- package/node_modules/diff/libesm/util/params.d.ts.map +0 -1
- package/node_modules/diff/libesm/util/params.js +0 -14
- package/node_modules/diff/libesm/util/string.d.ts +0 -30
- package/node_modules/diff/libesm/util/string.d.ts.map +0 -1
- package/node_modules/diff/libesm/util/string.js +0 -184
- package/node_modules/diff/package.json +0 -130
- package/node_modules/diff/release-notes.md +0 -432
- package/node_modules/node-gyp/commitlint.config.mjs +0 -3
- package/node_modules/node-gyp/gyp/commitlint.config.js +0 -6
- package/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake_test.py +0 -105
- package/node_modules/node-gyp/zizmor.yml +0 -5
- package/node_modules/proxy-agent-negotiate/dist/index.d.ts +0 -14
- package/node_modules/proxy-agent-negotiate/dist/index.d.ts.map +0 -1
- package/node_modules/proxy-agent-negotiate/dist/index.js +0 -35
- package/node_modules/proxy-agent-negotiate/dist/index.js.map +0 -1
- package/node_modules/proxy-agent-negotiate/package.json +0 -47
- package/node_modules/undici/docs/docs/api/CacheStore.md +0 -360
- package/node_modules/undici/docs/docs/api/ClientStats.md +0 -93
- package/node_modules/undici/docs/docs/api/GlobalInstallation.md +0 -121
- package/node_modules/undici/docs/docs/api/H2CClient.md +0 -385
- package/node_modules/undici/docs/docs/api/Interceptors.md +0 -419
- package/node_modules/undici/docs/docs/api/MockCallHistory.md +0 -371
- package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +0 -206
- package/node_modules/undici/docs/docs/api/RoundRobinPool.md +0 -239
- package/node_modules/undici/docs/docs/api/SnapshotAgent.md +0 -361
- package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +0 -256
- package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +0 -233
- package/node_modules/undici/docs/docs/getting-started.md +0 -281
- package/node_modules/undici/docs/docs/site.json +0 -125
- package/node_modules/undici/docs/docs/type-map.json +0 -79
- package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +0 -110
- package/node_modules/undici/types/dispatcher1-wrapper.d.ts +0 -7
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/core/socks5-client.js +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/core/socks5-utils.js +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/encoding/index.js +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/llhttp/constants.d.ts +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/llhttp/utils.d.ts +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/mock/snapshot-utils.js +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/date.js +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/util/stats.js +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/subresource-integrity/Readme.md +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/lib/web/subresource-integrity/subresource-integrity.js +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/cache-interceptor.d.ts +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/client-stats.d.ts +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/mock-call-history.d.ts +0 -0
- /package/node_modules/{undici → @mytools/fst-platform/node_modules/undici}/types/utility.d.ts +0 -0
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const assert = require('node:assert')
|
|
4
|
+
const { errorMonitor } = require('node:events')
|
|
4
5
|
const { pipeline } = require('node:stream')
|
|
5
6
|
const util = require('../core/util.js')
|
|
6
7
|
const {
|
|
7
8
|
RequestContentLengthMismatchError,
|
|
8
|
-
ResponseContentLengthMismatchError,
|
|
9
9
|
RequestAbortedError,
|
|
10
10
|
SocketError,
|
|
11
|
-
InformationalError
|
|
12
|
-
InvalidArgumentError,
|
|
13
|
-
HeadersTimeoutError,
|
|
14
|
-
BodyTimeoutError,
|
|
15
|
-
ResponseExceededMaxSizeError
|
|
11
|
+
InformationalError
|
|
16
12
|
} = require('../core/errors.js')
|
|
17
13
|
const {
|
|
18
14
|
kUrl,
|
|
@@ -29,40 +25,18 @@ const {
|
|
|
29
25
|
kOnError,
|
|
30
26
|
kMaxConcurrentStreams,
|
|
31
27
|
kHTTP2Session,
|
|
32
|
-
kHostAuthority,
|
|
33
28
|
kResume,
|
|
34
29
|
kSize,
|
|
35
|
-
kHTTPContext
|
|
36
|
-
kClosed,
|
|
37
|
-
kKeepAliveDefaultTimeout,
|
|
38
|
-
kHeadersTimeout,
|
|
39
|
-
kBodyTimeout,
|
|
40
|
-
kEnableConnectProtocol,
|
|
41
|
-
kRemoteSettings,
|
|
42
|
-
kHTTP2Stream,
|
|
43
|
-
kHTTP2SessionState,
|
|
44
|
-
kHTTP2Options,
|
|
45
|
-
kMaxResponseSize
|
|
30
|
+
kHTTPContext
|
|
46
31
|
} = require('../core/symbols.js')
|
|
47
|
-
const { channels } = require('../core/diagnostics.js')
|
|
48
32
|
|
|
49
33
|
const kOpenStreams = Symbol('open streams')
|
|
50
|
-
const kRequestStreamId = Symbol('request stream id')
|
|
51
|
-
const kRequestStream = Symbol('request stream')
|
|
52
|
-
const kRequestStreamCleanup = Symbol('request stream cleanup')
|
|
53
|
-
const kRequestStreamState = Symbol('request stream state')
|
|
54
|
-
const kReceivedGoAway = Symbol('received goaway')
|
|
55
|
-
const kGoAwayReplayAttempts = Symbol('goaway replay attempts')
|
|
56
|
-
const kRefusedStreamRetry = Symbol('refused stream retry')
|
|
57
|
-
|
|
58
|
-
// RFC 9113 section 8.7: a client SHOULD NOT automatically retry a request more
|
|
59
|
-
// than once. Without a budget a peer that keeps refusing turns one request into
|
|
60
|
-
// an unbounded connect/refuse/reconnect loop that never settles and starves the
|
|
61
|
-
// event loop.
|
|
62
|
-
const MAX_GOAWAY_REPLAY_ATTEMPTS = 1
|
|
63
34
|
|
|
64
35
|
let extractBody
|
|
65
36
|
|
|
37
|
+
// Experimental
|
|
38
|
+
let h2ExperimentalWarned = false
|
|
39
|
+
|
|
66
40
|
/** @type {import('http2')} */
|
|
67
41
|
let http2
|
|
68
42
|
try {
|
|
@@ -80,1032 +54,293 @@ const {
|
|
|
80
54
|
HTTP2_HEADER_SCHEME,
|
|
81
55
|
HTTP2_HEADER_CONTENT_LENGTH,
|
|
82
56
|
HTTP2_HEADER_EXPECT,
|
|
83
|
-
HTTP2_HEADER_STATUS
|
|
84
|
-
HTTP2_HEADER_PROTOCOL,
|
|
85
|
-
NGHTTP2_NO_ERROR,
|
|
86
|
-
NGHTTP2_REFUSED_STREAM
|
|
57
|
+
HTTP2_HEADER_STATUS
|
|
87
58
|
}
|
|
88
59
|
} = http2
|
|
89
60
|
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
client[kHTTP2Session] = null
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (socket != null && socket[kError] == null) {
|
|
108
|
-
socket[kError] = err
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (!session.closed && !session.destroyed) {
|
|
112
|
-
try {
|
|
113
|
-
session.destroy(err)
|
|
114
|
-
} catch {}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
util.destroy(socket, err)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function getGoAwayPendingIdx (client, lastStreamID) {
|
|
121
|
-
const maxAcceptedStreamID = Number.isInteger(lastStreamID) ? lastStreamID : Number.MAX_SAFE_INTEGER
|
|
122
|
-
|
|
123
|
-
for (let i = client[kRunningIdx]; i < client[kPendingIdx]; i++) {
|
|
124
|
-
const request = client[kQueue][i]
|
|
125
|
-
|
|
126
|
-
if (request == null) {
|
|
127
|
-
continue
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (typeof request[kRequestStreamId] !== 'number' || request[kRequestStreamId] > maxAcceptedStreamID) {
|
|
131
|
-
return i
|
|
61
|
+
function parseH2Headers (headers) {
|
|
62
|
+
const result = []
|
|
63
|
+
|
|
64
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
65
|
+
// h2 may concat the header value by array
|
|
66
|
+
// e.g. Set-Cookie
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
for (const subvalue of value) {
|
|
69
|
+
// we need to provide each header value of header name
|
|
70
|
+
// because the headers handler expect name-value pair
|
|
71
|
+
result.push(Buffer.from(name), Buffer.from(subvalue))
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
result.push(Buffer.from(name), Buffer.from(value))
|
|
132
75
|
}
|
|
133
76
|
}
|
|
134
77
|
|
|
135
|
-
return
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function detachRequestFromStream (request) {
|
|
139
|
-
request[kRequestStreamId] = null
|
|
140
|
-
request[kRequestStream] = null
|
|
141
|
-
request[kRequestStreamCleanup] = null
|
|
78
|
+
return result
|
|
142
79
|
}
|
|
143
80
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
request[kRequestStreamCleanup] = cleanup
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function clearRequestStream (request) {
|
|
155
|
-
const cleanup = request[kRequestStreamCleanup]
|
|
156
|
-
const stream = request[kRequestStream]
|
|
157
|
-
detachRequestFromStream(request)
|
|
158
|
-
cleanup?.(stream)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function requeueUnsentRequest (client, request) {
|
|
162
|
-
client[kQueue].splice(client[kPendingIdx] + 1, 0, request)
|
|
81
|
+
/**
|
|
82
|
+
* @param {import('node:http2').IncomingHttpHeaders} headers
|
|
83
|
+
* @returns {Buffer[]}
|
|
84
|
+
*/
|
|
85
|
+
function parseH2ResponseHeaders (headers) {
|
|
86
|
+
const { [HTTP2_HEADER_STATUS]: _statusCode, ...realHeaders } = headers
|
|
87
|
+
return parseH2Headers(realHeaders)
|
|
163
88
|
}
|
|
164
89
|
|
|
165
|
-
function
|
|
166
|
-
|
|
167
|
-
const runningIdx = client[kRunningIdx]
|
|
168
|
-
|
|
169
|
-
// In-order completion: clear the request and advance without splicing.
|
|
170
|
-
// The client's resume loop compacts cleared slots once the index grows.
|
|
171
|
-
if (runningIdx < client[kPendingIdx] && queue[runningIdx] === request) {
|
|
172
|
-
queue[runningIdx] = null
|
|
173
|
-
client[kRunningIdx] = runningIdx + 1
|
|
174
|
-
return
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const index = queue.indexOf(request, runningIdx)
|
|
178
|
-
|
|
179
|
-
if (index === -1 || index >= client[kPendingIdx]) {
|
|
180
|
-
return
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
queue.splice(index, 1)
|
|
184
|
-
client[kPendingIdx]--
|
|
90
|
+
async function connectH2 (client, socket) {
|
|
91
|
+
client[kSocket] = socket
|
|
185
92
|
|
|
186
|
-
if (
|
|
187
|
-
|
|
93
|
+
if (!h2ExperimentalWarned) {
|
|
94
|
+
h2ExperimentalWarned = true
|
|
95
|
+
process.emitWarning('H2 support is experimental, expect them to change at any time.', {
|
|
96
|
+
code: 'UNDICI-H2'
|
|
97
|
+
})
|
|
188
98
|
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function canReplayRequest (request) {
|
|
192
|
-
const { body } = request
|
|
193
99
|
|
|
194
|
-
|
|
195
|
-
|
|
100
|
+
const session = http2.connect(client[kUrl], {
|
|
101
|
+
createConnection: () => socket,
|
|
102
|
+
peerMaxConcurrentStreams: client[kMaxConcurrentStreams]
|
|
103
|
+
})
|
|
196
104
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
105
|
+
session[kOpenStreams] = 0
|
|
106
|
+
session[kClient] = client
|
|
107
|
+
session[kSocket] = socket
|
|
201
108
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
request[kGoAwayReplayAttempts] = attempts
|
|
109
|
+
util.addListener(session, 'error', onHttp2SessionError)
|
|
110
|
+
util.addListener(session, 'frameError', onHttp2FrameError)
|
|
111
|
+
util.addListener(session, 'end', onHttp2SessionEnd)
|
|
112
|
+
util.addListener(session, 'goaway', onHTTP2GoAway)
|
|
113
|
+
util.addListener(session, 'close', function () {
|
|
114
|
+
const { [kClient]: client } = this
|
|
115
|
+
const { [kSocket]: socket } = client
|
|
210
116
|
|
|
211
|
-
|
|
212
|
-
}
|
|
117
|
+
const err = this[kSocket][kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket))
|
|
213
118
|
|
|
214
|
-
|
|
215
|
-
if (stream != null && !stream.destroyed && !stream.closed) {
|
|
216
|
-
try {
|
|
217
|
-
stream.close(code)
|
|
218
|
-
} catch {}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
119
|
+
client[kHTTP2Session] = null
|
|
221
120
|
|
|
222
|
-
|
|
223
|
-
|
|
121
|
+
if (client.destroyed) {
|
|
122
|
+
assert(client[kPending] === 0)
|
|
224
123
|
|
|
225
|
-
|
|
226
|
-
|
|
124
|
+
// Fail entire queue.
|
|
125
|
+
const requests = client[kQueue].splice(client[kRunningIdx])
|
|
126
|
+
for (let i = 0; i < requests.length; i++) {
|
|
127
|
+
const request = requests[i]
|
|
128
|
+
util.errorRequest(client, request, err)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
})
|
|
227
132
|
|
|
228
|
-
|
|
229
|
-
}
|
|
133
|
+
session.unref()
|
|
230
134
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
// stream abandoned here would still run completeRequestStream() later — and
|
|
234
|
-
// splice out the request that has since been requeued onto another session.
|
|
235
|
-
function severRequestStream (stream) {
|
|
236
|
-
if (stream == null || stream[kRequestStreamState] == null) {
|
|
237
|
-
return
|
|
238
|
-
}
|
|
135
|
+
client[kHTTP2Session] = session
|
|
136
|
+
socket[kHTTP2Session] = session
|
|
239
137
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// Upgrade streams use their own close cleanup, which would otherwise release
|
|
243
|
-
// the session a second time after the stream has been severed for GOAWAY.
|
|
244
|
-
stream.off('close', onUpgradeStreamClose)
|
|
138
|
+
util.addListener(socket, 'error', function (err) {
|
|
139
|
+
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
|
|
245
140
|
|
|
246
|
-
|
|
247
|
-
closeStreamSession(stream)
|
|
248
|
-
}
|
|
141
|
+
this[kError] = err
|
|
249
142
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
}
|
|
143
|
+
this[kClient][kOnError](err)
|
|
144
|
+
})
|
|
254
145
|
|
|
255
|
-
function
|
|
256
|
-
|
|
146
|
+
util.addListener(socket, 'end', function () {
|
|
147
|
+
util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this)))
|
|
148
|
+
})
|
|
257
149
|
|
|
258
|
-
|
|
259
|
-
|
|
150
|
+
util.addListener(socket, 'close', function () {
|
|
151
|
+
const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
|
|
260
152
|
|
|
261
|
-
|
|
262
|
-
createConnection: () => socket,
|
|
263
|
-
peerMaxConcurrentStreams: client[kHTTP2Options].maxConcurrentStreams,
|
|
264
|
-
settings: {
|
|
265
|
-
// TODO(metcoder95): add support for PUSH
|
|
266
|
-
enablePush: false,
|
|
267
|
-
...(http2InitialWindowSize != null ? { initialWindowSize: http2InitialWindowSize } : null)
|
|
268
|
-
}
|
|
269
|
-
})
|
|
153
|
+
client[kSocket] = null
|
|
270
154
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
session[kClient] = client
|
|
274
|
-
session[kSocket] = socket
|
|
275
|
-
session[kHTTP2SessionState] = {
|
|
276
|
-
idleTimeout: null,
|
|
277
|
-
// Armed while the peer advertises MAX_CONCURRENT_STREAMS = 0 and we have
|
|
278
|
-
// work that cannot start. See setNoStreamsTimeout.
|
|
279
|
-
noStreamsTimeout: null,
|
|
280
|
-
// Sockets start out ref'd. Session ref/unref proxies to the socket, so a
|
|
281
|
-
// single cached flag lets us skip redundant uv ref/unref calls, provided
|
|
282
|
-
// every ref/unref of the session or its socket goes through
|
|
283
|
-
// refH2Session/unrefH2Session.
|
|
284
|
-
refed: true,
|
|
285
|
-
ping: {
|
|
286
|
-
interval: client[kHTTP2Options].pingInterval === 0 ? null : setInterval(onHttp2SendPing, client[kHTTP2Options].pingInterval, session).unref()
|
|
155
|
+
if (this[kHTTP2Session] != null) {
|
|
156
|
+
this[kHTTP2Session].destroy(err)
|
|
287
157
|
}
|
|
288
|
-
}
|
|
289
|
-
session[kReceivedGoAway] = false
|
|
290
|
-
// We set it to true by default in a best-effort; however once connected to an H2 server
|
|
291
|
-
// we will check if extended CONNECT protocol is supported or not
|
|
292
|
-
// and set this value accordingly.
|
|
293
|
-
session[kEnableConnectProtocol] = false
|
|
294
|
-
// States whether or not we have received the remote settings from the server
|
|
295
|
-
session[kRemoteSettings] = false
|
|
296
|
-
|
|
297
|
-
// Apply connection-level flow control once connected (if supported).
|
|
298
|
-
if (http2ConnectionWindowSize) {
|
|
299
|
-
util.addListener(session, 'connect', applyConnectionWindowSize.bind(session, http2ConnectionWindowSize))
|
|
300
|
-
}
|
|
301
158
|
|
|
302
|
-
|
|
303
|
-
util.addListener(session, 'frameError', onHttp2FrameError)
|
|
304
|
-
util.addListener(session, 'goaway', onHttp2SessionGoAway)
|
|
305
|
-
util.addListener(session, 'close', onHttp2SessionClose)
|
|
306
|
-
util.addListener(session, 'remoteSettings', onHttp2RemoteSettings)
|
|
307
|
-
// TODO (@metcoder95): implement SETTINGS support
|
|
308
|
-
// util.addListener(session, 'localSettings', onHttp2RemoteSettings)
|
|
159
|
+
client[kPendingIdx] = client[kRunningIdx]
|
|
309
160
|
|
|
310
|
-
|
|
161
|
+
assert(client[kRunning] === 0)
|
|
311
162
|
|
|
312
|
-
|
|
313
|
-
socket[kHTTP2Session] = session
|
|
163
|
+
client.emit('disconnect', client[kUrl], [client], err)
|
|
314
164
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
util.addListener(socket, 'close', onHttp2SocketClose)
|
|
165
|
+
client[kResume]()
|
|
166
|
+
})
|
|
318
167
|
|
|
319
|
-
|
|
320
|
-
socket.on('close',
|
|
168
|
+
let closed = false
|
|
169
|
+
socket.on('close', () => {
|
|
170
|
+
closed = true
|
|
171
|
+
})
|
|
321
172
|
|
|
322
173
|
return {
|
|
323
174
|
version: 'h2',
|
|
324
175
|
defaultPipelining: Infinity,
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
* @returns {boolean}
|
|
328
|
-
*/
|
|
329
|
-
write (request) {
|
|
330
|
-
return writeH2(client, request)
|
|
176
|
+
write (...args) {
|
|
177
|
+
return writeH2(client, ...args)
|
|
331
178
|
},
|
|
332
|
-
/**
|
|
333
|
-
* @returns {void}
|
|
334
|
-
*/
|
|
335
179
|
resume () {
|
|
336
180
|
resumeH2(client)
|
|
337
181
|
},
|
|
338
|
-
/**
|
|
339
|
-
* @param {Error | null} err
|
|
340
|
-
* @param {() => void} callback
|
|
341
|
-
*/
|
|
342
182
|
destroy (err, callback) {
|
|
343
|
-
if (
|
|
183
|
+
if (closed) {
|
|
344
184
|
queueMicrotask(callback)
|
|
345
185
|
} else {
|
|
186
|
+
// Destroying the socket will trigger the session close
|
|
346
187
|
socket.destroy(err).on('close', callback)
|
|
347
188
|
}
|
|
348
189
|
},
|
|
349
|
-
/**
|
|
350
|
-
* @type {boolean}
|
|
351
|
-
*/
|
|
352
190
|
get destroyed () {
|
|
353
191
|
return socket.destroyed
|
|
354
192
|
},
|
|
355
|
-
|
|
356
|
-
* @param {import('../core/request.js')} request
|
|
357
|
-
* @returns {boolean}
|
|
358
|
-
*/
|
|
359
|
-
busy (request) {
|
|
360
|
-
if (session[kRemoteSettings] === false && client[kRunning] > 0) {
|
|
361
|
-
return true
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (client[kRunning] >= client[kMaxConcurrentStreams]) {
|
|
365
|
-
return true
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
if (request != null) {
|
|
369
|
-
if (client[kRunning] > 0) {
|
|
370
|
-
// We are already processing requests
|
|
371
|
-
|
|
372
|
-
// Unlike HTTP/1.1 pipelining, HTTP/2 multiplexes requests on
|
|
373
|
-
// independent streams, so non-idempotent requests can be dispatched
|
|
374
|
-
// concurrently. Retry eligibility is handled by stream/session error
|
|
375
|
-
// handling instead of by serializing all non-idempotent requests.
|
|
376
|
-
// Don't dispatch an upgrade until all preceding requests have completed.
|
|
377
|
-
// Possibly, we do not have remote settings confirmed yet.
|
|
378
|
-
if ((request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false) return true
|
|
379
|
-
} else {
|
|
380
|
-
return (request.upgrade === 'websocket' || request.method === 'CONNECT') && session[kRemoteSettings] === false
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
193
|
+
busy () {
|
|
384
194
|
return false
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Session ref/unref proxies to the underlying socket, so refH2Session and
|
|
390
|
-
// unrefH2Session cover both and can skip the call when the cached ref state
|
|
391
|
-
// already matches.
|
|
392
|
-
function refH2Session (session) {
|
|
393
|
-
const state = session[kHTTP2SessionState]
|
|
394
|
-
|
|
395
|
-
if (state.refed === false) {
|
|
396
|
-
state.refed = true
|
|
397
|
-
session.ref()
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function unrefH2Session (session) {
|
|
402
|
-
const state = session[kHTTP2SessionState]
|
|
403
|
-
|
|
404
|
-
if (state.refed === true) {
|
|
405
|
-
state.refed = false
|
|
406
|
-
session.unref()
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function resumeH2 (client) {
|
|
411
|
-
const socket = client[kSocket]
|
|
412
|
-
const session = client[kHTTP2Session]
|
|
413
|
-
|
|
414
|
-
if (socket?.destroyed === false) {
|
|
415
|
-
// After an upgrade the queue is empty but its stream is still in use, so never unref while a stream is open.
|
|
416
|
-
if (session[kOpenStreams] === 0 && client[kSize] === 0) {
|
|
417
|
-
unrefH2Session(session)
|
|
418
|
-
} else {
|
|
419
|
-
refH2Session(session)
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (client[kSize] === 0 && session[kOpenStreams] === 0) {
|
|
423
|
-
setHttp2IdleTimeout(session)
|
|
424
|
-
} else {
|
|
425
|
-
clearHttp2IdleTimeout(session)
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if (client[kMaxConcurrentStreams] === 0 && client[kRunning] === 0 && client[kPending] > 0) {
|
|
429
|
-
setNoStreamsTimeout(session)
|
|
430
|
-
} else {
|
|
431
|
-
clearNoStreamsTimeout(session)
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
function clearNoStreamsTimeout (session) {
|
|
437
|
-
const state = session[kHTTP2SessionState]
|
|
438
|
-
|
|
439
|
-
if (state?.noStreamsTimeout != null) {
|
|
440
|
-
clearTimeout(state.noStreamsTimeout)
|
|
441
|
-
state.noStreamsTimeout = null
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// A peer is allowed to advertise SETTINGS_MAX_CONCURRENT_STREAMS = 0 to refuse
|
|
446
|
-
// new streams (RFC 9113 §6.5.2), and is expected to raise it again later. Until
|
|
447
|
-
// it does, busy() reports the client as permanently busy and queued requests
|
|
448
|
-
// cannot open a stream — which means no per-stream timeout covers them, and no
|
|
449
|
-
// reconnect can happen either, so the SETTINGS frame that would lift the limit
|
|
450
|
-
// can never arrive. Give the peer headersTimeout to start honouring requests
|
|
451
|
-
// before failing them; a request that cannot even be sent has missed the same
|
|
452
|
-
// deadline as one whose headers never arrive.
|
|
453
|
-
function setNoStreamsTimeout (session) {
|
|
454
|
-
const client = session[kClient]
|
|
455
|
-
const state = session[kHTTP2SessionState]
|
|
456
|
-
const timeout = client[kHeadersTimeout]
|
|
457
|
-
|
|
458
|
-
if (!timeout || state.noStreamsTimeout != null) {
|
|
459
|
-
return
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
state.noStreamsTimeout = setTimeout(onNoStreamsTimeout, timeout, session).unref()
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
function onNoStreamsTimeout (session) {
|
|
466
|
-
const client = session[kClient]
|
|
467
|
-
const state = session[kHTTP2SessionState]
|
|
468
|
-
|
|
469
|
-
state.noStreamsTimeout = null
|
|
470
|
-
|
|
471
|
-
if (
|
|
472
|
-
client[kHTTP2Session] !== session ||
|
|
473
|
-
client[kMaxConcurrentStreams] !== 0 ||
|
|
474
|
-
client[kRunning] !== 0 ||
|
|
475
|
-
client[kPending] === 0
|
|
476
|
-
) {
|
|
477
|
-
return
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
const err = new HeadersTimeoutError(
|
|
481
|
-
`HTTP/2: server did not accept a new stream within ${client[kHeadersTimeout]}`
|
|
482
|
-
)
|
|
483
|
-
|
|
484
|
-
const requests = client[kQueue].splice(client[kPendingIdx])
|
|
485
|
-
for (let i = 0; i < requests.length; i++) {
|
|
486
|
-
if (requests[i] != null) {
|
|
487
|
-
util.errorRequest(client, requests[i], err)
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// Drop the unusable session so the next request gets a fresh connection,
|
|
492
|
-
// whose SETTINGS may well allow streams again.
|
|
493
|
-
session[kError] = err
|
|
494
|
-
resetHttp2Session(session, err)
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
function clearHttp2IdleTimeout (session) {
|
|
498
|
-
const state = session[kHTTP2SessionState]
|
|
499
|
-
|
|
500
|
-
if (state?.idleTimeout != null) {
|
|
501
|
-
clearTimeout(state.idleTimeout)
|
|
502
|
-
state.idleTimeout = null
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
function setHttp2IdleTimeout (session) {
|
|
507
|
-
const client = session[kClient]
|
|
508
|
-
|
|
509
|
-
if (client[kHTTP2Session] !== session || session.closed || session.destroyed) {
|
|
510
|
-
return
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
if (session[kOpenStreams] !== 0 || client[kSize] !== 0) {
|
|
514
|
-
clearHttp2IdleTimeout(session)
|
|
515
|
-
return
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
const state = session[kHTTP2SessionState]
|
|
519
|
-
if (state.idleTimeout == null) {
|
|
520
|
-
state.idleTimeout = setTimeout(onHttp2SessionIdleTimeout, client[kKeepAliveDefaultTimeout], session).unref()
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
function onHttp2SessionIdleTimeout (session) {
|
|
525
|
-
const client = session[kClient]
|
|
526
|
-
const socket = session[kSocket]
|
|
527
|
-
const state = session[kHTTP2SessionState]
|
|
528
|
-
|
|
529
|
-
state.idleTimeout = null
|
|
530
|
-
|
|
531
|
-
if (client[kHTTP2Session] !== session || session[kOpenStreams] !== 0 || client[kSize] !== 0 || session.closed || session.destroyed) {
|
|
532
|
-
return
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
const err = new InformationalError('socket idle timeout')
|
|
536
|
-
socket[kError] = err
|
|
537
|
-
util.destroy(socket, err)
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
function applyConnectionWindowSize (connectionWindowSize) {
|
|
541
|
-
try {
|
|
542
|
-
if (typeof this.setLocalWindowSize === 'function') {
|
|
543
|
-
this.setLocalWindowSize(connectionWindowSize)
|
|
544
|
-
}
|
|
545
|
-
} catch {
|
|
546
|
-
// Best-effort only.
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
function onHttp2RemoteSettings (settings) {
|
|
551
|
-
// Fallbacks are a safe bet, remote setting will always override
|
|
552
|
-
this[kClient][kMaxConcurrentStreams] = settings.maxConcurrentStreams ?? this[kClient][kMaxConcurrentStreams]
|
|
553
|
-
/**
|
|
554
|
-
* From RFC-8441
|
|
555
|
-
* A sender MUST NOT send a SETTINGS_ENABLE_CONNECT_PROTOCOL parameter
|
|
556
|
-
* with the value of 0 after previously sending a value of 1.
|
|
557
|
-
*/
|
|
558
|
-
// Note: Cannot be tested in Node, it does not supports disabling the extended CONNECT protocol once enabled
|
|
559
|
-
if (this[kRemoteSettings] === true && this[kEnableConnectProtocol] === true && settings.enableConnectProtocol === false) {
|
|
560
|
-
const err = new InformationalError('HTTP/2: Server disabled extended CONNECT protocol against RFC-8441')
|
|
561
|
-
this[kSocket][kError] = err
|
|
562
|
-
this[kClient][kOnError](err)
|
|
563
|
-
return
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
this[kEnableConnectProtocol] = settings.enableConnectProtocol ?? this[kEnableConnectProtocol]
|
|
567
|
-
this[kRemoteSettings] = true
|
|
568
|
-
this[kClient][kResume]()
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function onHttp2SendPing (session) {
|
|
572
|
-
const state = session[kHTTP2SessionState]
|
|
573
|
-
if ((session.closed || session.destroyed) && state.ping.interval != null) {
|
|
574
|
-
clearInterval(state.ping.interval)
|
|
575
|
-
state.ping.interval = null
|
|
576
|
-
return
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
// If no ping sent, do nothing
|
|
580
|
-
session.ping(onPing.bind(session))
|
|
581
|
-
|
|
582
|
-
function onPing (err, duration) {
|
|
583
|
-
const client = this[kClient]
|
|
584
|
-
const socket = this[kSocket]
|
|
585
|
-
|
|
586
|
-
if (err != null) {
|
|
587
|
-
const error = new InformationalError(`HTTP/2: "PING" errored - type ${err.message}`)
|
|
588
|
-
socket[kError] = error
|
|
589
|
-
client[kOnError](error)
|
|
590
|
-
} else {
|
|
591
|
-
client.emit('ping', duration)
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
function onHttp2SessionError (err) {
|
|
597
|
-
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
|
|
598
|
-
|
|
599
|
-
this[kSocket][kError] = err
|
|
600
|
-
|
|
601
|
-
if (this[kReceivedGoAway]) {
|
|
602
|
-
return
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
this[kClient][kOnError](err)
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
function onHttp2FrameError (type, code, id) {
|
|
609
|
-
if (id === 0) {
|
|
610
|
-
if (this[kReceivedGoAway]) {
|
|
611
|
-
return
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
|
|
615
|
-
this[kSocket][kError] = err
|
|
616
|
-
this[kClient][kOnError](err)
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
/**
|
|
621
|
-
* This is the root cause of #3011
|
|
622
|
-
* We need to handle GOAWAY frames properly, and trigger the session close
|
|
623
|
-
* along with the socket right away
|
|
624
|
-
*
|
|
625
|
-
* @this {import('http2').ClientHttp2Session}
|
|
626
|
-
* @param {number} errorCode
|
|
627
|
-
* @param {number} lastStreamID
|
|
628
|
-
*/
|
|
629
|
-
function onHttp2SessionGoAway (errorCode, lastStreamID) {
|
|
630
|
-
if (this[kReceivedGoAway]) {
|
|
631
|
-
return
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
this[kReceivedGoAway] = true
|
|
635
|
-
|
|
636
|
-
const err = getGoAwayError(this, errorCode)
|
|
637
|
-
const client = this[kClient]
|
|
638
|
-
const previousPendingIdx = client[kPendingIdx]
|
|
639
|
-
const pendingIdx = getGoAwayPendingIdx(client, lastStreamID)
|
|
640
|
-
const retriableRequests = []
|
|
641
|
-
const streamsToClose = []
|
|
642
|
-
|
|
643
|
-
// Closing one stream after GOAWAY can synchronously emit frameError on
|
|
644
|
-
// sibling streams. Detach all affected requests first so those errors do
|
|
645
|
-
// not fail requests that are about to be requeued.
|
|
646
|
-
for (let i = pendingIdx; i < previousPendingIdx; i++) {
|
|
647
|
-
const request = client[kQueue][i]
|
|
648
|
-
|
|
649
|
-
if (request != null) {
|
|
650
|
-
// Read before detaching, which drops the stream state.
|
|
651
|
-
const responseStarted = hasResponseStarted(request)
|
|
652
|
-
|
|
653
|
-
streamsToClose.push(detachRequestStreamForClose(request))
|
|
654
|
-
|
|
655
|
-
if (!responseStarted && canReplayRequest(request) && registerGoAwayRefusal(request)) {
|
|
656
|
-
retriableRequests.push(request)
|
|
657
|
-
} else {
|
|
658
|
-
util.errorRequest(client, request, err)
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
for (let i = 0; i < streamsToClose.length; i++) {
|
|
664
|
-
closeStream(streamsToClose[i])
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
if (pendingIdx !== previousPendingIdx) {
|
|
668
|
-
const remainingPendingRequests = client[kQueue].slice(previousPendingIdx)
|
|
669
|
-
client[kQueue].length = pendingIdx
|
|
670
|
-
client[kQueue].push(...retriableRequests, ...remainingPendingRequests)
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
if (client[kHTTP2Session] === this) {
|
|
674
|
-
client[kSocket] = null
|
|
675
|
-
client[kHTTPContext] = null
|
|
676
|
-
client[kHTTP2Session] = null
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
clearHttp2IdleTimeout(this)
|
|
680
|
-
clearNoStreamsTimeout(this)
|
|
681
|
-
|
|
682
|
-
if (!this.closed && !this.destroyed) {
|
|
683
|
-
this.close()
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
client[kPendingIdx] = pendingIdx
|
|
687
|
-
|
|
688
|
-
client.emit('disconnect', client[kUrl], [client], err)
|
|
689
|
-
|
|
690
|
-
client[kResume]()
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
function onHttp2SessionClose () {
|
|
694
|
-
const { [kClient]: client, [kHTTP2SessionState]: state, [kSocket]: socket } = this
|
|
695
|
-
|
|
696
|
-
const err = socket[kError] || this[kError] || new SocketError('closed', util.getSocketInfo(socket))
|
|
697
|
-
|
|
698
|
-
if (client[kHTTP2Session] === this) {
|
|
699
|
-
client[kSocket] = null
|
|
700
|
-
client[kHTTPContext] = null
|
|
701
|
-
client[kHTTP2Session] = null
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
clearHttp2IdleTimeout(this)
|
|
705
|
-
clearNoStreamsTimeout(this)
|
|
706
|
-
|
|
707
|
-
if (state.ping.interval != null) {
|
|
708
|
-
clearInterval(state.ping.interval)
|
|
709
|
-
state.ping.interval = null
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
if (client.destroyed) {
|
|
713
|
-
assert(client[kPending] === 0)
|
|
714
|
-
|
|
715
|
-
// Fail entire queue.
|
|
716
|
-
const requests = client[kQueue].splice(client[kRunningIdx])
|
|
717
|
-
for (let i = 0; i < requests.length; i++) {
|
|
718
|
-
const request = requests[i]
|
|
719
|
-
if (request != null) {
|
|
720
|
-
util.errorRequest(client, request, err)
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
function onHttp2SocketClose () {
|
|
727
|
-
const err = this[kError] || new SocketError('closed', util.getSocketInfo(this))
|
|
728
|
-
|
|
729
|
-
const session = this[kHTTP2Session]
|
|
730
|
-
const client = session[kClient]
|
|
731
|
-
|
|
732
|
-
if (client[kSocket] !== this) {
|
|
733
|
-
// Ignore stale socket closes from a detached GOAWAY session and from any
|
|
734
|
-
// session that has already been replaced. If the session was detached
|
|
735
|
-
// without a GOAWAY and there is no replacement yet, we still need the
|
|
736
|
-
// close event to flush the client state.
|
|
737
|
-
if (session[kReceivedGoAway] || (client[kHTTP2Session] != null && client[kHTTP2Session] !== session)) {
|
|
738
|
-
return
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
client[kSocket] = null
|
|
743
|
-
client[kHTTPContext] = null
|
|
744
|
-
if (client[kHTTP2Session] === session) {
|
|
745
|
-
client[kHTTP2Session] = null
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
session.destroy(err)
|
|
749
|
-
|
|
750
|
-
client[kPendingIdx] = client[kRunningIdx]
|
|
751
|
-
|
|
752
|
-
assert(client[kRunning] === 0)
|
|
753
|
-
|
|
754
|
-
client.emit('disconnect', client[kUrl], [client], err)
|
|
755
|
-
|
|
756
|
-
client[kResume]()
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
function onHttp2SocketError (err) {
|
|
760
|
-
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
|
|
761
|
-
|
|
762
|
-
this[kError] = err
|
|
763
|
-
|
|
764
|
-
if (this[kHTTP2Session]?.[kReceivedGoAway]) {
|
|
765
|
-
return
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
this[kHTTP2Session]?.[kClient]?.[kOnError](err)
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
function onHttp2SocketEnd () {
|
|
772
|
-
util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this)))
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
function onSocketClose () {
|
|
776
|
-
this[kClosed] = true
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
function noop () {}
|
|
780
|
-
|
|
781
|
-
function closeStreamSession (stream) {
|
|
782
|
-
const session = stream[kHTTP2Session]
|
|
783
|
-
const client = session[kClient]
|
|
784
|
-
|
|
785
|
-
stream[kHTTP2Session] = null
|
|
786
|
-
session[kOpenStreams] -= 1
|
|
787
|
-
// A session that received GOAWAY does not need to stay ref'd for queued requests.
|
|
788
|
-
if (session[kOpenStreams] === 0 && (client[kSize] === 0 || session[kReceivedGoAway])) {
|
|
789
|
-
unrefH2Session(session)
|
|
790
|
-
setHttp2IdleTimeout(session)
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
function onUpgradeStreamClose () {
|
|
795
|
-
this.off('error', noop)
|
|
796
|
-
|
|
797
|
-
const state = this[kRequestStreamState]
|
|
798
|
-
this[kRequestStreamState] = null
|
|
799
|
-
|
|
800
|
-
failUpgradeStream(state, new InformationalError('HTTP/2: stream closed before response headers'))
|
|
801
|
-
closeStreamSession(this)
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
// Idempotent terminal cleanup, called from both 'end' and 'close': the
|
|
805
|
-
// null-state guard no-ops the later call.
|
|
806
|
-
function completeRequestStream () {
|
|
807
|
-
const state = this[kRequestStreamState]
|
|
808
|
-
|
|
809
|
-
if (state == null) {
|
|
810
|
-
return
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
// Release the stream first so request references are cleared,
|
|
814
|
-
// then complete the response with trailers if available.
|
|
815
|
-
releaseRequestStream(this)
|
|
816
|
-
|
|
817
|
-
if (state.pendingEnd && !state.request.aborted && !state.request.completed) {
|
|
818
|
-
state.request.onResponseEnd(state.trailers || {})
|
|
819
|
-
} else if (!state.request.aborted && !state.request.completed) {
|
|
820
|
-
// The stream closed without a complete response and without reporting an
|
|
821
|
-
// error. finalizeRequest() below frees the queue slot either way, so
|
|
822
|
-
// without this the request would simply vanish and its caller would never
|
|
823
|
-
// hear back.
|
|
824
|
-
util.errorRequest(
|
|
825
|
-
state.client,
|
|
826
|
-
state.request,
|
|
827
|
-
new InformationalError('HTTP/2: stream closed before the response was complete')
|
|
828
|
-
)
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
finalizeRequest(state)
|
|
832
|
-
closeStreamSession(this)
|
|
833
|
-
this[kRequestStreamState] = null
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
|
|
837
|
-
function shouldSendContentLength (method) {
|
|
838
|
-
return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
function buildRequestHeaders (reqHeaders) {
|
|
842
|
-
const headers = {}
|
|
843
|
-
|
|
844
|
-
for (let n = 0; n < reqHeaders.length; n += 2) {
|
|
845
|
-
const key = reqHeaders[n + 0]
|
|
846
|
-
const val = reqHeaders[n + 1]
|
|
847
|
-
const current = headers[key]
|
|
848
|
-
|
|
849
|
-
if (key === 'cookie') {
|
|
850
|
-
if (current != null) {
|
|
851
|
-
headers[key] = Array.isArray(current) ? (current.push(val), current) : [current, val]
|
|
852
|
-
} else {
|
|
853
|
-
headers[key] = val
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
continue
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
if (typeof val === 'string') {
|
|
860
|
-
headers[key] = current ? `${current}, ${val}` : val
|
|
861
|
-
continue
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
for (let i = 0; i < val.length; i++) {
|
|
865
|
-
headers[key] = headers[key] ? `${headers[key]}, ${val[i]}` : val[i]
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
return headers
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
function removeUpgradeStreamListeners (stream) {
|
|
873
|
-
stream.off('response', onUpgradeResponse)
|
|
874
|
-
stream.off('error', onUpgradeStreamError)
|
|
875
|
-
stream.off('end', onUpgradeStreamEnd)
|
|
876
|
-
stream.off('timeout', onUpgradeStreamTimeout)
|
|
877
|
-
stream.off('error', noop)
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
function releaseUpgradeStream (stream) {
|
|
881
|
-
if (stream == null) {
|
|
882
|
-
return
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
const state = stream[kRequestStreamState]
|
|
886
|
-
if (state == null) {
|
|
887
|
-
return
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
const { request } = state
|
|
891
|
-
|
|
892
|
-
if (request[kRequestStream] === stream) {
|
|
893
|
-
detachRequestFromStream(request)
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
removeUpgradeStreamListeners(stream)
|
|
897
|
-
|
|
898
|
-
if (!stream.destroyed && !stream.closed) {
|
|
899
|
-
stream.once('error', noop)
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
function failUpgradeStream (state, err) {
|
|
904
|
-
if (state == null) {
|
|
905
|
-
return
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
const { request } = state
|
|
909
|
-
if (state.responseReceived || request.aborted || request.completed) {
|
|
910
|
-
return
|
|
195
|
+
}
|
|
911
196
|
}
|
|
912
|
-
|
|
913
|
-
releaseUpgradeStream(state.stream)
|
|
914
|
-
state.abort(err, true)
|
|
915
197
|
}
|
|
916
198
|
|
|
917
|
-
function
|
|
918
|
-
const
|
|
199
|
+
function resumeH2 (client) {
|
|
200
|
+
const socket = client[kSocket]
|
|
919
201
|
|
|
920
|
-
if (
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
202
|
+
if (socket?.destroyed === false) {
|
|
203
|
+
if (client[kSize] === 0 && client[kMaxConcurrentStreams] === 0) {
|
|
204
|
+
socket.unref()
|
|
205
|
+
client[kHTTP2Session].unref()
|
|
206
|
+
} else {
|
|
207
|
+
socket.ref()
|
|
208
|
+
client[kHTTP2Session].ref()
|
|
209
|
+
}
|
|
924
210
|
}
|
|
925
211
|
}
|
|
926
212
|
|
|
927
|
-
function
|
|
928
|
-
|
|
929
|
-
}
|
|
213
|
+
function onHttp2SessionError (err) {
|
|
214
|
+
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
|
|
930
215
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
failUpgradeStream(state, new InformationalError(`HTTP/2: "stream timeout after ${state.headersTimeout}"`))
|
|
216
|
+
this[kSocket][kError] = err
|
|
217
|
+
this[kClient][kOnError](err)
|
|
934
218
|
}
|
|
935
219
|
|
|
936
|
-
function
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
state.responseReceived = true
|
|
942
|
-
|
|
943
|
-
const statusCode = headers[HTTP2_HEADER_STATUS]
|
|
944
|
-
delete headers[HTTP2_HEADER_STATUS]
|
|
945
|
-
|
|
946
|
-
try {
|
|
947
|
-
request.onRequestUpgrade(statusCode, headers, stream)
|
|
948
|
-
} catch (err) {
|
|
949
|
-
state.abort(err)
|
|
950
|
-
return
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
if (request.aborted) {
|
|
954
|
-
return
|
|
220
|
+
function onHttp2FrameError (type, code, id) {
|
|
221
|
+
if (id === 0) {
|
|
222
|
+
const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`)
|
|
223
|
+
this[kSocket][kError] = err
|
|
224
|
+
this[kClient][kOnError](err)
|
|
955
225
|
}
|
|
956
|
-
|
|
957
|
-
removeUpgradeStreamListeners(stream)
|
|
958
|
-
detachRequestFromStream(request)
|
|
959
|
-
finalizeRequest(state)
|
|
960
226
|
}
|
|
961
227
|
|
|
962
|
-
function
|
|
963
|
-
const
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
stream[kRequestStreamState] = state
|
|
968
|
-
state.stream = stream
|
|
228
|
+
function onHttp2SessionEnd () {
|
|
229
|
+
const err = new SocketError('other side closed', util.getSocketInfo(this[kSocket]))
|
|
230
|
+
this.destroy(err)
|
|
231
|
+
util.destroy(this[kSocket], err)
|
|
232
|
+
}
|
|
969
233
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
234
|
+
/**
|
|
235
|
+
* This is the root cause of #3011
|
|
236
|
+
* We need to handle GOAWAY frames properly, and trigger the session close
|
|
237
|
+
* along with the socket right away
|
|
238
|
+
*/
|
|
239
|
+
function onHTTP2GoAway (code) {
|
|
240
|
+
// We cannot recover, so best to close the session and the socket
|
|
241
|
+
const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${code}`, util.getSocketInfo(this))
|
|
242
|
+
const client = this[kClient]
|
|
976
243
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
stream.setTimeout(headersTimeout)
|
|
980
|
-
}
|
|
244
|
+
client[kSocket] = null
|
|
245
|
+
client[kHTTPContext] = null
|
|
981
246
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
247
|
+
if (this[kHTTP2Session] != null) {
|
|
248
|
+
this[kHTTP2Session].destroy(err)
|
|
249
|
+
this[kHTTP2Session] = null
|
|
985
250
|
}
|
|
986
251
|
|
|
987
|
-
|
|
988
|
-
completeRequest(state.client, state.request, resetPendingIdx)
|
|
252
|
+
util.destroy(this[kSocket], err)
|
|
989
253
|
|
|
990
|
-
|
|
991
|
-
|
|
254
|
+
// Fail head of pipeline.
|
|
255
|
+
if (client[kRunningIdx] < client[kQueue].length) {
|
|
256
|
+
const request = client[kQueue][client[kRunningIdx]]
|
|
257
|
+
client[kQueue][client[kRunningIdx]++] = null
|
|
258
|
+
util.errorRequest(client, request, err)
|
|
259
|
+
client[kPendingIdx] = client[kRunningIdx]
|
|
260
|
+
}
|
|
992
261
|
|
|
993
|
-
|
|
994
|
-
try {
|
|
995
|
-
return session.request(headers, options)
|
|
996
|
-
} catch (err) {
|
|
997
|
-
// A GOAWAY'd session rejects new streams, same as an invalid session:
|
|
998
|
-
// reset and requeue on a fresh connection rather than the destroy + abort
|
|
999
|
-
// below, whose destroy(socket, err) can crash via an unhandled 'error'.
|
|
1000
|
-
if (err?.code === 'ERR_HTTP2_INVALID_SESSION' || err?.code === 'ERR_HTTP2_GOAWAY_SESSION') {
|
|
1001
|
-
const wrappedErr = new SocketError(err.message, util.getSocketInfo(session[kSocket]))
|
|
1002
|
-
wrappedErr.cause = err
|
|
1003
|
-
session[kError] = wrappedErr
|
|
1004
|
-
resetHttp2Session(session, wrappedErr)
|
|
1005
|
-
requeueUnsentRequest(client, request)
|
|
1006
|
-
|
|
1007
|
-
return null
|
|
1008
|
-
}
|
|
262
|
+
assert(client[kRunning] === 0)
|
|
1009
263
|
|
|
1010
|
-
|
|
1011
|
-
session[kError] = wrappedErr
|
|
1012
|
-
session[kSocket][kError] = wrappedErr
|
|
264
|
+
client.emit('disconnect', client[kUrl], [client], err)
|
|
1013
265
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
abort(wrappedErr)
|
|
266
|
+
client[kResume]()
|
|
267
|
+
}
|
|
1017
268
|
|
|
1018
|
-
|
|
1019
|
-
|
|
269
|
+
// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
|
|
270
|
+
function shouldSendContentLength (method) {
|
|
271
|
+
return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
|
|
1020
272
|
}
|
|
1021
273
|
|
|
1022
274
|
function writeH2 (client, request) {
|
|
1023
|
-
const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout]
|
|
1024
|
-
const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout]
|
|
1025
275
|
const session = client[kHTTP2Session]
|
|
1026
|
-
const { method, path, host, upgrade, expectContinue, signal,
|
|
276
|
+
const { method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request
|
|
277
|
+
let { body } = request
|
|
1027
278
|
|
|
1028
|
-
if (upgrade
|
|
1029
|
-
util.errorRequest(client, request, new
|
|
279
|
+
if (upgrade) {
|
|
280
|
+
util.errorRequest(client, request, new Error('Upgrade not supported for H2'))
|
|
1030
281
|
return false
|
|
1031
282
|
}
|
|
1032
283
|
|
|
1033
|
-
const headers =
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
284
|
+
const headers = {}
|
|
285
|
+
for (let n = 0; n < reqHeaders.length; n += 2) {
|
|
286
|
+
const key = reqHeaders[n + 0]
|
|
287
|
+
const val = reqHeaders[n + 1]
|
|
1037
288
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
request,
|
|
1050
|
-
headersTimeout,
|
|
1051
|
-
bodyTimeout,
|
|
1052
|
-
requestFinalized: false,
|
|
1053
|
-
responseContentLength: null,
|
|
1054
|
-
responseReceived: false,
|
|
1055
|
-
bodySent: false,
|
|
1056
|
-
pendingEnd: false,
|
|
1057
|
-
trailers: null,
|
|
1058
|
-
session,
|
|
1059
|
-
stream: null
|
|
289
|
+
if (Array.isArray(val)) {
|
|
290
|
+
for (let i = 0; i < val.length; i++) {
|
|
291
|
+
if (headers[key]) {
|
|
292
|
+
headers[key] += `,${val[i]}`
|
|
293
|
+
} else {
|
|
294
|
+
headers[key] = val[i]
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
headers[key] = val
|
|
299
|
+
}
|
|
1060
300
|
}
|
|
1061
301
|
|
|
1062
|
-
|
|
1063
|
-
|
|
302
|
+
/** @type {import('node:http2').ClientHttp2Stream} */
|
|
303
|
+
let stream
|
|
304
|
+
|
|
305
|
+
const { hostname, port } = client[kUrl]
|
|
306
|
+
|
|
307
|
+
headers[HTTP2_HEADER_AUTHORITY] = host || `${hostname}${port ? `:${port}` : ''}`
|
|
308
|
+
headers[HTTP2_HEADER_METHOD] = method
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* @param {Error} [error]
|
|
312
|
+
*/
|
|
313
|
+
const abort = (error) => {
|
|
314
|
+
if (request.aborted) {
|
|
1064
315
|
return
|
|
1065
316
|
}
|
|
1066
317
|
|
|
1067
|
-
|
|
318
|
+
if (request.completed) {
|
|
319
|
+
if (method === 'CONNECT' && stream != null) {
|
|
320
|
+
util.destroy(stream, error || new RequestAbortedError())
|
|
321
|
+
}
|
|
322
|
+
return
|
|
323
|
+
}
|
|
1068
324
|
|
|
1069
|
-
|
|
325
|
+
error = error || new RequestAbortedError()
|
|
1070
326
|
|
|
1071
|
-
|
|
1072
|
-
clearRequestStream(request)
|
|
1073
|
-
|
|
1074
|
-
// On Abort, we close the stream to send RST_STREAM frame.
|
|
1075
|
-
const stream = state.stream
|
|
1076
|
-
stream.close()
|
|
1077
|
-
|
|
1078
|
-
// close() alone leaves cleanup waiting on the 'close' event; on a busy,
|
|
1079
|
-
// long-lived multiplexed session that event can fail to fire, leaving the
|
|
1080
|
-
// native Http2Stream (and the whole request graph it pins) alive for the
|
|
1081
|
-
// session's life. Destroy the stream synchronously to release the handle
|
|
1082
|
-
// deterministically. Deferring the destroy (e.g. via setImmediate) leaks
|
|
1083
|
-
// the same way when the event loop is stalled and the callback never runs
|
|
1084
|
-
// under abort churn (#5558); close() has already queued the RST_STREAM
|
|
1085
|
-
// frame on the native session, so a synchronous destroy still sends it.
|
|
1086
|
-
if (!stream.destroyed) {
|
|
1087
|
-
util.destroy(stream)
|
|
1088
|
-
}
|
|
327
|
+
util.errorRequest(client, request, error)
|
|
1089
328
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
finalizeRequest(state, resetPendingIdx)
|
|
329
|
+
if (stream != null) {
|
|
330
|
+
util.destroy(stream, error)
|
|
1093
331
|
}
|
|
1094
332
|
|
|
1095
333
|
// We do not destroy the socket as we can continue using the session
|
|
1096
|
-
// the stream
|
|
1097
|
-
util.destroy(
|
|
334
|
+
// the stream get's destroyed and the session remains to create new streams
|
|
335
|
+
util.destroy(body, error)
|
|
336
|
+
client[kQueue][client[kRunningIdx]++] = null
|
|
337
|
+
client[kResume]()
|
|
1098
338
|
}
|
|
1099
339
|
|
|
1100
|
-
state.abort = abort
|
|
1101
|
-
|
|
1102
|
-
/** @type {import('node:http2').ClientHttp2Stream} */
|
|
1103
|
-
let stream = null
|
|
1104
|
-
|
|
1105
340
|
try {
|
|
1106
341
|
// We are already connected, streams are pending.
|
|
1107
342
|
// We can call on connect, and wait for abort
|
|
1108
|
-
request.
|
|
343
|
+
request.onConnect(abort)
|
|
1109
344
|
} catch (err) {
|
|
1110
345
|
util.errorRequest(client, request, err)
|
|
1111
346
|
}
|
|
@@ -1114,59 +349,71 @@ function writeH2 (client, request) {
|
|
|
1114
349
|
return false
|
|
1115
350
|
}
|
|
1116
351
|
|
|
1117
|
-
if (
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
if (session[kEnableConnectProtocol] === false) {
|
|
1123
|
-
util.errorRequest(client, request, new InformationalError('HTTP/2: Extended CONNECT protocol not supported by server'))
|
|
1124
|
-
unrefH2Session(session)
|
|
1125
|
-
return false
|
|
1126
|
-
}
|
|
352
|
+
if (method === 'CONNECT') {
|
|
353
|
+
session.ref()
|
|
354
|
+
// We disabled endStream to allow the user to write to the stream
|
|
355
|
+
stream = session.request(headers, { endStream: false, signal })
|
|
356
|
+
let upgradeResponseFinished = false
|
|
1127
357
|
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
headers[
|
|
358
|
+
/**
|
|
359
|
+
* @param {import('node:http2').IncomingHttpHeaders} headers
|
|
360
|
+
*/
|
|
361
|
+
const onResponse = (headers) => {
|
|
362
|
+
upgradeResponseFinished = true
|
|
363
|
+
stream.off(errorMonitor, onUpgradeError)
|
|
364
|
+
request.onUpgradeResponse(Number(headers[HTTP2_HEADER_STATUS]), headers, parseH2ResponseHeaders)
|
|
365
|
+
}
|
|
1135
366
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
367
|
+
/**
|
|
368
|
+
* @param {Error} error
|
|
369
|
+
*/
|
|
370
|
+
const onUpgradeError = (error) => {
|
|
371
|
+
upgradeResponseFinished = true
|
|
372
|
+
stream.off('response', onResponse)
|
|
373
|
+
request.onUpgradeError(error)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const onReady = () => {
|
|
377
|
+
try {
|
|
378
|
+
request.onUpgrade(null, null, stream)
|
|
379
|
+
} catch (error) {
|
|
380
|
+
stream.off('response', onResponse)
|
|
381
|
+
abort(error)
|
|
382
|
+
return
|
|
1140
383
|
}
|
|
1141
384
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
unrefH2Session(session)
|
|
1145
|
-
return false
|
|
385
|
+
if (request.aborted) {
|
|
386
|
+
return
|
|
1146
387
|
}
|
|
1147
|
-
setupUpgradeStream(stream, state)
|
|
1148
|
-
return true
|
|
1149
|
-
}
|
|
1150
388
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
// `ready` event is triggered
|
|
1155
|
-
// We disabled endStream to allow the user to write to the stream
|
|
1156
|
-
stream = openStream(client, request, session, abort, headers, { endStream: false, signal })
|
|
1157
|
-
if (stream == null) {
|
|
1158
|
-
unrefH2Session(session)
|
|
1159
|
-
return false
|
|
389
|
+
stream.off('error', abort)
|
|
390
|
+
stream.once(errorMonitor, onUpgradeError)
|
|
391
|
+
client[kQueue][client[kRunningIdx]++] = null
|
|
1160
392
|
}
|
|
1161
|
-
|
|
393
|
+
|
|
394
|
+
stream.once('response', onResponse)
|
|
395
|
+
stream.once('error', abort)
|
|
396
|
+
++session[kOpenStreams]
|
|
397
|
+
onReady()
|
|
398
|
+
|
|
399
|
+
stream.once('close', () => {
|
|
400
|
+
if (!upgradeResponseFinished && request.completed) {
|
|
401
|
+
stream.off('response', onResponse)
|
|
402
|
+
stream.off(errorMonitor, onUpgradeError)
|
|
403
|
+
request.onUpgradeError(new InformationalError(`HTTP/2: "stream error" received - code ${stream.rstCode}`))
|
|
404
|
+
}
|
|
405
|
+
session[kOpenStreams] -= 1
|
|
406
|
+
if (session[kOpenStreams] === 0) session.unref()
|
|
407
|
+
})
|
|
1162
408
|
|
|
1163
409
|
return true
|
|
1164
410
|
}
|
|
1165
411
|
|
|
1166
412
|
// https://tools.ietf.org/html/rfc7540#section-8.3
|
|
1167
413
|
// :path and :scheme headers must be omitted when sending CONNECT
|
|
414
|
+
|
|
1168
415
|
headers[HTTP2_HEADER_PATH] = path
|
|
1169
|
-
headers[HTTP2_HEADER_SCHEME] =
|
|
416
|
+
headers[HTTP2_HEADER_SCHEME] = 'https'
|
|
1170
417
|
|
|
1171
418
|
// https://tools.ietf.org/html/rfc7231#section-4.3.1
|
|
1172
419
|
// https://tools.ietf.org/html/rfc7231#section-4.3.2
|
|
@@ -1180,14 +427,9 @@ function writeH2 (client, request) {
|
|
|
1180
427
|
const expectsPayload = (
|
|
1181
428
|
method === 'PUT' ||
|
|
1182
429
|
method === 'POST' ||
|
|
1183
|
-
method === 'PATCH'
|
|
1184
|
-
method === 'QUERY' ||
|
|
1185
|
-
method === 'PROPFIND' ||
|
|
1186
|
-
method === 'PROPPATCH'
|
|
430
|
+
method === 'PATCH'
|
|
1187
431
|
)
|
|
1188
432
|
|
|
1189
|
-
let body = state.body
|
|
1190
|
-
|
|
1191
433
|
if (body && typeof body.read === 'function') {
|
|
1192
434
|
// Try to read EOF in order to get length.
|
|
1193
435
|
body.read(0)
|
|
@@ -1209,12 +451,12 @@ function writeH2 (client, request) {
|
|
|
1209
451
|
contentLength = request.contentLength
|
|
1210
452
|
}
|
|
1211
453
|
|
|
1212
|
-
if (contentLength === 0
|
|
454
|
+
if (contentLength === 0 || !expectsPayload) {
|
|
1213
455
|
// https://tools.ietf.org/html/rfc7230#section-3.3.2
|
|
1214
456
|
// A user agent SHOULD NOT send a Content-Length header field when
|
|
1215
457
|
// the request message does not contain a payload body and the method
|
|
1216
458
|
// semantics do not anticipate such a body.
|
|
1217
|
-
|
|
459
|
+
|
|
1218
460
|
contentLength = null
|
|
1219
461
|
}
|
|
1220
462
|
|
|
@@ -1230,423 +472,172 @@ function writeH2 (client, request) {
|
|
|
1230
472
|
}
|
|
1231
473
|
|
|
1232
474
|
if (contentLength != null) {
|
|
1233
|
-
assert(body
|
|
475
|
+
assert(body, 'no body must not have content length')
|
|
1234
476
|
headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}`
|
|
1235
477
|
}
|
|
1236
478
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
if (channels.sendHeaders.hasSubscribers) {
|
|
1240
|
-
let header = ''
|
|
1241
|
-
for (const key in headers) {
|
|
1242
|
-
header += `${key}: ${headers[key]}\r\n`
|
|
1243
|
-
}
|
|
1244
|
-
channels.sendHeaders.publish({ request, headers: header, socket: session[kSocket] })
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
// TODO(metcoder95): add support for sending trailers
|
|
1248
|
-
const shouldEndStream = body === null || contentLength === 0
|
|
1249
|
-
|
|
1250
|
-
state.body = body
|
|
1251
|
-
state.contentLength = contentLength
|
|
1252
|
-
state.expectsPayload = expectsPayload
|
|
479
|
+
session.ref()
|
|
1253
480
|
|
|
481
|
+
const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null
|
|
1254
482
|
if (expectContinue) {
|
|
1255
483
|
headers[HTTP2_HEADER_EXPECT] = '100-continue'
|
|
1256
|
-
|
|
484
|
+
stream = session.request(headers, { endStream: shouldEndStream, signal })
|
|
1257
485
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
486
|
+
stream.once('continue', writeBodyH2)
|
|
487
|
+
} else {
|
|
488
|
+
stream = session.request(headers, {
|
|
489
|
+
endStream: shouldEndStream,
|
|
490
|
+
signal
|
|
491
|
+
})
|
|
492
|
+
writeBodyH2()
|
|
1261
493
|
}
|
|
1262
|
-
stream[kHTTP2Stream] = true
|
|
1263
|
-
stream[kRequestStreamState] = state
|
|
1264
|
-
state.stream = stream
|
|
1265
494
|
|
|
1266
495
|
// Increment counter as we have new streams open
|
|
1267
|
-
clearHttp2IdleTimeout(session)
|
|
1268
496
|
++session[kOpenStreams]
|
|
1269
497
|
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
stream.on('headers', onInterimResponse)
|
|
1286
|
-
stream.on('end', onEnd)
|
|
1287
|
-
stream.on('error', onError)
|
|
1288
|
-
stream.on('frameError', onFrameError)
|
|
1289
|
-
stream.on('aborted', onAborted)
|
|
1290
|
-
if (headersTimeout || bodyTimeout) {
|
|
1291
|
-
stream.on('timeout', onTimeout)
|
|
1292
|
-
}
|
|
1293
|
-
stream.on('trailers', onTrailers)
|
|
1294
|
-
|
|
1295
|
-
if (!expectContinue) {
|
|
1296
|
-
writeBodyH2.call(stream)
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
return true
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
function removeRequestStreamListeners (stream) {
|
|
1303
|
-
stream.off('error', noop)
|
|
1304
|
-
stream.off('continue', writeBodyH2)
|
|
1305
|
-
stream.off('response', onResponse)
|
|
1306
|
-
stream.off('headers', onInterimResponse)
|
|
1307
|
-
stream.off('end', onEnd)
|
|
1308
|
-
stream.off('error', onError)
|
|
1309
|
-
stream.off('frameError', onFrameError)
|
|
1310
|
-
stream.off('aborted', onAborted)
|
|
1311
|
-
stream.off('timeout', onTimeout)
|
|
1312
|
-
stream.off('trailers', onTrailers)
|
|
1313
|
-
stream.off('data', onData)
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
function releaseRequestStream (stream) {
|
|
1317
|
-
if (stream == null) {
|
|
1318
|
-
return
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
const state = stream[kRequestStreamState]
|
|
1322
|
-
if (state == null) {
|
|
1323
|
-
return
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
const { request } = state
|
|
1327
|
-
|
|
1328
|
-
if (request[kRequestStream] === stream) {
|
|
1329
|
-
detachRequestFromStream(request)
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
// A closed or destroyed stream cannot emit further events; leaving the
|
|
1333
|
-
// listeners in place saves the removal scans (they are collected with
|
|
1334
|
-
// the stream). All handlers bail out when the stream state is gone.
|
|
1335
|
-
if (!stream.destroyed && !stream.closed) {
|
|
1336
|
-
removeRequestStreamListeners(stream)
|
|
1337
|
-
stream.once('error', noop)
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
function onData (chunk) {
|
|
1342
|
-
const stream = this
|
|
1343
|
-
const state = stream[kRequestStreamState]
|
|
1344
|
-
|
|
1345
|
-
if (state == null) {
|
|
1346
|
-
return
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
const { request, maxResponseSize, responseContentLength } = state
|
|
1350
|
-
|
|
1351
|
-
if (request.aborted || request.completed) {
|
|
1352
|
-
return
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
if (responseContentLength != null && state.bytesRead + chunk.length > responseContentLength) {
|
|
1356
|
-
state.abort(new ResponseContentLengthMismatchError())
|
|
1357
|
-
return
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
if (maxResponseSize > -1 && state.bytesRead + chunk.length > maxResponseSize) {
|
|
1361
|
-
// Unlike HTTP/1.1, which destroys the socket because it cannot abandon one
|
|
1362
|
-
// response without losing framing, resetting the offending stream leaves
|
|
1363
|
-
// the session usable for its siblings.
|
|
1364
|
-
state.abort(new ResponseExceededMaxSizeError())
|
|
1365
|
-
return
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
state.bytesRead += chunk.length
|
|
1369
|
-
|
|
1370
|
-
if (request.onResponseData(chunk) === false) {
|
|
1371
|
-
stream.pause()
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
function onInterimResponse (headers) {
|
|
1376
|
-
const stream = this
|
|
1377
|
-
const state = stream[kRequestStreamState]
|
|
1378
|
-
|
|
1379
|
-
if (state == null) {
|
|
1380
|
-
return
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
const { request } = state
|
|
1384
|
-
|
|
1385
|
-
if (request.aborted || request.completed) {
|
|
1386
|
-
return
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
// node http2 emits 'headers' for interim (1xx) informational responses,
|
|
1390
|
-
// while the final response arrives via 'response'. Forward these to the
|
|
1391
|
-
// handler so that onInfo is invoked, matching the HTTP/1 behaviour and the
|
|
1392
|
-
// documented onInfo contract.
|
|
1393
|
-
const statusCode = headers[HTTP2_HEADER_STATUS]
|
|
1394
|
-
delete headers[HTTP2_HEADER_STATUS]
|
|
1395
|
-
|
|
1396
|
-
request.onResponseStart(Number(statusCode), headers, noop, '')
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
function onResponse (headers) {
|
|
1400
|
-
const stream = this
|
|
1401
|
-
const state = stream[kRequestStreamState]
|
|
1402
|
-
|
|
1403
|
-
if (state == null) {
|
|
1404
|
-
return
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
const { request } = state
|
|
1408
|
-
|
|
1409
|
-
stream.off('response', onResponse)
|
|
1410
|
-
|
|
1411
|
-
// Final response received while still awaiting 100 (Continue): the body won't
|
|
1412
|
-
// be sent, so close our half or the stream stays open and never completes.
|
|
1413
|
-
if (state.body != null && !state.bodySent && !stream.writableEnded) {
|
|
1414
|
-
stream.removeListener('continue', writeBodyH2)
|
|
1415
|
-
stream.end()
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
const statusCode = Number(headers[HTTP2_HEADER_STATUS])
|
|
1419
|
-
delete headers[HTTP2_HEADER_STATUS]
|
|
1420
|
-
request.onResponseStarted()
|
|
1421
|
-
state.responseReceived = true
|
|
1422
|
-
|
|
1423
|
-
// A Content-Length in HEAD and 304 responses describes the selected
|
|
1424
|
-
// representation rather than DATA on this stream. Successful CONNECT uses
|
|
1425
|
-
// the upgrade path above; all other final responses use Content-Length as
|
|
1426
|
-
// their DATA payload length.
|
|
1427
|
-
if (request.method !== 'HEAD' && statusCode !== 304) {
|
|
1428
|
-
const contentLength = headers[HTTP2_HEADER_CONTENT_LENGTH]
|
|
1429
|
-
state.responseContentLength = contentLength == null ? null : Number(contentLength)
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
if (state.headersTimeout || state.bodyTimeout) {
|
|
1433
|
-
stream.setTimeout(state.bodyTimeout)
|
|
1434
|
-
}
|
|
1435
|
-
|
|
1436
|
-
// Due to the stream nature, it is possible we face a race condition
|
|
1437
|
-
// where the stream has been assigned, but the request has been aborted
|
|
1438
|
-
// or already completed and headers hasn't been received yet. A late
|
|
1439
|
-
// 'response' delivered after completion would call request.onResponseStart
|
|
1440
|
-
// post-completion, tripping its `assert(!this.completed)` (an uncatchable
|
|
1441
|
-
// throw on the http2 event tick). Guard `completed` here as onEnd/onTrailers
|
|
1442
|
-
// already do; best effort is to release the stream immediately as there's
|
|
1443
|
-
// no value to keep it open.
|
|
1444
|
-
if (request.aborted || request.completed) {
|
|
1445
|
-
releaseRequestStream(stream)
|
|
1446
|
-
return
|
|
1447
|
-
}
|
|
1448
|
-
|
|
1449
|
-
if (request.onResponseStart(statusCode, headers, stream.resume.bind(stream), '') === false) {
|
|
1450
|
-
stream.pause()
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1453
|
-
stream.on('data', onData)
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
|
-
function onEnd () {
|
|
1457
|
-
const stream = this
|
|
1458
|
-
const state = stream[kRequestStreamState]
|
|
1459
|
-
|
|
1460
|
-
if (state == null) {
|
|
1461
|
-
return
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
const { request } = state
|
|
498
|
+
stream.once('response', headers => {
|
|
499
|
+
const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers
|
|
500
|
+
request.onResponseStarted()
|
|
501
|
+
|
|
502
|
+
// Due to the stream nature, it is possible we face a race condition
|
|
503
|
+
// where the stream has been assigned, but the request has been aborted
|
|
504
|
+
// the request remains in-flight and headers hasn't been received yet
|
|
505
|
+
// for those scenarios, best effort is to destroy the stream immediately
|
|
506
|
+
// as there's no value to keep it open.
|
|
507
|
+
if (request.aborted) {
|
|
508
|
+
const err = new RequestAbortedError()
|
|
509
|
+
util.errorRequest(client, request, err)
|
|
510
|
+
util.destroy(stream, err)
|
|
511
|
+
return
|
|
512
|
+
}
|
|
1465
513
|
|
|
1466
|
-
|
|
514
|
+
if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) {
|
|
515
|
+
stream.pause()
|
|
516
|
+
}
|
|
1467
517
|
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
if (!request.aborted && !request.completed) {
|
|
1472
|
-
if (state.responseContentLength != null && state.bytesRead !== state.responseContentLength) {
|
|
1473
|
-
state.abort(new ResponseContentLengthMismatchError())
|
|
1474
|
-
return
|
|
518
|
+
stream.on('data', (chunk) => {
|
|
519
|
+
if (request.onData(chunk) === false) {
|
|
520
|
+
stream.pause()
|
|
1475
521
|
}
|
|
522
|
+
})
|
|
523
|
+
})
|
|
1476
524
|
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
525
|
+
stream.once('end', () => {
|
|
526
|
+
// When state is null, it means we haven't consumed body and the stream still do not have
|
|
527
|
+
// a state.
|
|
528
|
+
// Present specially when using pipeline or stream
|
|
529
|
+
if (stream.state?.state == null || stream.state.state < 6) {
|
|
530
|
+
request.onComplete([])
|
|
1483
531
|
}
|
|
1484
|
-
} else {
|
|
1485
|
-
// Stream ended without receiving a response - this is an error
|
|
1486
|
-
// (e.g., server destroyed the stream before sending headers)
|
|
1487
|
-
state.abort(new InformationalError('HTTP/2: stream half-closed (remote)'), true)
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
function retryRefusedStream (stream, state) {
|
|
1492
|
-
const { client, request } = state
|
|
1493
|
-
|
|
1494
|
-
if (
|
|
1495
|
-
state.responseReceived ||
|
|
1496
|
-
request.aborted ||
|
|
1497
|
-
request.completed ||
|
|
1498
|
-
request[kRefusedStreamRetry] ||
|
|
1499
|
-
!canReplayRequest(request)
|
|
1500
|
-
) {
|
|
1501
|
-
return false
|
|
1502
|
-
}
|
|
1503
532
|
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
533
|
+
if (session[kOpenStreams] === 0) {
|
|
534
|
+
// Stream is closed or half-closed-remote (6), decrement counter and cleanup
|
|
535
|
+
// It does not have sense to continue working with the stream as we do not
|
|
536
|
+
// have yet RST_STREAM support on client-side
|
|
1507
537
|
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
// usable for the retry. Severing also drops the 'close' listener, so the
|
|
1511
|
-
// abandoned stream cannot later complete the retried request.
|
|
1512
|
-
detachRequestStreamForClose(request)
|
|
1513
|
-
state.stream = null
|
|
1514
|
-
state.requestFinalized = true
|
|
1515
|
-
|
|
1516
|
-
completeRequest(client, request)
|
|
1517
|
-
client[kQueue].splice(client[kPendingIdx], 0, request)
|
|
1518
|
-
client[kResume]()
|
|
1519
|
-
|
|
1520
|
-
return true
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
function onError (err) {
|
|
1524
|
-
const stream = this
|
|
1525
|
-
const state = stream[kRequestStreamState]
|
|
1526
|
-
|
|
1527
|
-
if (state == null) {
|
|
1528
|
-
return
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
stream.off('error', onError)
|
|
1532
|
-
|
|
1533
|
-
// Node's HTTP/2 implementation can turn an incomplete Content-Length body
|
|
1534
|
-
// into a protocol stream error instead of emitting 'end'. Prefer the
|
|
1535
|
-
// content-length mismatch error when the received byte count proves it.
|
|
1536
|
-
if (state.responseContentLength != null && state.bytesRead !== state.responseContentLength) {
|
|
1537
|
-
err = new ResponseContentLengthMismatchError()
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
if (typeof stream.rstCode === 'number' && stream.rstCode !== NGHTTP2_NO_ERROR) {
|
|
1541
|
-
err.http2ErrorCode = stream.rstCode
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1544
|
-
if (
|
|
1545
|
-
stream.rstCode === NGHTTP2_REFUSED_STREAM &&
|
|
1546
|
-
retryRefusedStream(stream, state)
|
|
1547
|
-
) {
|
|
1548
|
-
return
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
state.abort(err)
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
function onFrameError (type, code) {
|
|
1555
|
-
const stream = this
|
|
1556
|
-
const state = stream[kRequestStreamState]
|
|
1557
|
-
|
|
1558
|
-
if (state == null) {
|
|
1559
|
-
return
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
stream.off('frameError', onFrameError)
|
|
1563
|
-
state.abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
function onAborted () {
|
|
1567
|
-
this.off('data', onData)
|
|
1568
|
-
}
|
|
1569
|
-
|
|
1570
|
-
function onTimeout () {
|
|
1571
|
-
const stream = this
|
|
1572
|
-
const state = stream[kRequestStreamState]
|
|
538
|
+
session.unref()
|
|
539
|
+
}
|
|
1573
540
|
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
541
|
+
abort(new InformationalError('HTTP/2: stream half-closed (remote)'))
|
|
542
|
+
client[kQueue][client[kRunningIdx]++] = null
|
|
543
|
+
client[kPendingIdx] = client[kRunningIdx]
|
|
544
|
+
client[kResume]()
|
|
545
|
+
})
|
|
1577
546
|
|
|
1578
|
-
|
|
1579
|
-
|
|
547
|
+
stream.once('close', () => {
|
|
548
|
+
session[kOpenStreams] -= 1
|
|
549
|
+
if (session[kOpenStreams] === 0) {
|
|
550
|
+
session.unref()
|
|
551
|
+
}
|
|
552
|
+
})
|
|
1580
553
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
state.abort(err)
|
|
1585
|
-
}
|
|
554
|
+
stream.once('error', function (err) {
|
|
555
|
+
abort(err)
|
|
556
|
+
})
|
|
1586
557
|
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
558
|
+
stream.once('frameError', (type, code) => {
|
|
559
|
+
abort(new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`))
|
|
560
|
+
})
|
|
1590
561
|
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
}
|
|
562
|
+
// stream.on('aborted', () => {
|
|
563
|
+
// // TODO(HTTP/2): Support aborted
|
|
564
|
+
// })
|
|
1594
565
|
|
|
1595
|
-
|
|
566
|
+
// stream.on('timeout', () => {
|
|
567
|
+
// // TODO(HTTP/2): Support timeout
|
|
568
|
+
// })
|
|
1596
569
|
|
|
1597
|
-
stream.
|
|
1598
|
-
|
|
570
|
+
// stream.on('push', headers => {
|
|
571
|
+
// // TODO(HTTP/2): Support push
|
|
572
|
+
// })
|
|
1599
573
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
}
|
|
574
|
+
// stream.on('trailers', headers => {
|
|
575
|
+
// // TODO(HTTP/2): Support trailers
|
|
576
|
+
// })
|
|
1603
577
|
|
|
1604
|
-
|
|
1605
|
-
state.trailers = trailers
|
|
1606
|
-
}
|
|
578
|
+
return true
|
|
1607
579
|
|
|
1608
|
-
function writeBodyH2 () {
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
const { abort, body, client, contentLength, expectsPayload, request } = state
|
|
1613
|
-
|
|
1614
|
-
if (!body || contentLength === 0) {
|
|
1615
|
-
writeBuffer(
|
|
1616
|
-
abort,
|
|
1617
|
-
stream,
|
|
1618
|
-
null,
|
|
1619
|
-
client,
|
|
1620
|
-
request,
|
|
1621
|
-
client[kSocket],
|
|
1622
|
-
contentLength,
|
|
1623
|
-
expectsPayload
|
|
1624
|
-
)
|
|
1625
|
-
} else if (util.isBuffer(body)) {
|
|
1626
|
-
writeBuffer(
|
|
1627
|
-
abort,
|
|
1628
|
-
stream,
|
|
1629
|
-
body,
|
|
1630
|
-
client,
|
|
1631
|
-
request,
|
|
1632
|
-
client[kSocket],
|
|
1633
|
-
contentLength,
|
|
1634
|
-
expectsPayload
|
|
1635
|
-
)
|
|
1636
|
-
} else if (util.isBlobLike(body)) {
|
|
1637
|
-
if (typeof body.stream === 'function') {
|
|
1638
|
-
writeIterable(
|
|
580
|
+
function writeBodyH2 () {
|
|
581
|
+
/* istanbul ignore else: assertion */
|
|
582
|
+
if (!body || contentLength === 0) {
|
|
583
|
+
writeBuffer(
|
|
1639
584
|
abort,
|
|
1640
585
|
stream,
|
|
1641
|
-
|
|
586
|
+
null,
|
|
1642
587
|
client,
|
|
1643
588
|
request,
|
|
1644
589
|
client[kSocket],
|
|
1645
590
|
contentLength,
|
|
1646
591
|
expectsPayload
|
|
1647
592
|
)
|
|
1648
|
-
} else {
|
|
1649
|
-
|
|
593
|
+
} else if (util.isBuffer(body)) {
|
|
594
|
+
writeBuffer(
|
|
595
|
+
abort,
|
|
596
|
+
stream,
|
|
597
|
+
body,
|
|
598
|
+
client,
|
|
599
|
+
request,
|
|
600
|
+
client[kSocket],
|
|
601
|
+
contentLength,
|
|
602
|
+
expectsPayload
|
|
603
|
+
)
|
|
604
|
+
} else if (util.isBlobLike(body)) {
|
|
605
|
+
if (typeof body.stream === 'function') {
|
|
606
|
+
writeIterable(
|
|
607
|
+
abort,
|
|
608
|
+
stream,
|
|
609
|
+
body.stream(),
|
|
610
|
+
client,
|
|
611
|
+
request,
|
|
612
|
+
client[kSocket],
|
|
613
|
+
contentLength,
|
|
614
|
+
expectsPayload
|
|
615
|
+
)
|
|
616
|
+
} else {
|
|
617
|
+
writeBlob(
|
|
618
|
+
abort,
|
|
619
|
+
stream,
|
|
620
|
+
body,
|
|
621
|
+
client,
|
|
622
|
+
request,
|
|
623
|
+
client[kSocket],
|
|
624
|
+
contentLength,
|
|
625
|
+
expectsPayload
|
|
626
|
+
)
|
|
627
|
+
}
|
|
628
|
+
} else if (util.isStream(body)) {
|
|
629
|
+
writeStream(
|
|
630
|
+
abort,
|
|
631
|
+
client[kSocket],
|
|
632
|
+
expectsPayload,
|
|
633
|
+
stream,
|
|
634
|
+
body,
|
|
635
|
+
client,
|
|
636
|
+
request,
|
|
637
|
+
contentLength
|
|
638
|
+
)
|
|
639
|
+
} else if (util.isIterable(body)) {
|
|
640
|
+
writeIterable(
|
|
1650
641
|
abort,
|
|
1651
642
|
stream,
|
|
1652
643
|
body,
|
|
@@ -1656,31 +647,9 @@ function writeBodyH2 () {
|
|
|
1656
647
|
contentLength,
|
|
1657
648
|
expectsPayload
|
|
1658
649
|
)
|
|
650
|
+
} else {
|
|
651
|
+
assert(false)
|
|
1659
652
|
}
|
|
1660
|
-
} else if (util.isStream(body)) {
|
|
1661
|
-
writeStream(
|
|
1662
|
-
abort,
|
|
1663
|
-
client[kSocket],
|
|
1664
|
-
expectsPayload,
|
|
1665
|
-
stream,
|
|
1666
|
-
body,
|
|
1667
|
-
client,
|
|
1668
|
-
request,
|
|
1669
|
-
contentLength
|
|
1670
|
-
)
|
|
1671
|
-
} else if (util.isIterable(body)) {
|
|
1672
|
-
writeIterable(
|
|
1673
|
-
abort,
|
|
1674
|
-
stream,
|
|
1675
|
-
body,
|
|
1676
|
-
client,
|
|
1677
|
-
request,
|
|
1678
|
-
client[kSocket],
|
|
1679
|
-
contentLength,
|
|
1680
|
-
expectsPayload
|
|
1681
|
-
)
|
|
1682
|
-
} else {
|
|
1683
|
-
assert(false)
|
|
1684
653
|
}
|
|
1685
654
|
}
|
|
1686
655
|
|
|
@@ -1739,6 +708,8 @@ function writeStream (abort, socket, expectsPayload, h2stream, body, client, req
|
|
|
1739
708
|
}
|
|
1740
709
|
|
|
1741
710
|
async function writeBlob (abort, h2stream, body, client, request, socket, contentLength, expectsPayload) {
|
|
711
|
+
assert(contentLength === body.size, 'blob body must have content length')
|
|
712
|
+
|
|
1742
713
|
try {
|
|
1743
714
|
if (contentLength != null && contentLength !== body.size) {
|
|
1744
715
|
throw new RequestContentLengthMismatchError()
|