Skip to content

Commit

Permalink
Merge pull request #1169 from dotcypress/form-data-file
Browse files Browse the repository at this point in the history
add metadata for form-data file field
  • Loading branch information
FredKSchott committed Oct 16, 2014
2 parents 9863b27 + 1a742c1 commit 04548a9
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 10 deletions.
28 changes: 20 additions & 8 deletions README.md
Expand Up @@ -199,9 +199,9 @@ Here's some examples of valid `no_proxy` values:
* `google.com:443, yahoo.com:80` - don't proxy HTTPS requests to Google, and don't proxy HTTP requests to Yahoo!
* `*` - ignore `https_proxy`/`http_proxy` environment variables altogether.

## UNIX Socket
## UNIX Socket

`request` supports the `unix://` protocol for all requests. The path is assumed to be absolute to the root of the host file system.
`request` supports the `unix://` protocol for all requests. The path is assumed to be absolute to the root of the host file system.

HTTP paths are extracted from the supplied URL by testing each level of the full URL against net.connect for a socket response.

Expand Down Expand Up @@ -233,7 +233,19 @@ var formData = {
my_field: 'my_value',
my_buffer: new Buffer([1, 2, 3]),
my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
remote_file: request(remoteFile)
remote_file: request(remoteFile),
attachments: [
fs.createReadStream(__dirname + '/attacment1.jpg')
fs.createReadStream(__dirname + '/attachment2.jpg')
],
custom_file: {
value: fs.createReadStream('/dev/urandom'),
// See the [form-data](https://github.com/felixge/node-form-data) README for more information about options.
options: {
filename: 'topsecret.jpg',
contentType: 'image/jpg'
}
}
};
request.post({url:'http://service.com/upload', formData: formData}, function optionalCallback(err, httpResponse, body) {
if (err) {
Expand Down Expand Up @@ -313,7 +325,7 @@ If passed as an option, `auth` should be a hash containing values `user` || `use

`sendImmediately` defaults to `true`, which causes a basic authentication header to be sent. If `sendImmediately` is `false`, then `request` will retry with a proper authentication header after receiving a `401` response from the server (which must contain a `WWW-Authenticate` header indicating the required authentication method).

Note that you can also use for basic authentication a trick using the URL itself, as specified in [RFC 1738](http://www.ietf.org/rfc/rfc1738.txt).
Note that you can also use for basic authentication a trick using the URL itself, as specified in [RFC 1738](http://www.ietf.org/rfc/rfc1738.txt).
Simply pass the `user:password` before the host with an `@` sign.

```javascript
Expand Down Expand Up @@ -449,7 +461,7 @@ The first argument can be either a `url` or an `options` object. The only requir
tunneling proxy.


The callback argument gets 3 arguments:
The callback argument gets 3 arguments:

1. An `error` when applicable (usually from [`http.ClientRequest`](http://nodejs.org/api/http.html#http_class_http_clientrequest) object)
2. An [`http.IncomingMessage`](http://nodejs.org/api/http.html#http_http_incomingmessage) object
Expand All @@ -463,7 +475,7 @@ There are also shorthand methods for different HTTP METHODs and some other conve

This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it.

**Note:** You can call `.defaults()` on the wrapper that is returned from `request.defaults` to add/override defaults that were previously defaulted.
**Note:** You can call `.defaults()` on the wrapper that is returned from `request.defaults` to add/override defaults that were previously defaulted.

For example:
```javascript
Expand Down Expand Up @@ -635,10 +647,10 @@ request({url: url, jar: j}, function () {
To inspect your cookie jar after a request

```javascript
var j = request.jar()
var j = request.jar()
request({url: 'http://www.google.com', jar: j}, function () {
var cookie_string = j.getCookieString(uri); // "key1=value1; key2=value2; ..."
var cookies = j.getCookies(uri);
var cookies = j.getCookies(uri);
// [{key: 'key1', value: 'value1', domain: "www.google.com", ...}, ...]
})
```
Expand Down
16 changes: 15 additions & 1 deletion request.js
Expand Up @@ -453,9 +453,23 @@ Request.prototype.init = function (options) {
if (options.formData) {
var formData = options.formData
var requestForm = self.form()
var appendFormValue = function (key, value) {
if (value.hasOwnProperty('value') && value.hasOwnProperty('options')) {
requestForm.append(key, value.value, value.options)
} else {
requestForm.append(key, value)
}
}
for (var formKey in formData) {
if (formData.hasOwnProperty(formKey)) {
requestForm.append(formKey, formData[formKey])
var formValue = formData[formKey]
if (formValue instanceof Array) {
for (var j = 0; j < formValue.length; j++) {
appendFormValue(formKey, formValue[j])
}
} else {
appendFormValue(formKey, formValue)
}
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion tests/test-form-data.js
Expand Up @@ -6,7 +6,7 @@ var http = require('http')
, tape = require('tape')

tape('multipart formData', function(t) {
t.plan(15)
t.plan(20)

var remoteFile = 'http://nodejs.org/images/logo.png'
, multipartFormData = {}
Expand Down Expand Up @@ -41,6 +41,16 @@ tape('multipart formData', function(t) {
// 4th field : remote_file
t.ok( data.indexOf('form-data; name="remote_file"') != -1 )
t.ok( data.indexOf('; filename="'+path.basename(multipartFormData.remote_file.path)+'"') != -1 )

// 5th field : file with metadata
t.ok( data.indexOf('form-data; name="secret_file"') != -1 )
t.ok( data.indexOf('Content-Disposition: form-data; name="secret_file"; filename="topsecret.jpg"') != -1 )
t.ok( data.indexOf('Content-Type: image/custom') != -1 )

// 6th field : batch of files
t.ok( data.indexOf('form-data; name="batch"') != -1 )
t.ok( data.match(/form-data; name="batch"/g).length == 2 )

// check for http://nodejs.org/images/logo.png traces
t.ok( data.indexOf('ImageReady') != -1 )
t.ok( data.indexOf('Content-Type: '+mime.lookup(remoteFile) ) != -1 )
Expand All @@ -57,6 +67,17 @@ tape('multipart formData', function(t) {
multipartFormData.my_buffer = new Buffer([1, 2, 3])
multipartFormData.my_file = fs.createReadStream(__dirname + '/unicycle.jpg')
multipartFormData.remote_file = request(remoteFile)
multipartFormData.secret_file = {
value: fs.createReadStream(__dirname + '/unicycle.jpg'),
options: {
filename: 'topsecret.jpg',
contentType: 'image/custom'
}
}
multipartFormData.batch = [
fs.createReadStream(__dirname + '/unicycle.jpg'),
fs.createReadStream(__dirname + '/unicycle.jpg')
]

var req = request.post({
url: 'http://localhost:8080/upload',
Expand Down

0 comments on commit 04548a9

Please sign in to comment.