basic http added

This commit is contained in:
David Frank 2015-01-26 18:15:07 +08:00
parent 9c472a52f2
commit 75699bb467
4 changed files with 119 additions and 4 deletions

View File

@ -19,8 +19,8 @@ Plus if you are going all the way to implement `XMLHttpRequest` in node and then
# Features
* Stay consistent with `window.fetch` API.
* Make conscious trade-off when following [WHATWG fetch spec](https://fetch.spec.whatwg.org/) implementation details, document known difference.
* Stay consistent with `window.fetch` API whenever possible.
* Make conscious trade-off when following [whatwg fetch spec](https://fetch.spec.whatwg.org/) implementation details, document known difference.
* Use native promise, but allow substituting it with [insert your favorite promise library].

View File

@ -5,7 +5,8 @@
* export fetch
*/
var parser = require('url');
var parse = require('url').parse;
var resolve = require('url').resolve;
var http = require('http');
var https = require('https');
var zlib = require('zlib');
@ -24,8 +25,66 @@ function Fetch(url, opts) {
if (!(this instanceof Fetch))
return new Fetch(url, opts);
if (!Fetch.Promise) {
throw new Error('native promise missing, set Fetch.Promise to your favorite substitute');
}
return new Fetch.Promise(function(resolve, reject) {
opts = opts || {};
var uri = parse(url);
if (!uri.protocol || !uri.hostname) {
reject(Error('only absolute url are supported'));
return;
}
if (uri.protocol !== 'http:' && uri.protocol !== 'https:') {
reject(Error('only http(s) protocol are supported'));
return;
}
var request;
if (uri.protocol !== 'https:') {
request = https.request;
} else {
request = http.request;
}
// avoid side-effect on input
var options = {
hostname: uri.hostname
, port: uri.port
, method: opts.method
, path: uri.path
, headers: opts.headers
, auth: uri.auth
//, agent: opts.agent
};
var req = request(options);
var output;
req.on('response', function(res) {
output = {
headers: res.headers
, status: res.statusCode
, bytes: 0
};
res.on('data', function(chunk) {
output.bytes += chunk.length;
});
res.on('end', function() {
resolve(output);
});
});
req.end();
});
};
// expose Promise
Fetch.Promise = global.Promise;

View File

@ -22,8 +22,10 @@
},
"homepage": "https://github.com/bitinn/node-fetch",
"devDependencies": {
"bluebird": "^2.9.1",
"chai": "^1.10.0",
"chai-as-promised": "^4.1.1",
"mocha": "^2.1.0"
"mocha": "^2.1.0",
"promise": "^6.1.0"
}
}

View File

@ -0,0 +1,54 @@
// test tools
var chai = require('chai');
var cap = require('chai-as-promised');
chai.use(cap);
var expect = chai.expect;
var http = require('http');
var https = require('https');
var bluebird = require('bluebird');
var then = require('promise');
// test subjects
var fetch = require('../index.js');
// test with native promise on node 0.11, and bluebird for node 0.10
fetch.Promise = fetch.Promise || bluebird;
var url, opts;
describe('Fetch', function() {
before(function() {
// TODO: local server for more stable testing
});
it('should return a promise', function() {
url = 'http://example.com/';
expect(fetch(url)).to.be.an.instanceof(fetch.Promise);
});
it('should return custom promise', function() {
url = 'http://example.com/';
var old = fetch.Promise;
fetch.Promise = then;
expect(fetch(url)).to.be.an.instanceof(then);
fetch.Promise = old;
});
it('should reject with error if url is relative', function() {
url = 'some/path';
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
});
it('should reject with error if protocol is unsupported', function() {
url = 'ftp://example.com/';
return expect(fetch(url)).to.eventually.be.rejectedWith(Error);
});
it('should resolve with result', function() {
url = 'http://example.com/';
return fetch(url).then(function(res) {
console.log(res);
});
});
});