3
3
* SPDX-License-Identifier: Apache-2.0
4
4
*/
5
5
6
- import * as fs from 'fs' // eslint-disable-line no-restricted-imports
7
- import * as http from 'http'
8
- import * as https from 'https'
9
- import * as stream from 'stream'
10
- import got , { Response , RequestError , CancelError } from 'got'
11
- import urlToOptions from 'got/dist/source/core/utils/url-to-options'
12
- import Request from 'got/dist/source/core'
13
6
import { VSCODE_EXTENSION_ID } from '../extensions'
14
7
import { getLogger , Logger } from '../logger'
15
8
import { ResourceFetcher } from './resourcefetcher'
16
- import { Timeout , CancellationError , CancelEvent } from '../utilities/timeoutUtils'
17
- import { isCloud9 } from '../extensionUtilities'
18
- import { Headers } from 'got/dist/source/core'
19
-
20
- // XXX: patched Got module for compatability with older VS Code versions (e.g. Cloud9)
21
- // `got` has also deprecated `urlToOptions`
22
- const patchedGot = got . extend ( {
23
- request : ( url , options , callback ) => {
24
- if ( url . protocol === 'https:' ) {
25
- return https . request ( { ...options , ...urlToOptions ( url ) } , callback )
26
- }
27
- return http . request ( { ...options , ...urlToOptions ( url ) } , callback )
28
- } ,
29
- } )
30
-
31
- /** Promise that resolves/rejects when all streams close. Can also access streams directly. */
32
- type FetcherResult = Promise < void > & {
33
- /** Download stream piped to `fsStream`. */
34
- requestStream : Request // `got` doesn't add the correct types to 'on' for some reason
35
- /** Stream writing to the file system. */
36
- fsStream : fs . WriteStream
37
- }
9
+ import { Timeout , CancelEvent } from '../utilities/timeoutUtils'
10
+ import request , { RequestError } from '../request'
38
11
39
12
type RequestHeaders = { eTag ?: string ; gZip ?: boolean }
40
13
@@ -65,20 +38,8 @@ export class HttpResourceFetcher implements ResourceFetcher {
65
38
*
66
39
* @param pipeLocation Optionally pipe the download to a file system location
67
40
*/
68
- public get ( ) : Promise < string | undefined >
69
- public get ( pipeLocation : string ) : FetcherResult
70
- public get ( pipeLocation ?: string ) : Promise < string | undefined > | FetcherResult {
41
+ public get ( ) : Promise < string | undefined > {
71
42
this . logger . verbose ( `downloading: ${ this . logText ( ) } ` )
72
-
73
- if ( pipeLocation ) {
74
- const result = this . pipeGetRequest ( pipeLocation , this . params . timeout )
75
- result . fsStream . on ( 'exit' , ( ) => {
76
- this . logger . verbose ( `downloaded: ${ this . logText ( ) } ` )
77
- } )
78
-
79
- return result
80
- }
81
-
82
43
return this . downloadRequest ( )
83
44
}
84
45
@@ -94,15 +55,15 @@ export class HttpResourceFetcher implements ResourceFetcher {
94
55
public async getNewETagContent ( eTag ?: string ) : Promise < { content ?: string ; eTag : string } > {
95
56
const response = await this . getResponseFromGetRequest ( this . params . timeout , { eTag, gZip : true } )
96
57
97
- const eTagResponse = response . headers . etag
58
+ const eTagResponse = response . headers . get ( ' etag' )
98
59
if ( ! eTagResponse ) {
99
60
throw new Error ( `This URL does not support E-Tags. Cannot use this function for: ${ this . url . toString ( ) } ` )
100
61
}
101
62
102
63
// NOTE: Even with use of `gzip` encoding header, the response content is uncompressed.
103
64
// Most likely due to the http request library uncompressing it for us.
104
- let contents : string | undefined = response . body . toString ( )
105
- if ( response . statusCode === 304 ) {
65
+ let contents : string | undefined = await response . text ( )
66
+ if ( response . status === 304 ) {
106
67
// Explanation: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match
107
68
contents = undefined
108
69
this . logger . verbose ( `E-Tag, ${ eTagResponse } , matched. No content downloaded from: ${ this . url } ` )
@@ -119,7 +80,8 @@ export class HttpResourceFetcher implements ResourceFetcher {
119
80
private async downloadRequest ( ) : Promise < string | undefined > {
120
81
try {
121
82
// HACK(?): receiving JSON as a string without `toString` makes it so we can't deserialize later
122
- const contents = ( await this . getResponseFromGetRequest ( this . params . timeout ) ) . body . toString ( )
83
+ const resp = await this . getResponseFromGetRequest ( this . params . timeout )
84
+ const contents = ( await resp . text ( ) ) . toString ( )
123
85
if ( this . params . onSuccess ) {
124
86
this . params . onSuccess ( contents )
125
87
}
@@ -128,10 +90,10 @@ export class HttpResourceFetcher implements ResourceFetcher {
128
90
129
91
return contents
130
92
} catch ( err ) {
131
- const error = err as CancelError | RequestError
93
+ const error = err as RequestError
132
94
this . logger . verbose (
133
95
`Error downloading ${ this . logText ( ) } : %s` ,
134
- error . message ?? error . code ?? error . response ?. statusMessage ?? error . response ?. statusCode
96
+ error . message ?? error . code ?? error . response . statusText ?? error . response . status
135
97
)
136
98
return undefined
137
99
}
@@ -145,56 +107,30 @@ export class HttpResourceFetcher implements ResourceFetcher {
145
107
getLogger ( ) . debug ( `Download for "${ this . logText ( ) } " ${ event . agent === 'user' ? 'cancelled' : 'timed out' } ` )
146
108
}
147
109
148
- // TODO: make pipeLocation a vscode.Uri
149
- private pipeGetRequest ( pipeLocation : string , timeout ?: Timeout ) : FetcherResult {
150
- const requester = isCloud9 ( ) ? patchedGot : got
151
- const requestStream = requester . stream ( this . url , { headers : this . buildRequestHeaders ( ) } )
152
- const fsStream = fs . createWriteStream ( pipeLocation )
153
-
154
- const done = new Promise < void > ( ( resolve , reject ) => {
155
- const pipe = stream . pipeline ( requestStream , fsStream , ( err ) => {
156
- if ( err instanceof RequestError ) {
157
- return reject ( Object . assign ( new Error ( 'Failed to download file' ) , { code : err . code } ) )
158
- }
159
- err ? reject ( err ) : resolve ( )
160
- } )
161
-
162
- const cancelListener = timeout ?. token . onCancellationRequested ( ( event ) => {
163
- this . logCancellation ( event )
164
- pipe . destroy ( new CancellationError ( event . agent ) )
165
- } )
166
-
167
- pipe . on ( 'close' , ( ) => cancelListener ?. dispose ( ) )
168
- } )
169
-
170
- return Object . assign ( done , { requestStream, fsStream } )
171
- }
172
-
173
- private async getResponseFromGetRequest ( timeout ?: Timeout , headers ?: RequestHeaders ) : Promise < Response < string > > {
174
- const requester = isCloud9 ( ) ? patchedGot : got
175
- const promise = requester ( this . url , {
110
+ private async getResponseFromGetRequest ( timeout ?: Timeout , headers ?: RequestHeaders ) : Promise < Response > {
111
+ const req = request . fetch ( 'GET' , this . url , {
176
112
headers : this . buildRequestHeaders ( headers ) ,
177
113
} )
178
114
179
115
const cancelListener = timeout ?. token . onCancellationRequested ( ( event ) => {
180
116
this . logCancellation ( event )
181
- promise . cancel ( new CancellationError ( event . agent ) . message )
117
+ req . cancel ( )
182
118
} )
183
119
184
- return promise . finally ( ( ) => cancelListener ?. dispose ( ) )
120
+ return req . response . finally ( ( ) => cancelListener ?. dispose ( ) )
185
121
}
186
122
187
123
private buildRequestHeaders ( requestHeaders ?: RequestHeaders ) : Headers {
188
- const headers : Headers = { }
124
+ const headers = new Headers ( )
189
125
190
- headers [ 'User-Agent' ] = VSCODE_EXTENSION_ID . awstoolkit
126
+ headers . set ( 'User-Agent' , VSCODE_EXTENSION_ID . awstoolkit )
191
127
192
128
if ( requestHeaders ?. eTag !== undefined ) {
193
- headers [ 'If-None-Match' ] = requestHeaders . eTag
129
+ headers . set ( 'If-None-Match' , requestHeaders . eTag )
194
130
}
195
131
196
132
if ( requestHeaders ?. gZip ) {
197
- headers [ 'Accept-Encoding' ] = 'gzip'
133
+ headers . set ( 'Accept-Encoding' , 'gzip' )
198
134
}
199
135
200
136
return headers
0 commit comments