Skip to content

Commit

Permalink
Add Promise API
Browse files Browse the repository at this point in the history
* Base logic moved into event-emitter and all APIs wrapped around it
* read-all-stream combined into one place - less code duplication
* Unzip stream now inherits all properties and function from response and returned instead of response

Closes #66
  • Loading branch information
floatdrop committed Jul 15, 2015
1 parent 63d95b6 commit 04dbc4b
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 243 deletions.
342 changes: 192 additions & 150 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
21 changes: 15 additions & 6 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 @@ -104,6 +110,8 @@ Milliseconds after which the request will be aborted and an error event with `ET

##### 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 @@ -118,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 @@ -130,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
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();
});

0 comments on commit 04dbc4b

Please sign in to comment.