Skip to content

Commit ce5f277

Browse files
committed
fix: coding against native FormData and form-data
1 parent 8001580 commit ce5f277

File tree

6 files changed

+138
-45
lines changed

6 files changed

+138
-45
lines changed

package-lock.json

Lines changed: 77 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@
8181
"chalk": "^1.1.1",
8282
"commander": "^2.9.0",
8383
"debug": "^2.2.0",
84-
"formdata-polyfill": "^3.0.20",
84+
"event-stream": "^4.0.1",
85+
"form-data": "^3.0.0",
8586
"fs-readfile-promise": "^2.0.1",
8687
"fs-writefile-promise": "^1.0.3",
8788
"har-validator": "^5.0.0",

src/index.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
'use strict'
44

5-
require('formdata-polyfill')
6-
75
var debug = require('debug')('httpsnippet')
6+
var es = require('event-stream')
7+
var MultiPartForm = require('form-data')
88
var qs = require('querystring')
99
var reducer = require('./helpers/reducer')
1010
var targets = require('./targets')
@@ -106,21 +106,49 @@ HTTPSnippet.prototype.prepare = function (request) {
106106
request.postData.mimeType = 'multipart/form-data'
107107

108108
if (request.postData.params) {
109-
var form = new FormData()
109+
var form = new MultiPartForm()
110+
111+
// The `form-data` module returns one of two things: a native FormData object, or its own polyfill. Since this
112+
// polyfill support the full API of the native FormData object, when this library is running in a browser
113+
// environment it'll fail on two things:
114+
//
115+
// - The API for `form.append()` has three arguments and the third should only be present when the second is a
116+
// Blob or USVString.
117+
// - `FormData.pipe()` isn't a function.
118+
//
119+
// Since the native FormData object is iterable, we easily detect what version of `form-data` we're working
120+
// with here to allow `multipart/form-data` requests to be compiled under both browser and Node environments.
121+
// This hack sucks yeah, but it's the only way we can use this library in the browser as if we code this against
122+
// just the native FormData object, we can't polyfill it back into Node because Blob and File objects, which
123+
// something like `formdata-polyfill` requires, don't exist there.
124+
const isNativeFormData = (typeof form[Symbol.iterator] === 'function');
110125

111126
// easter egg
112127
const boundary = '---011000010111000001101001'
113128

114129
request.postData.params.forEach(function (param) {
115-
if (isBlob(param.value)) {
116-
form.append(param.name, param.value || '', param.fileName || null)
130+
if (isNativeFormData) {
131+
if (isBlob(param.value)) {
132+
form.append(param.name, param.value || '', param.fileName || null)
133+
} else {
134+
form.append(param.name, param.value || '')
135+
}
117136
} else {
118-
form.append(param.name, param.value || '')
137+
form.append(param.name, param.value || '', {
138+
filename: param.fileName || null,
139+
contentType: param.contentType || null
140+
})
119141
}
120142
})
121143

122-
for (var data of formDataIterator(form, boundary)) {
123-
request.postData.text += data
144+
if (isNativeFormData) {
145+
for (var data of formDataIterator(form, boundary)) {
146+
request.postData.text += data
147+
}
148+
} else {
149+
form.pipe(es.map(function (data, cb) {
150+
request.postData.text += data
151+
}))
124152
}
125153

126154
request.postData.boundary = boundary

src/targets/index.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
'use strict'
22

33
module.exports = {
4-
// c: require('./c'),
5-
// clojure: require('./clojure'),
6-
// csharp: require('./csharp'),
7-
// go: require('./go'),
8-
// http: require('./http'),
9-
// java: require('./java'),
10-
// javascript: require('./javascript'),
11-
// node: require('./node'),
12-
// objc: require('./objc'),
13-
// ocaml: require('./ocaml'),
14-
// php: require('./php'),
15-
// powershell: require('./powershell'),
16-
// python: require('./python'),
17-
// r: require('./r'),
18-
// ruby: require('./ruby'),
4+
c: require('./c'),
5+
clojure: require('./clojure'),
6+
csharp: require('./csharp'),
7+
go: require('./go'),
8+
http: require('./http'),
9+
java: require('./java'),
10+
javascript: require('./javascript'),
11+
node: require('./node'),
12+
objc: require('./objc'),
13+
ocaml: require('./ocaml'),
14+
php: require('./php'),
15+
powershell: require('./powershell'),
16+
python: require('./python'),
17+
r: require('./r'),
18+
ruby: require('./ruby'),
1919
shell: require('./shell'),
20-
// swift: require('./swift')
20+
swift: require('./swift')
2121
}

src/targets/shell/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ module.exports = {
99
},
1010

1111
curl: require('./curl'),
12-
// httpie: require('./httpie'),
13-
// wget: require('./wget')
12+
httpie: require('./httpie'),
13+
wget: require('./wget')
1414
}

test/targets.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const skipMe = {
5050
'*': [
5151
'multipart-data',
5252
'multipart-file',
53-
// 'multipart-form-data'
53+
'multipart-form-data'
5454
]
5555
}
5656
}
@@ -88,15 +88,15 @@ var itShouldGenerateOutput = function (request, path, target, client) {
8888
})
8989
}
9090

91-
/* describe('Available Targets', function () {
91+
describe('Available Targets', function () {
9292
HTTPSnippet.availableTargets().forEach(function (target) {
9393
it('available-targets.json should include ' + target.title, function () {
9494
fixtures['available-targets'].should.containEql(target)
9595
})
9696
})
97-
}) */
97+
})
9898

99-
/* describe('Custom targets', function () {
99+
describe('Custom targets', function () {
100100
describe('Adding a custom target', function () {
101101
it('should throw if the target does has no info object', function () {
102102
(function () {
@@ -186,7 +186,7 @@ var itShouldGenerateOutput = function (request, path, target, client) {
186186
})
187187
})
188188
})
189-
}) */
189+
})
190190

191191
// test all the things!
192192
describe('Targets', function () {

0 commit comments

Comments
 (0)