diff --git a/src/superagent.js b/src/superagent.js index e6a11408a..a8d3b2dfb 100644 --- a/src/superagent.js +++ b/src/superagent.js @@ -33,8 +33,9 @@ class Request { this.okFunc = ({ status }) => status >=200 && status <= 299; this.timer = { timeout: 0, id: null, controller: null }; this.retryCount = 0; - this.body = null; + this.body = Buffer.alloc(0); this.redirectCount = 5; + this.boundary = null; // multipart only } async _handleResponse(url, response) { @@ -82,7 +83,7 @@ class Request { if (error) reject(error); else resolve(result); }); - if (this.body) request.write(this.body); + request.write(this.body); request.end(); }); @@ -170,15 +171,29 @@ class Request { return this; } + field(name, value) { + if (!this.boundary) this._boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2); + + const partHeader = Buffer.from(`--${this.boundary}\r\nContent-Disposition: form-data; name="${name}"\r\n\r\n`, 'utf8'); + const partData = Buffer.from(value, 'utf8'); + const partTrailer = Buffer.from(`\r\n--${this.boundary}--\r\n`, 'utf8'); + this.body = Buffer.concat([this.body, partHeader, partData, partTrailer]); + + this.options.headers['content-type'] = `multipart/form-data; boundary=${this.boundary}`; + this.options.headers['content-length'] = this.body.byteLength; + + return this; + } + attach(name, filepath) { // this is only used in tests and thus simplistic - const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2); + if (!this.boundary) this._boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2); - const partHeader = Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="${name}" filename="${path.basename(filepath)}"\r\n\r\n`, 'utf8'); + const partHeader = Buffer.from(`--${this.boundary}\r\nContent-Disposition: form-data; name="${name}" filename="${path.basename(filepath)}"\r\n\r\n`, 'utf8'); const partData = fs.readFileSync(filepath); - const partTrailer = Buffer.from(`\r\n--${boundary}--\r\n`, 'utf8'); - this.body = Buffer.concat([partHeader, partData, partTrailer]); + const partTrailer = Buffer.from(`\r\n--${this.boundary}--\r\n`, 'utf8'); + this.body = Buffer.concat([this.body, partHeader, partData, partTrailer]); - this.options.headers['content-type'] = `multipart/form-data; boundary=${boundary}`; + this.options.headers['content-type'] = `multipart/form-data; boundary=${this.boundary}`; this.options.headers['content-length'] = this.body.byteLength; return this;