diff --git a/readme.md b/readme.md index bd3028c0a..ee3fa4c56 100644 --- a/readme.md +++ b/readme.md @@ -408,7 +408,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 21bee3f49..49ef41b14 100644 --- a/source/index.ts +++ b/source/index.ts @@ -56,7 +56,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 87be014a4..9b82276b9 100644 --- a/source/request-as-event-emitter.ts +++ b/source/request-as-event-emitter.ts @@ -96,7 +96,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 b279ffeed..e5a90aa08 100644 --- a/source/utils/types.ts +++ b/source/utils/types.ts @@ -153,6 +153,7 @@ export interface Options extends URLOptions { context?: {[key: string]: unknown}; maxRedirects?: number; lookup?: CacheableLookup['lookup']; + methodRewriting?: boolean; } export interface NormalizedOptions extends Except { diff --git a/test/redirects.ts b/test/redirects.ts index 3142a02f0..b2c40f357 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, ''); +});