Got: Socket hang up error occurs when redirected after submitting FormData

Created on 16 May 2020  路  8Comments  路  Source: sindresorhus/got

  • Got version: 11.3.1
  • Node.js version: 14.2.0 (12.16.3)
  • OS & version: Windows10 (Ubuntu 18.04 on WSL)

Code to reproduce

import got from "got";
import FormData from "form-data";

(async function f() {
    try {
        const body = new FormData();
        body.append("aaa", "bbb");
        const res = await got.post(`http://httpstat.us/302`, { body });
    } catch (err) {
        console.log(err);
    }
})();
internal/streams/legacy.js:61
      throw er; // Unhandled stream error in pipe.
      ^

Error: socket hang up
    at connResetException (internal/errors.js:608:14)
    at TLSSocket.socketOnEnd (_http_client.js:453:23)
    at TLSSocket.emit (events.js:322:22)
    at endReadableNT (_stream_readable.js:1187:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) {
  code: 'ECONNRESET'
}

Additional info

Similar result is produced with the local flask server (no error message, simply get stucked)

from flask import Flask, request, redirect, url_for
app = Flask(__name__)


@app.route('/', methods=["GET", "POST"])
def index():
    return "hello"


@app.route('/redirect', methods=["POST"])
def redirect_to_index():
    return redirect(url_for("index"))


if __name__ == '__main__':
    app.run(debug=True)

Checklist

  • [x] I have read the documentation.
  • [x] I have tried my code with the latest version of Node.js and Got.

Most helpful comment

This bug is due to the fact that FormData is a stream-like object.
It's read until the end for the first request. Then, when it comes the redirect (second request), it's already at the end, so no body is transmitted (while the server is waiting for it).

All 8 comments

This bug is due to the fact that FormData is a stream-like object.
It's read until the end for the first request. Then, when it comes the redirect (second request), it's already at the end, so no body is transmitted (while the server is waiting for it).

@szmarczak
One solution could be calling await this._finalizeBody(); right before sending the body and making the user change (re-initialize) the body in the beforeRedirect (or beforeRequest) hook, but, to me, it seems a little tricky.

Another solution could be reading all the stream a single time and using it as a Buffer when making requests, but this is going to break the stream feature (big file are going to fill the RAM).

@Giotino is right. It is not a bug, it's the intended behavior. If you want to use method rewriting, please use get-stream and pass the output to the body option.

Thank you for your quick response. Giving body: await getStream(body) solves the problem.
By the way, how to remove the body (and re-calculate the headers) in the second request when methodRewriting: false or 303 is returned ?

how to remove the body (and re-calculate the headers) in the second request when methodRewriting: false

What do you mean? The body is removed if you disable method rewriting.

@Giotino @szmarczak Using methodRewriting: false does not seem to work for me, it still causes crash. Only setting followRedirect: false helped.

Perhaps the code still tries to read FormData but simply not sending it despite that?

I have the same issue. Using get-stream results in a HTTP 413 Request Entity Too Large error. However, curl is able to POST the same file without issues. Any ideas on how to fix this?

I have the same issue. Using get-stream results in a HTTP 413 Request Entity Too Large error. However, curl is able to POST the same file without issues. Any ideas on how to fix this?

When using get-stream on a form data are you also setting the boundary header?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

quocnguyen picture quocnguyen  路  4Comments

tkoelpin picture tkoelpin  路  3Comments

f-mer picture f-mer  路  4Comments

joolfe picture joolfe  路  3Comments

framerate picture framerate  路  4Comments