Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.0.0 #82

Merged
merged 7 commits into from
Jul 23, 2015
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
368 changes: 192 additions & 176 deletions index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@
],
"dependencies": {
"duplexify": "^3.2.0",
"infinity-agent": "^2.0.0",
"is-redirect": "^1.0.0",
"is-stream": "^1.0.0",
"lowercase-keys": "^1.0.0",
"nested-error-stacks": "^1.0.0",
"object-assign": "^3.0.0",
"pinkie-promise": "^1.0.0",
"prepend-http": "^1.0.0",
"read-all-stream": "^3.0.0",
"timed-out": "^2.0.0"
Expand Down
41 changes: 27 additions & 14 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@ got('todomvc.com', function (err, data, res) {
//=> <!doctype html> ...
});

// Promise mode
got('todomvc.com')
.then(function (res) {
console.log(res.body);
})
.catch(console.error);

// Stream mode
got('todomvc.com').pipe(fs.createWriteStream('index.html'));
got.stream('todomvc.com').pipe(fs.createWriteStream('index.html'));

// For POST, PUT and PATCH methods got returns a WritableStream
fs.createReadStream('index.html').pipe(got.post('todomvc.com'));
// For POST, PUT and PATCH methods got.stream returns a WritableStream
fs.createReadStream('index.html').pipe(got.stream('todomvc.com', {method: 'POST'}));
```

### API
Expand Down Expand Up @@ -102,16 +108,10 @@ Type: `number`

Milliseconds after which the request will be aborted and an error event with `ETIMEDOUT` code will be emitted.

###### agent

[http.Agent](http://nodejs.org/api/http.html#http_class_http_agent) instance.

If `undefined` - [`infinity-agent`](https://github.com/floatdrop/infinity-agent) will be used to backport Agent class from Node.js core.

To use default [globalAgent](http://nodejs.org/api/http.html#http_http_globalagent) just pass `null`.

##### callback(error, data, response)

Function to be called, when error or data recieved. If omitted - Promise will be returned.

###### error

`Error` object with HTTP status code as `code` property.
Expand All @@ -126,6 +126,10 @@ The [response object](http://nodejs.org/api/http.html#http_http_incomingmessage)

When in stream mode, you can listen for events:

##### .on('request', request)

`request` event to get the request object of the request.

##### .on('response', response)

`response` event to get the response object of the final request.
Expand All @@ -138,9 +142,6 @@ When in stream mode, you can listen for events:

`error` event emitted in case of protocol error (like `ENOTFOUND` etc.) or status error (4xx or 5xx). Second argument is body of server response in case of status error. Third argument is response object.

###### response

The [response object](http://nodejs.org/api/http.html#http_http_incomingmessage).

#### got.get(url, [options], [callback])
#### got.post(url, [options], [callback])
Expand Down Expand Up @@ -185,6 +186,18 @@ got('todomvc.com', {
```


## Node 0.10

It is a known issue with Node [http.Agent](https://nodejs.org/docs/v0.10.39/api/http.html#http_class_http_agent) and `agent.maxSockets`, which is set to `5`. This can cause low performance of application and (in rare cases) deadlocks. To avoid this you can set it manually:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it clear it's fixed in Node 0.12 and higher, so it's only needed to do this if you care about Node 0.10 compatibility in your application.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed a little bit - but still can be wrong/confusing.

p.s. This agent tuning does not affects compatibility (it will work on 0.10) - but, in some cases, performance.


```js
require('http').globalAgent.maxSockets = Infinity;
require('https').globalAgent.maxSockets = Infinity;
```

This should only ever be done at the top-level application layer.


## Related

- [gh-got](https://github.com/sindresorhus/gh-got) - Convenience wrapper for interacting with the GitHub API
Expand Down
22 changes: 17 additions & 5 deletions test/test-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,37 @@ s.on('/', function (req, res) {
res.end('ok');
});

s.on('/404', function (req, res) {
res.statusCode = 404;
res.end('not found');
});

test('setup', function (t) {
s.listen(s.port, function () {
t.end();
});
});

test('callback mode', {timeout: 1000}, function (t) {
test('callback mode', function (t) {
got.get(s.url, function (err, data) {
t.error(err);
t.equal(data, 'ok');
t.end();
});
});

test('stream mode', {timeout: 1000}, function (t) {
test('promise mode', function (t) {
t.plan(2);

got.get(s.url)
.on('data', function (data) {
t.equal(data.toString(), 'ok');
t.end();
.then(function (res) {
t.equal(res.body, 'ok');
});

got.get(s.url + '/404')
.catch(function (err) {
t.equal(err.message, 'GET http://localhost:6767/404 response code is 404 (Not Found)');
t.equal(err.response.body, 'not found');
});
});

Expand Down
36 changes: 4 additions & 32 deletions test/test-http.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,39 +70,11 @@ test('buffer on encoding === null', function (t) {
});
});

test('stream mode', function (t) {
got(s.url)
.on('data', function (data) {
t.equal(data.toString(), 'ok');
t.end();
});
});

test('emit response object to stream', function (t) {
got(s.url)
.on('response', function (res) {
t.ok(res);
t.ok(res.headers);
t.end();
});
});

test('proxy errors to the stream', function (t) {
got(s.url + '/404')
.on('error', function (err, data, res) {
t.equal(err.code, 404);
t.equal(data, 'not');
t.ok(res);
t.end();
});
});

test('timeout option', function (t) {
got(s.url + '/404', {timeout: 1})
.on('error', function (err) {
t.equal(err.code, 'ETIMEDOUT');
t.end();
});
got(s.url + '/404', {timeout: 1}, function (err) {
t.equal(err.code, 'ETIMEDOUT');
t.end();
});
});

test('query option', function (t) {
Expand Down
7 changes: 0 additions & 7 deletions test/test-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ test('setup', function (t) {
});
});

test('json option can not be used in stream mode', function (t) {
t.throws(function () {
got(s.url, {json: true});
}, 'got can not be used as stream when options.json is used');
t.end();
});

test('json option should parse response', function (t) {
got(s.url, {json: true}, function (err, json) {
t.error(err);
Expand Down
26 changes: 0 additions & 26 deletions test/test-post.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,32 +67,6 @@ test('works with empty post response', function (t) {
});
});

test('return readable stream', function (t) {
got.post(s.url, {body: from2Array(['wow'])})
.on('data', function (data) {
t.equal(data.toString(), 'wow');
t.end();
});
});

test('return writeable stream', function (t) {
got.post(s.url)
.on('data', function (data) {
t.equal(data.toString(), 'wow');
t.end();
})
.end('wow');
});

test('throws on write to stream with body specified', function (t) {
t.throws(function () {
got(s.url, {body: 'wow'}).write('wow');
});

// wait for request to end
setTimeout(t.end.bind(t), 10);
});

test('post have content-length header to string', function (t) {
t.plan(5);

Expand Down
20 changes: 4 additions & 16 deletions test/test-redirects.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ var got = require('../');
var server = require('./server.js');
var s = server.createServer();

s.on('/', function (req, res) {
res.end('reached');
});

s.on('/finite', function (req, res) {
res.writeHead(302, {
location: s.url + '/'
Expand Down Expand Up @@ -32,10 +36,6 @@ s.on('/relativeQuery?bang', function (req, res) {
res.end();
});

s.on('/', function (req, res) {
res.end('reached');
});

test('setup', function (t) {
s.listen(s.port, function () {
t.end();
Expand Down Expand Up @@ -90,18 +90,6 @@ test('redirect only GET and HEAD requests', function (t) {
});
});

test('redirect event', function (t) {
got(s.url + '/endless')
.on('redirect', function (res, opts) {
t.equal(res.headers.location, s.url + '/endless');
opts.path = '/';
})
.on('data', function (data) {
t.equal(data.toString(), 'reached');
t.end();
});
});

test('cleanup', function (t) {
s.close();
t.end();
Expand Down
90 changes: 90 additions & 0 deletions test/test-stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
'use strict';

var test = require('tap').test;
var from2Array = require('from2-array');
var got = require('../');
var server = require('./server.js');
var s = server.createServer();

s.on('/', function (req, res) {
res.end('ok');
});

s.on('/post', function (req, res) {
req.pipe(res);
});

s.on('/redirect', function (req, res) {
res.writeHead(302, {
location: s.url
});
res.end();
});

test('setup', function (t) {
s.listen(s.port, function () {
t.end();
});
});

test('json option can not be used in stream mode', function (t) {
t.throws(function () {
got.stream(s.url, {json: true});
}, 'got can not be used as stream when options.json is used');
t.end();
});

test('return readable stream', function (t) {
got.stream(s.url)
.on('data', function (data) {
t.equal(data.toString(), 'ok');
t.end();
});
});

test('return writeable stream', function (t) {
t.plan(1);
got.stream(s.url + '/post', {method: 'POST'})
.on('data', function (data) {
t.equal(data.toString(), 'wow');
})
.end('wow');
});

test('throws on write to stream with body specified', function (t) {
t.throws(function () {
got.stream(s.url, {body: 'wow'}).write('wow');
}, 'got\'s stream is not writable when options.body is used');

// wait for request to end
setTimeout(t.end.bind(t), 10);
});

test('request event', function (t) {
got.stream(s.url)
.on('request', function (req) {
t.ok(req);
t.end();
});
});

test('redirect event', function (t) {
got.stream(s.url + '/redirect')
.on('redirect', function (res, opts) {
t.equal(res.headers.location, s.url);
t.end();
});
});

test('response event', function (t) {
got.stream(s.url)
.on('response', function (res) {
t.equal(res.statusCode, 200);
t.end();
});
});

test('cleanup', function (t) {
s.close();
t.end();
});