pnpm 11.25.0 → 11.27.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/CHANGELOG.md +128 -0
- package/README.md +11 -15
- package/dist/node_modules/undici/lib/dispatcher/client-h1.js +12 -4
- package/dist/node_modules/undici/lib/handler/retry-handler.js +29 -3
- package/dist/node_modules/undici/lib/web/eventsource/eventsource-stream.js +245 -150
- package/dist/node_modules/undici/lib/web/websocket/connection.js +1 -1
- package/dist/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
- package/dist/node_modules/undici/package.json +1 -1
- package/dist/pnpm.mjs +8975 -8022
- package/dist/worker.js +6375 -3187
- package/package.json +1 -1
- package/dist/node_modules/.package-map.json +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,133 @@
|
|
|
1
1
|
# pnpm
|
|
2
2
|
|
|
3
|
+
## 11.27.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- `nodeDownloadMirrors` can now be set in the global config file (`config.yaml`) and through the `PNPM_CONFIG_NODE_DOWNLOAD_MIRRORS` environment variable, so a Node.js download mirror can be configured once for a machine instead of in every workspace [#12124](https://github.com/pnpm/pnpm/issues/12124), [#13611](https://github.com/pnpm/pnpm/issues/13611).
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
PNPM_CONFIG_NODE_DOWNLOAD_MIRRORS='{"release":"https://npmmirror.com/mirrors/node/"}'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- Added a new setting `trustPolicyExcludePrune` (default: `false`). When enabled, `pnpm add`, `pnpm update`, and `pnpm remove` prune the entries of `trustPolicyExclude` in `pnpm-workspace.yaml` that the freshly written lockfile no longer resolves: versions that are gone are dropped (an entry is removed once none of its versions remain), and entries for packages that are no longer in the lockfile are removed too. Name patterns (`@scope/*`) are always kept. The cleanup is skipped when the install's lockfile does not cover the whole workspace (`sharedWorkspaceLockfile: false`), since entries another project still needs would look stale.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- pnpm now reads the `packageManager`, `devEngines.packageManager` and runtime pins from the workspace root's `package.json` when `lockfileDir` is set. A project that moved its lockfile lost the pins it declared there [#14633](https://github.com/pnpm/pnpm/issues/14633).
|
|
18
|
+
|
|
19
|
+
- Fixed `pnpm add -g`, `pnpm update -g`, and `pnpm remove -g` mutating global bins or install directories after only partially reading an installed package group. If any declared package manifest is missing, malformed, or unreadable, pnpm now fails before activation or removal and leaves the existing global installation intact [pnpm/pnpm#13796](https://github.com/pnpm/pnpm/issues/13796).
|
|
20
|
+
|
|
21
|
+
- `fetch-timeout` now limits how long a request may make no progress. The timer restarts on every chunk that arrives. A large download over a slow connection is no longer aborted while data is still coming in. A connection that stops delivering data still fails after `fetch-timeout` [#14604](https://github.com/pnpm/pnpm/issues/14604).
|
|
22
|
+
|
|
23
|
+
- `pnpm peers check` no longer reports a peer dependency declared as `workspace:^`, `workspace:~`, or a bare `workspace:` as unmet. pnpm reported these as unmet whatever version the linked workspace project supplied [#14770](https://github.com/pnpm/pnpm/issues/14770).
|
|
24
|
+
|
|
25
|
+
- A `readPackage` hook that edits its argument in place no longer changes what a later install in the same command resolves. A `deprecated` notice read from the lockfile no longer carries over to another install either [#13988](https://github.com/pnpm/pnpm/issues/13988).
|
|
26
|
+
|
|
27
|
+
- `pnpm install` now auto-installs missing transitive peers when workspace projects share a dependency at different depths. This also removes incomplete duplicate peer contexts from the lockfile. Fixes [pnpm/pnpm#14840](https://github.com/pnpm/pnpm/issues/14840).
|
|
28
|
+
|
|
29
|
+
- GitHub Actions updates now stop if an action reference changes while its versions are being resolved. Unrelated workflow edits are preserved.
|
|
30
|
+
|
|
31
|
+
GitHub Actions homepage links no longer expose server credentials. GitHub server URLs now require HTTPS, with HTTP allowed only for loopback hosts.
|
|
32
|
+
|
|
33
|
+
- `pnpm licenses list` now reports the runtime downloaded through `devEngines.runtime` with `onFail: "download"`. The command previously failed with `ERR_PNPM_UNSUPPORTED_PACKAGE_TYPE` [#14172](https://github.com/pnpm/pnpm/issues/14172).
|
|
34
|
+
|
|
35
|
+
- pnpm no longer creates a project `pnpm-lock.yaml` when `devEngines.packageManager.onFail` is `download` and lockfile writing is turned off with `lockfile: false` or `--no-lockfile`. pnpm still switches to the pinned version [#14728](https://github.com/pnpm/pnpm/issues/14728).
|
|
36
|
+
|
|
37
|
+
- A `registry` or `@scope:registry` set in an `.npmrc` now wins over the registry a `pnpm login` credential stored in the global `config.yaml` points at. Previously, after logging in to one registry, installs in a project whose `.npmrc` named a private registry went to the logged-in registry instead. They now go to the registry the `.npmrc` names [#14614](https://github.com/pnpm/pnpm/issues/14614).
|
|
38
|
+
|
|
39
|
+
- A patch that gives a dependency a `preinstall`, `install`, or `postinstall` script, or a `binding.gyp`, now runs that build. pnpm asks for build approval first, so the package is listed under "Ignored build scripts" until it is allowed to build. pnpm 12 ran nothing, and pnpm 11 ran it without asking [#14648](https://github.com/pnpm/pnpm/issues/14648).
|
|
40
|
+
|
|
41
|
+
- Registries that share a host but differ by URL path — one JFrog Artifactory, Nexus, AWS CodeArtifact or GitLab Packages instance serving several repositories — now get a metadata cache directory each. Previously they shared one, so resolving a package from one of them could answer with another's versions, integrity hashes and tarball URLs and fail with `ERR_PNPM_TARBALL_URL_MISMATCH` [#13558](https://github.com/pnpm/pnpm/issues/13558).
|
|
42
|
+
|
|
43
|
+
The URL scheme is part of the cache directory name too, so an `http` registry can no longer hand its metadata — which can be rewritten in transit — to a resolution configured for `https` at the same host.
|
|
44
|
+
|
|
45
|
+
The first install after upgrading refetches registry metadata once. The package store is untouched.
|
|
46
|
+
|
|
47
|
+
`pnpm cache view` now labels each entry with the full registry URL. It printed `registry.npmjs.org` before and prints `https://registry.npmjs.org/` now.
|
|
48
|
+
|
|
49
|
+
`pnpm cache list-registries` and `pnpm cache list` print the new directory names. Scripts that parse either command need updating.
|
|
50
|
+
|
|
51
|
+
- Updated the embedded Node.js release keys to the current canonical `nodejs/release-keys` list.
|
|
52
|
+
|
|
53
|
+
- `pnpm sbom` now omits package author fields when the manifest author name is empty or contains only whitespace [pnpm/pnpm#14685](https://github.com/pnpm/pnpm/issues/14685). In a filtered or split workspace run, only a project with no `author` field inherits the workspace root's author.
|
|
54
|
+
|
|
55
|
+
- `pnpm sbom --sbom-format spdx` now writes `creationInfo.created` with whole seconds, such as `2026-09-08T10:38:21Z`. The timestamp carried fractional seconds, which strict SPDX consumers rejected [#14684](https://github.com/pnpm/pnpm/issues/14684).
|
|
56
|
+
|
|
57
|
+
- Windows filesystem operations now retry permission errors for up to one second. Permanent permission errors previously delayed failure by a minute. Sharing and lock violations retain their one-minute retry budget [pnpm/pnpm#14682](https://github.com/pnpm/pnpm/issues/14682).
|
|
58
|
+
|
|
59
|
+
- pnpm now writes `node_modules/.package-map.json` only when `nodeExperimentalPackageMap` is enabled. Nothing reads the file without that setting. An install that stops writing the map removes the one a previous install left.
|
|
60
|
+
|
|
61
|
+
- pnpm now unpacks a downloaded runtime archive into a randomly named directory inside the store. It previously used a predictable path, where another user of a shared store could plant a symlink and redirect the write outside the store ([GHSA-vwc7-r8mq-g2x9](https://github.com/advisories/GHSA-vwc7-r8mq-g2x9)).
|
|
62
|
+
|
|
63
|
+
## 11.26.0
|
|
64
|
+
|
|
65
|
+
### Minor Changes
|
|
66
|
+
|
|
67
|
+
- Catalogs can now resolve workspace dependencies through the `workspace:` protocol.
|
|
68
|
+
|
|
69
|
+
- `pnpm remove` and `pnpm update` now accept `--trust-lockfile`, `--no-trust-lockfile`, `--trust-policy`, `--trust-policy-exclude`, and `--trust-policy-ignore-after`. `pnpm remove` checks the whole lockfile against the active policies unless `--trust-lockfile` is set.
|
|
70
|
+
|
|
71
|
+
- Added `pnpm change check` for CI validation of package versions against the `versioning.epics` bands and `versioning.fixed` groups in `pnpm-workspace.yaml`.
|
|
72
|
+
|
|
73
|
+
### Patch Changes
|
|
74
|
+
|
|
75
|
+
- Fetch and tarball errors and retry logs now hide URL credentials, query strings, and fragments that could expose secrets.
|
|
76
|
+
|
|
77
|
+
- Fixed a race during config dependency updates that could redirect a lockfile write through a symlink [#14322](https://github.com/pnpm/pnpm/issues/14322).
|
|
78
|
+
|
|
79
|
+
- `pnpm add --allow-build=!<pkg>` now correctly denies builds, including in global installs. `pnpm approve-builds <pkg>` and `pnpm approve-builds !<pkg>` now save decisions even when the package is not awaiting approval, with a warning [#14067](https://github.com/pnpm/pnpm/issues/14067).
|
|
80
|
+
|
|
81
|
+
- Fixed `pnpm audit --fix` failing without a value or when followed by another flag. `pnpm audit --fix=override` now respects `saveExact` and `savePrefix` when writing overrides [#13261](https://github.com/pnpm/pnpm/issues/13261), [#11523](https://github.com/pnpm/pnpm/issues/11523).
|
|
82
|
+
|
|
83
|
+
- `pnpm audit` now excludes ignored advisories from vulnerability totals and severity counts, and reports them separately [#14535](https://github.com/pnpm/pnpm/issues/14535).
|
|
84
|
+
|
|
85
|
+
- `pnpm deploy` no longer requires `injectWorkspacePackages`. If a workspace dependency's peer has multiple possible versions, deployment reports `ERR_PNPM_DEPLOY_AMBIGUOUS_PEER` with the conflicting versions. Pin the peer with `overrides` to deploy without injection [#9386](https://github.com/pnpm/pnpm/issues/9386).
|
|
86
|
+
|
|
87
|
+
- Fixed concurrent installs sharing a store occasionally failing with an `ENOENT` error while importing a package file [#14353](https://github.com/pnpm/pnpm/issues/14353).
|
|
88
|
+
|
|
89
|
+
- Fixed installation failures when a linked local dependency provides a peer dependency also provided by an ancestor, including with `pnpm deploy --legacy`.
|
|
90
|
+
|
|
91
|
+
- `pnpm install --node-linker=hoisted` no longer downloads skipped optional dependencies when `node_modules` already exists [#14139](https://github.com/pnpm/pnpm/issues/14139).
|
|
92
|
+
|
|
93
|
+
- Fixed `pnpm install` rejecting a symlinked lockfile when config dependencies are unchanged. Updates to config dependencies also preserve lockfiles with a byte order mark. Writes through symlinked lockfiles remain blocked [#14372](https://github.com/pnpm/pnpm/issues/14372).
|
|
94
|
+
|
|
95
|
+
- `pnpm install` now relinks workspace packages when `publishConfig.linkDirectory` changes. Frozen installs require the lockfile to be regenerated [#14488](https://github.com/pnpm/pnpm/issues/14488).
|
|
96
|
+
|
|
97
|
+
- Auto-installed optional peers now satisfy their declared range even when the workspace root uses a version outside that range [#13867](https://github.com/pnpm/pnpm/issues/13867).
|
|
98
|
+
|
|
99
|
+
- Fixed global virtual store paths for dependency cycles to consistently account for the runtime engine when dependencies have allowed builds [#14341](https://github.com/pnpm/pnpm/issues/14341).
|
|
100
|
+
|
|
101
|
+
- Standalone installations now preserve the bundled `node-gyp` files needed to build native dependencies.
|
|
102
|
+
|
|
103
|
+
- Downloaded runtimes are now available to dependency lifecycle scripts during installation.
|
|
104
|
+
|
|
105
|
+
- Node.js downloads from `nodeDownloadMirrors` now use URL-scoped npm credentials, including bearer tokens, basic auth, and `tokenHelper` [#14334](https://github.com/pnpm/pnpm/issues/14334).
|
|
106
|
+
|
|
107
|
+
- Fixed `globalDir` and `globalBinDir` handling in global configuration and environment variables, including `~/` expansion. This fixes `pnpm add -g` failing after `pnpm config set -g global-bin-dir` [#14336](https://github.com/pnpm/pnpm/issues/14336).
|
|
108
|
+
|
|
109
|
+
- The JavaScript pnpm can again switch to the project's pinned pnpm version on hosts without a matching native binary. If the requested version requires an unavailable native binary, the error now identifies the unsupported host [#13622](https://github.com/pnpm/pnpm/issues/13622).
|
|
110
|
+
|
|
111
|
+
- Global `pnpm config` commands now skip project package manager version switching, allowing authentication to be configured before downloading the pinned version [#14463](https://github.com/pnpm/pnpm/issues/14463).
|
|
112
|
+
|
|
113
|
+
- `pnpm self-update`, `pnpm with`, and automatic version switching no longer wait through registry retries when a configured registry has no signatures and `registry.npmjs.org` is unavailable [#14483](https://github.com/pnpm/pnpm/issues/14483).
|
|
114
|
+
|
|
115
|
+
- Fixed argument forwarding on Windows with `shellEmulator` enabled. Trailing backslashes, line breaks, and literal shell expressions are preserved [#14548](https://github.com/pnpm/pnpm/issues/14548).
|
|
116
|
+
|
|
117
|
+
- Relative `scriptShell` paths now resolve from the workspace root. Bare command names such as `bash` still use `PATH` [#14422](https://github.com/pnpm/pnpm/issues/14422).
|
|
118
|
+
|
|
119
|
+
- `pnpm import` now preserves the project-local lockfile when `lockfileDir` points elsewhere and restores the destination lockfile on failure. Branch lockfile imports leave the shared lockfile unchanged [#14563](https://github.com/pnpm/pnpm/issues/14563).
|
|
120
|
+
|
|
121
|
+
- `catalogMode` and `--save-catalog` no longer move local paths, tarballs, or `workspace:<path>` specifiers into catalogs [#14437](https://github.com/pnpm/pnpm/issues/14437).
|
|
122
|
+
|
|
123
|
+
- `--side-effects-cache`, `--no-side-effects-cache`, and `PNPM_CONFIG_SIDE_EFFECTS_CACHE` now toggle only the local cache, preserving any remote cache configured in `sideEffectsCache`.
|
|
124
|
+
|
|
125
|
+
- `pnpm unpublish` now handles registry two-factor authentication challenges through web authentication or a one-time password prompt [#14464](https://github.com/pnpm/pnpm/issues/14464).
|
|
126
|
+
|
|
127
|
+
- `pnpm outdated` and `pnpm update` now follow GitHub Actions references using self-repository syntax, such as `uses: $/.github/actions/setup`.
|
|
128
|
+
|
|
129
|
+
- `pnpm remove` now accepts `--unsafe-perm`.
|
|
130
|
+
|
|
3
131
|
## 11.25.0
|
|
4
132
|
|
|
5
133
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -52,11 +52,16 @@ To quote the [Rush](https://rushjs.io/) team:
|
|
|
52
52
|
</a>
|
|
53
53
|
</td>
|
|
54
54
|
<td align="center" valign="middle">
|
|
55
|
-
<a href="https://notion.com/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
55
|
+
<a href="https://notion.com/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
|
|
56
|
+
</td>
|
|
57
|
+
</tr>
|
|
58
|
+
<tr>
|
|
59
|
+
<td align="center" valign="middle">
|
|
60
|
+
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
56
61
|
<picture>
|
|
57
|
-
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/
|
|
58
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/
|
|
59
|
-
<img src="https://pnpm.io/img/users/
|
|
62
|
+
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
|
|
63
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
|
|
64
|
+
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
|
|
60
65
|
</picture>
|
|
61
66
|
</a>
|
|
62
67
|
</td>
|
|
@@ -101,15 +106,6 @@ To quote the [Rush](https://rushjs.io/) team:
|
|
|
101
106
|
</picture>
|
|
102
107
|
</a>
|
|
103
108
|
</td>
|
|
104
|
-
<td align="center" valign="middle">
|
|
105
|
-
<a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
106
|
-
<picture>
|
|
107
|
-
<source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
|
|
108
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
|
|
109
|
-
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
|
|
110
|
-
</picture>
|
|
111
|
-
</a>
|
|
112
|
-
</td>
|
|
113
109
|
<td align="center" valign="middle">
|
|
114
110
|
<a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
115
111
|
<picture>
|
|
@@ -119,8 +115,6 @@ To quote the [Rush](https://rushjs.io/) team:
|
|
|
119
115
|
</picture>
|
|
120
116
|
</a>
|
|
121
117
|
</td>
|
|
122
|
-
</tr>
|
|
123
|
-
<tr>
|
|
124
118
|
<td align="center" valign="middle">
|
|
125
119
|
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
126
120
|
<picture>
|
|
@@ -130,6 +124,8 @@ To quote the [Rush](https://rushjs.io/) team:
|
|
|
130
124
|
</picture>
|
|
131
125
|
</a>
|
|
132
126
|
</td>
|
|
127
|
+
</tr>
|
|
128
|
+
<tr>
|
|
133
129
|
<td align="center" valign="middle">
|
|
134
130
|
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=readme" target="_blank" rel="noopener noreferrer">
|
|
135
131
|
<picture>
|
|
@@ -876,7 +876,7 @@ async function connectH1 (client, socket) {
|
|
|
876
876
|
|
|
877
877
|
function clearIdleSocketValidation (socket) {
|
|
878
878
|
if (socket[kIdleSocketValidationTimeout]) {
|
|
879
|
-
|
|
879
|
+
clearImmediate(socket[kIdleSocketValidationTimeout])
|
|
880
880
|
socket[kIdleSocketValidationTimeout] = null
|
|
881
881
|
}
|
|
882
882
|
|
|
@@ -885,15 +885,23 @@ function clearIdleSocketValidation (socket) {
|
|
|
885
885
|
|
|
886
886
|
function scheduleIdleSocketValidation (client, socket) {
|
|
887
887
|
socket[kIdleSocketValidation] = 1
|
|
888
|
-
|
|
888
|
+
// Yield to the check phase (after poll) so unsolicited bytes / FIN / RST
|
|
889
|
+
// already pending on this idle keep-alive socket are processed before the
|
|
890
|
+
// next request is written (GHSA-35p6-xmwp-9g52).
|
|
891
|
+
//
|
|
892
|
+
// setTimeout(0) pays Node's ~1ms timer floor on every sequential reuse
|
|
893
|
+
// (#5493). setImmediate avoids that, but an *unref'd* Immediate lets poll
|
|
894
|
+
// block for ~500ms when the event loop is otherwise idle (#5600 / #5606).
|
|
895
|
+
// A ref'd Immediate both keeps the pending request alive and makes poll
|
|
896
|
+
// return immediately — the hybrid those issues asked for.
|
|
897
|
+
socket[kIdleSocketValidationTimeout] = setImmediate(() => {
|
|
889
898
|
socket[kIdleSocketValidationTimeout] = null
|
|
890
899
|
socket[kIdleSocketValidation] = 2
|
|
891
900
|
|
|
892
901
|
if (client[kSocket] === socket && !socket.destroyed) {
|
|
893
902
|
client[kResume]()
|
|
894
903
|
}
|
|
895
|
-
}
|
|
896
|
-
socket[kIdleSocketValidationTimeout].unref?.()
|
|
904
|
+
})
|
|
897
905
|
}
|
|
898
906
|
|
|
899
907
|
/**
|
|
@@ -90,6 +90,7 @@ class RetryHandler {
|
|
|
90
90
|
this.end = null
|
|
91
91
|
this.etag = null
|
|
92
92
|
this.resume = null
|
|
93
|
+
this.headersSent = false
|
|
93
94
|
|
|
94
95
|
// Handle possible onConnect duplication
|
|
95
96
|
this.handler.onConnect(reason => {
|
|
@@ -102,6 +103,20 @@ class RetryHandler {
|
|
|
102
103
|
})
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
checkpointResponseEnd (headers, resume) {
|
|
107
|
+
if (this.end == null && this.opts.method !== 'HEAD') {
|
|
108
|
+
const contentLength = headers['content-length']
|
|
109
|
+
this.end = contentLength != null ? Number(contentLength) - 1 : null
|
|
110
|
+
|
|
111
|
+
assert(
|
|
112
|
+
this.end == null || Number.isFinite(this.end),
|
|
113
|
+
'invalid content-length'
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this.resume = this.end != null ? resume : null
|
|
118
|
+
}
|
|
119
|
+
|
|
105
120
|
onRequestSent () {
|
|
106
121
|
if (this.handler.onRequestSent) {
|
|
107
122
|
this.handler.onRequestSent()
|
|
@@ -191,6 +206,8 @@ class RetryHandler {
|
|
|
191
206
|
|
|
192
207
|
if (statusCode >= 300) {
|
|
193
208
|
if (this.retryOpts.statusCodes.includes(statusCode) === false) {
|
|
209
|
+
this.headersSent = true
|
|
210
|
+
this.checkpointResponseEnd(headers, resume)
|
|
194
211
|
return this.handler.onHeaders(
|
|
195
212
|
statusCode,
|
|
196
213
|
rawHeaders,
|
|
@@ -259,8 +276,15 @@ class RetryHandler {
|
|
|
259
276
|
|
|
260
277
|
const { start, size, end = size - 1 } = contentRange
|
|
261
278
|
|
|
262
|
-
|
|
263
|
-
|
|
279
|
+
if (this.start !== start || (this.end != null && this.end !== end)) {
|
|
280
|
+
this.abort(
|
|
281
|
+
new RequestRetryError('Content-Range mismatch', statusCode, {
|
|
282
|
+
headers,
|
|
283
|
+
data: { count: this.retryCount }
|
|
284
|
+
})
|
|
285
|
+
)
|
|
286
|
+
return false
|
|
287
|
+
}
|
|
264
288
|
|
|
265
289
|
this.resume = resume
|
|
266
290
|
return true
|
|
@@ -272,6 +296,7 @@ class RetryHandler {
|
|
|
272
296
|
const range = parseRangeHeader(headers['content-range'])
|
|
273
297
|
|
|
274
298
|
if (range == null) {
|
|
299
|
+
this.headersSent = true
|
|
275
300
|
return this.handler.onHeaders(
|
|
276
301
|
statusCode,
|
|
277
302
|
rawHeaders,
|
|
@@ -310,6 +335,7 @@ class RetryHandler {
|
|
|
310
335
|
)
|
|
311
336
|
|
|
312
337
|
this.resume = resume
|
|
338
|
+
this.headersSent = true
|
|
313
339
|
this.etag = headers.etag != null ? headers.etag : null
|
|
314
340
|
|
|
315
341
|
// Weak etags are not useful for comparison nor cache
|
|
@@ -349,7 +375,7 @@ class RetryHandler {
|
|
|
349
375
|
}
|
|
350
376
|
|
|
351
377
|
onError (err) {
|
|
352
|
-
if (this.aborted || isDisturbed(this.opts.body)) {
|
|
378
|
+
if (this.aborted || isDisturbed(this.opts.body) || (this.headersSent && this.resume == null)) {
|
|
353
379
|
return this.handler.onError(err)
|
|
354
380
|
}
|
|
355
381
|
|