From b82358fe4a054951128801e5226fd4daea76eccc Mon Sep 17 00:00:00 2001
From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com>
Date: Mon, 25 Nov 2019 17:29:04 +0100
Subject: [PATCH] Add `methodRewriting` option (#942)
---
readme.md | 7 ++++++-
source/index.ts | 3 ++-
source/request-as-event-emitter.ts | 2 +-
source/utils/types.ts | 1 +
test/redirects.ts | 27 +++++++++++++++++++++++++++
5 files changed, 37 insertions(+), 3 deletions(-)
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, '');
+});