From 75699bb4671e182fa9d3accdef6ca4d7ff7a7336 Mon Sep 17 00:00:00 2001 From: David Frank Date: Mon, 26 Jan 2015 18:15:07 +0800 Subject: [PATCH] basic http added --- README.md | 4 ++-- index.js | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++- package.json | 4 +++- test/test.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b65c11c..331d17f 100644 --- a/README.md +++ b/README.md @@ -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]. diff --git a/index.js b/index.js index 5d21e2a..0e88715 100644 --- a/index.js +++ b/index.js @@ -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; diff --git a/package.json b/package.json index dfb585f..9c866b7 100644 --- a/package.json +++ b/package.json @@ -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" } } diff --git a/test/test.js b/test/test.js index e69de29..c5ca25e 100644 --- a/test/test.js +++ b/test/test.js @@ -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); + }); + }); +});