diff --git a/readme.md b/readme.md index 9b19f8398..8155cb373 100644 --- a/readme.md +++ b/readme.md @@ -410,7 +410,12 @@ Defines if redirect responses should be followed automatically. Note that if a `303` is sent by the server in response to any request type (`POST`, `DELETE`, etc.), Got will automatically request the resource pointed to in the location header via `GET`. This is in accordance with [the spec](https://tools.ietf.org/html/rfc7231#section-6.4.4). -This supports [method rewriting](https://tools.ietf.org/html/rfc7231#section-6.4). For example, when sending a POST request and receiving a `302`, it will resend that request to the new location. +###### methodRewriting + +Type: `boolean`
+Default: `true` + +By default, redirects will use [method rewriting](https://tools.ietf.org/html/rfc7231#section-6.4). For example, when sending a POST request and receiving a `302`, it will resend the body to the new location using the same HTTP method (`POST` in this case). ###### maxRedirects diff --git a/source/index.ts b/source/index.ts index ddea37a9e..577458a76 100644 --- a/source/index.ts +++ b/source/index.ts @@ -58,7 +58,8 @@ const defaults: Defaults = { responseType: 'default', resolveBodyOnly: false, maxRedirects: 10, - prefixUrl: '' + prefixUrl: '', + methodRewriting: true }, handlers: [defaultHandler], mutableDefaults: false diff --git a/source/request-as-event-emitter.ts b/source/request-as-event-emitter.ts index b8df8c092..aa2febada 100644 --- a/source/request-as-event-emitter.ts +++ b/source/request-as-event-emitter.ts @@ -97,7 +97,7 @@ export default (options: NormalizedOptions) => { if (options.followRedirect && Reflect.has(typedResponse.headers, 'location') && redirectCodes.has(statusCode)) { typedResponse.resume(); // We're being redirected, we don't care about the response. - if (statusCode === 303) { + if (statusCode === 303 || options.methodRewriting === false) { if (options.method !== 'GET' && options.method !== 'HEAD') { // Server responded with "see other", indicating that the resource exists at another location, // and the client should request it from that location via GET or HEAD. diff --git a/source/utils/types.ts b/source/utils/types.ts index 0b7429e36..b01203338 100644 --- a/source/utils/types.ts +++ b/source/utils/types.ts @@ -177,6 +177,7 @@ export interface Options extends Partial>, Merge context?: {[key: string]: any}; maxRedirects?: number; lookup?: CacheableLookup['lookup']; + methodRewriting?: boolean; } export interface NormalizedOptions extends Except, Except { diff --git a/test/redirects.ts b/test/redirects.ts index 43cce57ed..bf909f181 100644 --- a/test/redirects.ts +++ b/test/redirects.ts @@ -362,3 +362,30 @@ test('body is passed on POST redirect', withServer, async (t, server, got) => { t.is(body, 'foobar'); }); + +test('method overwriting can be turned off', withServer, async (t, server, got) => { + server.post('/redirect', (_request, response) => { + response.writeHead(302, { + location: '/' + }); + response.end(); + }); + + server.get('/', (_request, response) => { + response.end(); + }); + + const {body} = await got.post('redirect', { + body: 'foobar', + methodRewriting: false, + hooks: { + beforeRedirect: [ + options => { + t.is(options.body, undefined); + } + ] + } + }); + + t.is(body, ''); +});