superagent: fix multipart form-data

This commit is contained in:
Girish Ramakrishnan
2025-02-18 16:55:31 +01:00
parent d75e95a23d
commit 4e038142da
+16 -10
View File
@@ -82,7 +82,7 @@ class Request {
if (error) reject(error); else resolve(result); if (error) reject(error); else resolve(result);
}); });
if (this.body) request.write(this.body, 'utf8'); if (this.body) request.write(this.body);
request.end(); request.end();
}); });
@@ -134,11 +134,11 @@ class Request {
const contentType = this.options.headers['content-type']; const contentType = this.options.headers['content-type'];
if (!contentType || contentType === 'application/json') { if (!contentType || contentType === 'application/json') {
this.options.headers['content-type'] = 'application/json'; this.options.headers['content-type'] = 'application/json';
this.body = JSON.stringify(data); this.body = Buffer.from(JSON.stringify(data), 'utf8');
this.options.headers['content-length'] = Buffer.byteLength(this.body, 'utf8'); this.options.headers['content-length'] = this.body.byteLength;
} else if (contentType === 'application/x-www-form-urlencoded') { } else if (contentType === 'application/x-www-form-urlencoded') {
this.body = (new URLSearchParams(data)).toString(); this.body = Buffer.from((new URLSearchParams(data)).toString(), 'utf8');
this.options.headers['content-length'] = Buffer.byteLength(this.body, 'utf8'); this.options.headers['content-length'] = this.body.byteLength;
} }
return this; return this;
} }
@@ -169,11 +169,17 @@ class Request {
return this; return this;
} }
attach(name, filepath) { attach(name, filepath) { // this is only used in tests and thus simplistic
if (!(this.options.body instanceof FormData)) this.options.body = new FormData(); const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2);
const data = fs.readFileSync(filepath);
this.options.body.append(name, new Blob([data]), path.basename(filepath)); const partHeader = Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="${name}" filename="${path.basename(filepath)}"\r\n\r\n`, 'utf8');
delete this.options.headers['content-type']; // explicitly remove it. without it boundary won't make it to the header! const partData = fs.readFileSync(filepath);
const partTrailer = Buffer.from(`\r\n--${boundary}--\r\n`, 'utf8');
this.body = Buffer.concat([partHeader, partData, partTrailer]);
this.options.headers['content-type'] = `multipart/form-data; boundary=${boundary}`;
this.options.headers['content-length'] = this.body.byteLength;
return this; return this;
} }