fix: do not silently exit on bad HTTPS requests (#3768)

close #3756
close #3754
This commit is contained in:
Zoltan Kochan
2021-09-13 04:44:40 +03:00
committed by GitHub
parent 11a934da15
commit bab1723854
13 changed files with 65 additions and 37 deletions

View File

@@ -0,0 +1,7 @@
---
"@pnpm/fetch": patch
"@pnpm/fetching-types": patch
"@pnpm/server": patch
---
The Node.js process should not silently exit on some broken HTTPS requests.

View File

@@ -36,11 +36,10 @@
"@pnpm/fetching-types": "workspace:2.2.0",
"@pnpm/npm-registry-agent": "workspace:5.0.0",
"@zkochan/retry": "^0.2.0",
"node-fetch": "^2.6.1"
"node-fetch": "3.0.0-beta.9"
},
"devDependencies": {
"@pnpm/logger": "^4.0.0",
"@types/node-fetch": "^2.5.7",
"cpy-cli": "^3.1.1",
"nock": "12.0.3"
},

View File

@@ -39,7 +39,7 @@ export default async function fetchRetry (url: RequestInfo, opts: RequestInit =
return await new Promise((resolve, reject) => op.attempt(async (attempt) => {
try {
// this will be retried
const res = await fetch(url, opts)
const res = await fetch(url as any, opts) // eslint-disable-line
if ((res.status >= 500 && res.status < 600) || res.status === 429) {
throw new ResponseError(res)
} else {

View File

@@ -5,7 +5,7 @@ import nock from 'nock'
test('fetchFromRegistry', async () => {
const fetchFromRegistry = createFetchFromRegistry({})
const res = await fetchFromRegistry('https://registry.npmjs.org/is-positive')
const metadata = await res.json()
const metadata = await res.json() as any // eslint-disable-line
expect(metadata.name).toEqual('is-positive')
expect(metadata.versions['1.0.0'].scripts).not.toBeTruthy()
})
@@ -13,7 +13,7 @@ test('fetchFromRegistry', async () => {
test('fetchFromRegistry fullMetadata', async () => {
const fetchFromRegistry = createFetchFromRegistry({ fullMetadata: true })
const res = await fetchFromRegistry('https://registry.npmjs.org/is-positive')
const metadata = await res.json()
const metadata = await res.json() as any // eslint-disable-line
expect(metadata.name).toEqual('is-positive')
expect(metadata.versions['1.0.0'].scripts).toBeTruthy()
})

View File

@@ -29,7 +29,7 @@
},
"funding": "https://opencollective.com/pnpm",
"dependencies": {
"@types/node-fetch": "^2.5.7",
"@zkochan/retry": "^0.2.0"
"@zkochan/retry": "^0.2.0",
"node-fetch": "3.0.0-beta.9"
}
}

View File

@@ -683,7 +683,8 @@ test('error is thrown when package is not found in the registry', async () => {
},
{
status: 404,
statusText: 'Not Found',
// statusText: 'Not Found',
statusText: '',
},
notExistingPackage
)
@@ -720,7 +721,8 @@ test('extra info is shown if package has valid semver appended', async () => {
},
{
status: 404,
statusText: 'Not Found',
// statusText: 'Not Found',
statusText: '',
},
notExistingPackage
)
@@ -761,7 +763,8 @@ test('error is thrown when package needs authorization', async () => {
},
{
status: 403,
statusText: 'Forbidden',
// statusText: 'Forbidden',
statusText: '',
},
'needs-auth'
)

View File

@@ -46,7 +46,7 @@ export async function getNodeDir (opts: NvmNodeCommandOptions) {
await fs.promises.mkdir(nodesDir, { recursive: true })
if (wantedNodeVersion == null) {
const response = await fetch('https://registry.npmjs.org/node')
wantedNodeVersion = (await response.json())['dist-tags'].lts
wantedNodeVersion = (await response.json() as any)['dist-tags'].lts // eslint-disable-line
if (wantedNodeVersion == null) {
throw new Error('Could not resolve LTS version of Node.js')
}
@@ -104,7 +104,7 @@ async function downloadAndUnpackZip (
const tmp = path.join(tempy.directory(), 'pnpm.zip')
const dest = fs.createWriteStream(tmp)
await new Promise((resolve, reject) => {
response.body.pipe(dest).on('error', reject).on('close', resolve)
response.body!.pipe(dest).on('error', reject).on('close', resolve)
})
const zip = new AdmZip(tmp)
const nodeDir = path.dirname(targetDir)

View File

@@ -37,12 +37,11 @@
"@pnpm/package-requester": "workspace:15.1.1",
"@pnpm/package-store": "workspace:12.0.14",
"@types/mz": "^2.7.3",
"@types/node-fetch": "^2.5.7",
"@types/uuid": "^8.3.0",
"@zkochan/rimraf": "^2.1.1",
"is-port-reachable": "3.0.0",
"load-json-file": "^6.2.0",
"node-fetch": "^2.6.1",
"node-fetch": "3.0.0-beta.9",
"tempy": "^1.0.0"
},
"dependencies": {

View File

@@ -74,7 +74,7 @@ function limitFetch<T>(limit: (fn: () => PromiseLike<T>) => Promise<T>, url: str
if (!response.ok) {
throw await response.json()
}
const json = await response.json()
const json = await response.json() as any // eslint-disable-line
if (json.error) {
throw json.error
}

View File

@@ -292,7 +292,7 @@ test('server should only allow POST', async () => {
// Ensure 405 error is received
const response = await fetch(`${remotePrefix}/a-random-endpoint`, { method: method })
expect(response.status).toBe(405)
expect((await response.json()).error).toBeTruthy()
expect((await response.json() as any).error).toBeTruthy() // eslint-disable-line
}
await server.close()
@@ -315,7 +315,7 @@ test('server route not found', async () => {
const response = await fetch(`${remotePrefix}/a-random-endpoint`, { method: 'POST' })
// Ensure error is correct
expect(response.status).toBe(404)
expect((await response.json()).error).toBeTruthy()
expect((await response.json() as any).error).toBeTruthy() // eslint-disable-line
await server.close()
await storeCtrlForServer.close()

View File

@@ -167,20 +167,20 @@ export default (
? opts.onProgress
: undefined
let downloaded = 0
res.body.on('data', (chunk: Buffer) => {
res.body!.on('data', (chunk: Buffer) => {
downloaded += chunk.length
if (onProgress != null) onProgress(downloaded)
})
// eslint-disable-next-line no-async-promise-executor
return await new Promise<FetchResult>(async (resolve, reject) => {
const stream = res.body
const stream = res.body!
.on('error', reject)
try {
const [integrityCheckResult, filesIndex] = await Promise.all([
opts.integrity ? safeCheckStream(res.body, opts.integrity, url) : true,
opts.cafs.addFilesFromTarball(res.body, opts.manifest),
opts.cafs.addFilesFromTarball(res.body!, opts.manifest),
waitTillClosed({ stream, size, getDownloaded: () => downloaded, url }),
])
if (integrityCheckResult !== true) {

View File

@@ -299,7 +299,8 @@ test('throw error when accessing private package w/o authorization', async () =>
},
{
status: 403,
statusText: 'Forbidden',
// statusText: 'Forbidden',
statusText: '',
}
)
)

51
pnpm-lock.yaml generated
View File

@@ -539,21 +539,19 @@ importers:
'@pnpm/fetching-types': workspace:2.2.0
'@pnpm/logger': ^4.0.0
'@pnpm/npm-registry-agent': workspace:5.0.0
'@types/node-fetch': ^2.5.7
'@zkochan/retry': ^0.2.0
cpy-cli: ^3.1.1
nock: 12.0.3
node-fetch: ^2.6.1
node-fetch: 3.0.0-beta.9
dependencies:
'@pnpm/core-loggers': link:../core-loggers
'@pnpm/fetching-types': link:../fetching-types
'@pnpm/npm-registry-agent': link:../npm-registry-agent
'@zkochan/retry': 0.2.0
node-fetch: 2.6.1
node-fetch: 3.0.0-beta.9
devDependencies:
'@pnpm/fetch': 'link:'
'@pnpm/logger': 4.0.0
'@types/node-fetch': 2.5.12
cpy-cli: 3.1.1
nock: 12.0.3
@@ -573,11 +571,11 @@ importers:
packages/fetching-types:
specifiers:
'@pnpm/fetching-types': 'link:'
'@types/node-fetch': ^2.5.7
'@zkochan/retry': ^0.2.0
node-fetch: 3.0.0-beta.9
dependencies:
'@types/node-fetch': 2.5.12
'@zkochan/retry': 0.2.0
node-fetch: 3.0.0-beta.9
devDependencies:
'@pnpm/fetching-types': 'link:'
@@ -2909,12 +2907,11 @@ importers:
'@pnpm/store-controller-types': workspace:11.0.5
'@pnpm/types': workspace:7.4.0
'@types/mz': ^2.7.3
'@types/node-fetch': ^2.5.7
'@types/uuid': ^8.3.0
'@zkochan/rimraf': ^2.1.1
is-port-reachable: 3.0.0
load-json-file: ^6.2.0
node-fetch: ^2.6.1
node-fetch: 3.0.0-beta.9
p-limit: ^3.1.0
promise-share: ^1.0.0
tempy: ^1.0.0
@@ -2933,12 +2930,11 @@ importers:
'@pnpm/package-store': link:../package-store
'@pnpm/server': 'link:'
'@types/mz': 2.7.4
'@types/node-fetch': 2.5.12
'@types/uuid': 8.3.1
'@zkochan/rimraf': 2.1.1
is-port-reachable: 3.0.0
load-json-file: 6.2.0
node-fetch: 2.6.1
node-fetch: 3.0.0-beta.9
tempy: 1.0.1
packages/sort-packages:
@@ -4952,12 +4948,6 @@ packages:
'@types/node': 16.7.5
dev: true
/@types/node-fetch/2.5.12:
resolution: {integrity: sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==}
dependencies:
'@types/node': 16.7.5
form-data: 3.0.1
/@types/node/12.20.21:
resolution: {integrity: sha512-Qk7rOvV2A4vNgXNS88vEvbJE1NDFPCQ8AU+pNElrU2bA4yrRDef3fg3SUe+xkwyin3Bpg/Xh5JkNWTlsOcS2tA==}
dev: true
@@ -6066,6 +6056,7 @@ packages:
/asynckit/0.4.0:
resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=}
dev: true
/at-least-node/1.0.0:
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
@@ -6787,6 +6778,7 @@ packages:
engines: {node: '>= 0.8'}
dependencies:
delayed-stream: 1.0.0
dev: true
/command-exists/1.2.9:
resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==}
@@ -7164,6 +7156,10 @@ packages:
/data-uri-to-buffer/2.0.2:
resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
/data-uri-to-buffer/3.0.1:
resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==}
engines: {node: '>= 6'}
/data-urls/1.1.0:
resolution: {integrity: sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==}
dependencies:
@@ -7350,6 +7346,7 @@ packages:
/delayed-stream/1.0.0:
resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=}
engines: {node: '>=0.4.0'}
dev: true
/delegates/1.0.0:
resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=}
@@ -8205,6 +8202,15 @@ packages:
bser: 2.1.1
dev: true
/fetch-blob/2.1.2:
resolution: {integrity: sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==}
engines: {node: ^10.17.0 || >=12.3.0}
peerDependencies:
domexception: '*'
peerDependenciesMeta:
domexception:
optional: true
/figures/1.7.0:
resolution: {integrity: sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=}
engines: {node: '>=0.10.0'}
@@ -8383,6 +8389,7 @@ packages:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.32
dev: true
/forwarded/0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
@@ -10893,12 +10900,14 @@ packages:
/mime-db/1.49.0:
resolution: {integrity: sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==}
engines: {node: '>= 0.6'}
dev: true
/mime-types/2.1.32:
resolution: {integrity: sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==}
engines: {node: '>= 0.6'}
dependencies:
mime-db: 1.49.0
dev: true
/mime/1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
@@ -11207,6 +11216,16 @@ packages:
/node-fetch/2.6.1:
resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==}
engines: {node: 4.x || >=6.0.0}
dev: true
/node-fetch/3.0.0-beta.9:
resolution: {integrity: sha512-RdbZCEynH2tH46+tj0ua9caUHVWrd/RHnRfvly2EVdqGmI3ndS1Vn/xjm5KuGejDt2RNDQsVRLPNd2QPwcewVg==}
engines: {node: ^10.17 || >=12.3}
dependencies:
data-uri-to-buffer: 3.0.1
fetch-blob: 2.1.2
transitivePeerDependencies:
- domexception
/node-gyp-build/4.2.3:
resolution: {integrity: sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==}