Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methodRewriting option #942

Merged
merged 4 commits into from Nov 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion readme.md
Expand Up @@ -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`<br>
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

Expand Down
3 changes: 2 additions & 1 deletion source/index.ts
Expand Up @@ -56,7 +56,8 @@ const defaults: Defaults = {
responseType: 'default',
resolveBodyOnly: false,
maxRedirects: 10,
prefixUrl: ''
prefixUrl: '',
methodRewriting: true
},
handlers: [defaultHandler],
mutableDefaults: false
Expand Down
2 changes: 1 addition & 1 deletion source/request-as-event-emitter.ts
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions source/utils/types.ts
Expand Up @@ -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<Options, keyof URLOptions> {
Expand Down
27 changes: 27 additions & 0 deletions test/redirects.ts
Expand Up @@ -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, '');
});