Content of form data does not persist leading to socket hang up #1513
-
Describe the bug
I am using the When using form-data, the content of Initial run:
Retry run:
Actual behaviorThe content of Expected behaviorThe content of Code to reproduceThe following code is not reproducible "as-is" because it requires credentials, but illustrates the issue. "use strict"
import got, { Options } from "got"
import formData from "form-data"
const test = async function () {
const form = new formData()
form.append("title", "Big Buck Bunny")
form.append("description", "This is a test...")
const initialOptions: Options = {
headers: {
authorization: "Bearer {redactedInvalidAccessToken}",
},
body: form,
responseType: "json",
throwHttpErrors: false,
}
console.log(initialOptions)
const initialVideoResponse: any = await got.put(
`https://peertube.sunknudsen.com/api/v1/videos/f79b7b72-817f-4ba1-9c58-d59d63d64366`,
initialOptions
)
console.log(initialVideoResponse.statusCode, initialVideoResponse.body)
const tokenResponse: any = await got.post(
`https://peertube.sunknudsen.com/api/v1/users/token`,
{
form: {
client_id: "{redactedClientId}",
client_secret: "{redactedClientSecret}",
refresh_token: "{redactedRefreshToken}",
grant_type: "refresh_token",
},
responseType: "json",
throwHttpErrors: false,
}
)
console.log(tokenResponse.statusCode, tokenResponse.body)
const retryOptions: Options = {
headers: {
authorization: `Bearer ${tokenResponse.body.access_token}`,
},
body: form,
responseType: "json",
throwHttpErrors: false,
}
console.log(retryOptions)
// The following request hangs and eventuality throws socket hang up error
const retryVideoResponse: any = await got.put(
`https://peertube.sunknudsen.com/api/v1/videos/f79b7b72-817f-4ba1-9c58-d59d63d64366`,
retryOptions
)
console.log(retryVideoResponse.statusCode, retryVideoResponse.body)
}
test() Checklist
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
This is an expected behavior. If you want to make a request with the same FormData body you should recreate it. Example: const got = require('got');
const FormData = require('form-data');
const genBody = () => {
const form = new FormData();
form.append("title", "Big Buck Bunny");
form.append("description", "This is a test...");
return form;
};
const firstRequest = got('URL', {
body: genBody()
});
const secondRequest = got('URL', {
body: genBody()
}); |
Beta Was this translation helpful? Give feedback.
-
Hi @Giotino, what about when using hooks or retries? The same request is replayed right? |
Beta Was this translation helpful? Give feedback.
-
No, it still not works because the form data can be read only one time. If you're uploading a lot of data, such as files, you should do something like this: const got = require('got');
const FormData = require('form-data');
const genBody = () => {
const form = new FormData();
form.append('A', 'B');
return form;
};
got.post('URL', {
body: genBody(),
hooks: {
beforeRetry: [
options => {
const form = genBody();
options.body = form;
options.headers['content-type'] = `multipart/form-data; boundary=${form.getBoundary()}`;
}
]
}
}); Or, if you're sending a little form (like your example) you can simply do this (because it's using a buffer as body): const got = require('got');
const FormData = require('form-data');
const getStream = require('get-stream');
const form = new FormData();
form.append('A', 'B');
const bufferBody = getStream(form);
got.post('URL', {
body: bufferBody,
headers: {
'content-type': `multipart/form-data; boundary=${form.getBoundary()}`
}
}); Both solution works fine in both cases, but, the first one is (IMO) overkill for small forms, and the second one is going to store the entire form (files included) in RAM before sending it (without taking advantage of the Node.js streams) which is not optimal if you're working with files. |
Beta Was this translation helpful? Give feedback.
No, it still not works because the form data can be read only one time.
If you're uploading a lot of data, such as files, you should do something like this:
Or, if you're sending a little form (like your example) you can simply do this (because it's using a buffer…