@@ -20,13 +20,8 @@ import urlToOptions from './utils/url-to-options';
20
20
import { RequestFunction , NormalizedOptions , Response , ResponseObject , AgentByProtocol } from './utils/types' ;
21
21
import dynamicRequire from './utils/dynamic-require' ;
22
22
23
- export type GetMethodRedirectCodes = 300 | 301 | 302 | 303 | 304 | 305 | 307 | 308 ;
24
- export type AllMethodRedirectCodes = 300 | 303 | 307 | 308 ;
25
- export type WithoutBody = 'GET' | 'HEAD' ;
26
-
27
- const getMethodRedirectCodes : ReadonlySet < GetMethodRedirectCodes > = new Set ( [ 300 , 301 , 302 , 303 , 304 , 305 , 307 , 308 ] ) ;
28
- const allMethodRedirectCodes : ReadonlySet < AllMethodRedirectCodes > = new Set ( [ 300 , 303 , 307 , 308 ] ) ;
29
- const withoutBody : ReadonlySet < WithoutBody > = new Set ( [ 'GET' , 'HEAD' ] ) ;
23
+ const redirectCodes : ReadonlySet < number > = new Set ( [ 300 , 301 , 302 , 303 , 304 , 307 , 308 ] ) ;
24
+ const withoutBody : ReadonlySet < string > = new Set ( [ 'GET' , 'HEAD' ] ) ;
30
25
31
26
export interface RequestAsEventEmitter extends EventEmitter {
32
27
retry : < T extends Error > ( error : T ) => boolean ;
@@ -143,46 +138,50 @@ export default (options: NormalizedOptions, input?: TransformStream) => {
143
138
await Promise . all ( promises ) ;
144
139
}
145
140
146
- if ( options . followRedirect && 'location' in typedResponse . headers ) {
147
- if ( allMethodRedirectCodes . has ( statusCode as AllMethodRedirectCodes ) || ( getMethodRedirectCodes . has ( statusCode as GetMethodRedirectCodes ) && ( options . method === 'GET' || options . method === 'HEAD' ) ) ) {
148
- typedResponse . resume ( ) ; // We're being redirected, we don't care about the response.
149
-
150
- if ( statusCode === 303 ) {
151
- // Server responded with "see other", indicating that the resource exists at another location,
152
- // and the client should request it from that location via GET or HEAD.
153
- options . method = 'GET' ;
154
- }
141
+ if ( options . followRedirect && Reflect . has ( typedResponse . headers , 'location' ) && redirectCodes . has ( statusCode ) ) {
142
+ typedResponse . resume ( ) ; // We're being redirected, we don't care about the response.
155
143
156
- if ( redirects . length >= options . maxRedirects ) {
157
- throw new MaxRedirectsError ( typedResponse , options . maxRedirects , options ) ;
158
- }
144
+ if ( statusCode === 303 && options . method !== 'GET' && options . method !== 'HEAD' ) {
145
+ // Server responded with "see other", indicating that the resource exists at another location,
146
+ // and the client should request it from that location via GET or HEAD.
147
+ options . method = 'GET' ;
159
148
160
- // Handles invalid URLs. See https://github.com/sindresorhus/got/issues/604
161
- const redirectBuffer = Buffer . from ( typedResponse . headers . location , 'binary' ) . toString ( ) ;
162
- const redirectURL = new URL ( redirectBuffer , currentUrl ) ;
163
- redirectString = redirectURL . toString ( ) ;
149
+ delete options . json ;
150
+ delete options . form ;
151
+ delete options . body ;
152
+ }
164
153
165
- redirects . push ( redirectString ) ;
154
+ if ( redirects . length >= options . maxRedirects ) {
155
+ throw new MaxRedirectsError ( typedResponse , options . maxRedirects , options ) ;
156
+ }
166
157
167
- const redirectOptions = {
168
- ...options ,
169
- port : undefined ,
170
- auth : undefined ,
171
- ...urlToOptions ( redirectURL )
172
- } ;
158
+ // Handles invalid URLs. See https://github.com/sindresorhus/got/issues/604
159
+ const redirectBuffer = Buffer . from ( typedResponse . headers . location , 'binary' ) . toString ( ) ;
160
+ const redirectURL = new URL ( redirectBuffer , currentUrl ) ;
161
+ redirectString = redirectURL . toString ( ) ;
173
162
174
- for ( const hook of options . hooks . beforeRedirect ) {
175
- // eslint-disable-next-line no-await-in-loop
176
- await hook ( redirectOptions , typedResponse ) ;
177
- }
163
+ redirects . push ( redirectString ) ;
178
164
179
- emitter . emit ( 'redirect' , response , redirectOptions ) ;
165
+ const redirectOptions = {
166
+ ...options ,
167
+ port : undefined ,
168
+ auth : undefined ,
169
+ ...urlToOptions ( redirectURL )
170
+ } ;
180
171
181
- await get ( redirectOptions ) ;
182
- return ;
172
+ for ( const hook of options . hooks . beforeRedirect ) {
173
+ // eslint-disable-next-line no-await-in-loop
174
+ await hook ( redirectOptions , typedResponse ) ;
183
175
}
176
+
177
+ emitter . emit ( 'redirect' , response , redirectOptions ) ;
178
+
179
+ await get ( redirectOptions ) ;
180
+ return ;
184
181
}
185
182
183
+ delete options . body ;
184
+
186
185
getResponse ( typedResponse , options , emitter ) ;
187
186
} catch ( error ) {
188
187
emitError ( error ) ;
@@ -362,7 +361,7 @@ export default (options: NormalizedOptions, input?: TransformStream) => {
362
361
const isForm = ! is . nullOrUndefined ( options . form ) ;
363
362
const isJSON = ! is . nullOrUndefined ( options . json ) ;
364
363
const isBody = ! is . nullOrUndefined ( body ) ;
365
- if ( ( isBody || isForm || isJSON ) && withoutBody . has ( options . method as WithoutBody ) ) {
364
+ if ( ( isBody || isForm || isJSON ) && withoutBody . has ( options . method ) ) {
366
365
throw new TypeError ( `The \`${ options . method } \` method cannot be used with a body` ) ;
367
366
}
368
367
0 commit comments