From 845436c34b68f238efb7122b4e627a4e8995ebb4 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 26 Feb 2015 16:45:40 -0300 Subject: [PATCH 1/7] Initial http server structure --- api/app.js | 44 ++++++++++++++++++++++ api/bin/www | 90 +++++++++++++++++++++++++++++++++++++++++++++ api/config.js | 7 ++++ api/routes/index.js | 11 ++++++ package.json | 2 +- 5 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 api/app.js create mode 100755 api/bin/www create mode 100644 api/config.js create mode 100644 api/routes/index.js diff --git a/api/app.js b/api/app.js new file mode 100644 index 00000000..94bc1f3b --- /dev/null +++ b/api/app.js @@ -0,0 +1,44 @@ +'use strict'; + +var express = require('express'); +var bodyParser = require('body-parser'); + +var config = require('./config'); +var routes = require('./routes/index'); + + +function API(backend, opts) { + this.backend = backend; + this.opts = opts; + + this._initApp(); +} + +API.prototype._initApp = function() { + this.app = express(); + + // parse POST data + this.app.use(bodyParser.json()); + this.app.use(bodyParser.urlencoded({ extended: false })); + + // install routes + this.app.use('/v1', routes); + + // catch 404 and forward to error handler + this.app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); + }); + + // production error handler + this.app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); + }); +} + +module.exports = API; diff --git a/api/bin/www b/api/bin/www new file mode 100755 index 00000000..850e5e28 --- /dev/null +++ b/api/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var API = require('../app'); +var http = require('http'); +var api = new API(); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '8000'); +api.app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(api.app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + console.log('Listening on ' + bind); +} diff --git a/api/config.js b/api/config.js new file mode 100644 index 00000000..89a83ace --- /dev/null +++ b/api/config.js @@ -0,0 +1,7 @@ +'use strict'; + +var env = process.env; + +module.exports = { + port: env.BITCORED_HTTP_PORT || 8000 +} diff --git a/api/routes/index.js b/api/routes/index.js new file mode 100644 index 00000000..3d220bc4 --- /dev/null +++ b/api/routes/index.js @@ -0,0 +1,11 @@ +'use strict'; + +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.send('index'); +}); + +module.exports = router; diff --git a/package.json b/package.json index 957d0d66..ae41b05d 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "commander": "^2.3.0", "config": "^1.12.0", "cron": "^1.0.4", - "express": "~3.4.7", + "express": "4.11.1", "glob": "*", "js-yaml": "^3.2.7", "leveldown": "~0.10.0", From 33f6f422d899c6f403373e0eb871e55f4f9344c3 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 27 Feb 2015 11:47:28 -0300 Subject: [PATCH 2/7] Split api version --- api/app.js | 6 +++--- api/routes/index.js | 8 +++++++- api/routes/v1.js | 11 +++++++++++ api/routes/v2.js | 11 +++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 api/routes/v1.js create mode 100644 api/routes/v2.js diff --git a/api/app.js b/api/app.js index 94bc1f3b..4dfa5c72 100644 --- a/api/app.js +++ b/api/app.js @@ -4,7 +4,7 @@ var express = require('express'); var bodyParser = require('body-parser'); var config = require('./config'); -var routes = require('./routes/index'); +var routes = require('./routes'); function API(backend, opts) { @@ -22,7 +22,7 @@ API.prototype._initApp = function() { this.app.use(bodyParser.urlencoded({ extended: false })); // install routes - this.app.use('/v1', routes); + this.app.use('/', routes); // catch 404 and forward to error handler this.app.use(function(req, res, next) { @@ -34,7 +34,7 @@ API.prototype._initApp = function() { // production error handler this.app.use(function(err, req, res, next) { res.status(err.status || 500); - res.render('error', { + res.send({ message: err.message, error: {} }); diff --git a/api/routes/index.js b/api/routes/index.js index 3d220bc4..6f686d26 100644 --- a/api/routes/index.js +++ b/api/routes/index.js @@ -3,9 +3,15 @@ var express = require('express'); var router = express.Router(); +var v1 = require('./v1'); +var v2 = require('./v2'); + /* GET home page. */ router.get('/', function(req, res, next) { - res.send('index'); + res.send('bitcore node api'); }); +router.use('/v1', v1); +router.use('/v2', v2); + module.exports = router; diff --git a/api/routes/v1.js b/api/routes/v1.js new file mode 100644 index 00000000..80ca3e40 --- /dev/null +++ b/api/routes/v1.js @@ -0,0 +1,11 @@ +'use strict'; + +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/blocks', function(req, res, next) { + res.send('blocks v1'); +}); + +module.exports = router; diff --git a/api/routes/v2.js b/api/routes/v2.js new file mode 100644 index 00000000..9897746e --- /dev/null +++ b/api/routes/v2.js @@ -0,0 +1,11 @@ +'use strict'; + +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/blocks', function(req, res, next) { + res.send('blocks v2'); +}); + +module.exports = router; From ce415a37eb5305a7aeedbcc4ee8cd16a0e694746 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 27 Feb 2015 11:59:27 -0300 Subject: [PATCH 3/7] Add CORS to web api --- api/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/app.js b/api/app.js index 4dfa5c72..de1ad753 100644 --- a/api/app.js +++ b/api/app.js @@ -1,5 +1,6 @@ 'use strict'; +var cors = require('cors') var express = require('express'); var bodyParser = require('body-parser'); @@ -18,6 +19,7 @@ API.prototype._initApp = function() { this.app = express(); // parse POST data + this.app.use(cors()); this.app.use(bodyParser.json()); this.app.use(bodyParser.urlencoded({ extended: false })); From 75bc316ea40efbf0f7559d24ec973083a73c27ad Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 27 Feb 2015 12:36:28 -0300 Subject: [PATCH 4/7] Add backing services to http api --- api/app.js | 28 +++++++++++----------------- api/bin/www | 15 ++++++++++++--- api/routes/index.js | 21 ++++++++++++--------- api/routes/v1.js | 16 ++++++++++------ api/routes/v2.js | 16 ++++++++++------ 5 files changed, 55 insertions(+), 41 deletions(-) diff --git a/api/app.js b/api/app.js index de1ad753..ef6755f8 100644 --- a/api/app.js +++ b/api/app.js @@ -7,40 +7,34 @@ var bodyParser = require('body-parser'); var config = require('./config'); var routes = require('./routes'); - -function API(backend, opts) { - this.backend = backend; - this.opts = opts; - - this._initApp(); -} - -API.prototype._initApp = function() { - this.app = express(); +function init(backend) { + var app = express(); // parse POST data - this.app.use(cors()); - this.app.use(bodyParser.json()); - this.app.use(bodyParser.urlencoded({ extended: false })); + app.use(cors()); + app.use(bodyParser.json()); + app.use(bodyParser.urlencoded({ extended: false })); // install routes - this.app.use('/', routes); + app.use('/', routes(backend)); // catch 404 and forward to error handler - this.app.use(function(req, res, next) { + app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // production error handler - this.app.use(function(err, req, res, next) { + app.use(function(err, req, res, next) { res.status(err.status || 500); res.send({ message: err.message, error: {} }); }); + + return app; } -module.exports = API; +module.exports = init; diff --git a/api/bin/www b/api/bin/www index 850e5e28..55d52e15 100755 --- a/api/bin/www +++ b/api/bin/www @@ -6,20 +6,29 @@ var API = require('../app'); var http = require('http'); -var api = new API(); + +/** + * Init api with backing services + */ + +var Node = { + status: 'live', + nodes: 123 +} +var app = new API(Node); /** * Get port from environment and store in Express. */ var port = normalizePort(process.env.PORT || '8000'); -api.app.set('port', port); +app.set('port', port); /** * Create HTTP server. */ -var server = http.createServer(api.app); +var server = http.createServer(app); /** * Listen on provided port, on all network interfaces. diff --git a/api/routes/index.js b/api/routes/index.js index 6f686d26..645f8d9f 100644 --- a/api/routes/index.js +++ b/api/routes/index.js @@ -3,15 +3,18 @@ var express = require('express'); var router = express.Router(); -var v1 = require('./v1'); -var v2 = require('./v2'); +function initRouter(backend) { + var v1 = require('./v1')(backend); + var v2 = require('./v2')(backend); -/* GET home page. */ -router.get('/', function(req, res, next) { - res.send('bitcore node api'); -}); + router.use('/v1', v1); + router.use('/v2', v2); -router.use('/v1', v1); -router.use('/v2', v2); + router.get('/', function(req, res, next) { + res.send('bitcore node api'); + }); -module.exports = router; + return router; +} + +module.exports = initRouter; diff --git a/api/routes/v1.js b/api/routes/v1.js index 80ca3e40..5a75b370 100644 --- a/api/routes/v1.js +++ b/api/routes/v1.js @@ -1,11 +1,15 @@ 'use strict'; var express = require('express'); -var router = express.Router(); -/* GET home page. */ -router.get('/blocks', function(req, res, next) { - res.send('blocks v1'); -}); +function initRouter(backend) { + var router = express.Router(); -module.exports = router; + router.get('/blocks', function(req, res, next) { + res.send('blocks v1' + backend.status); + }); + + return router; +} + +module.exports = initRouter; diff --git a/api/routes/v2.js b/api/routes/v2.js index 9897746e..b6e51377 100644 --- a/api/routes/v2.js +++ b/api/routes/v2.js @@ -1,11 +1,15 @@ 'use strict'; var express = require('express'); -var router = express.Router(); -/* GET home page. */ -router.get('/blocks', function(req, res, next) { - res.send('blocks v2'); -}); +function initRouter(backend) { + var router = express.Router(); -module.exports = router; + router.get('/blocks', function(req, res, next) { + res.send('blocks v2 ' + backend.nodes); + }); + + return router; +} + +module.exports = initRouter; From 072e538989b7e5cd1aaafee06e95b47e464a5125 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 27 Feb 2015 12:47:40 -0300 Subject: [PATCH 5/7] Add first api version (insight) --- api/routes/v1.js | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/api/routes/v1.js b/api/routes/v1.js index 5a75b370..bfcaabf3 100644 --- a/api/routes/v1.js +++ b/api/routes/v1.js @@ -5,9 +5,44 @@ var express = require('express'); function initRouter(backend) { var router = express.Router(); - router.get('/blocks', function(req, res, next) { - res.send('blocks v1' + backend.status); - }); + function mockResponse(req, res, next) { + res.send('This is a mocked response. Backed service is: ' + backend.status); + } + + router.get('/blocks', mockResponse); + router.get('/block/:blockHash', mockResponse); + router.get('/block-index/:height', mockResponse); + + // Transaction routes + router.get('/tx/:txid', mockResponse); + router.get('/txs', mockResponse); + router.post('/tx/send', mockResponse); + + // Address routes + router.get('/addr/:addr', mockResponse); + router.get('/addr/:addr/utxo', mockResponse); + router.get('/addrs/:addrs/utxo', mockResponse); + router.post('/addrs/utxo', mockResponse); + router.get('/addrs/:addrs/txs', mockResponse); + router.post('/addrs/txs', mockResponse); + + // Address property routes + router.get('/addr/:addr/balance', mockResponse); + router.get('/addr/:addr/totalReceived', mockResponse); + router.get('/addr/:addr/totalSent', mockResponse); + router.get('/addr/:addr/unconfirmedBalance', mockResponse); + + // Status route + router.get('/status', mockResponse); + router.get('/sync', mockResponse); + router.get('/peer', mockResponse); + + // Currency + router.get('/currency', mockResponse); + + // Address routes + router.get('/messages/verify', mockResponse); + router.post('/messages/verify', mockResponse); return router; } From b64a0c0169b02c187e9ddfc70c283a4efbd2ed2c Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 27 Feb 2015 12:53:12 -0300 Subject: [PATCH 6/7] Add gzip compression --- api/app.js | 2 ++ package.json | 2 ++ 2 files changed, 4 insertions(+) diff --git a/api/app.js b/api/app.js index ef6755f8..55db77f4 100644 --- a/api/app.js +++ b/api/app.js @@ -2,6 +2,7 @@ var cors = require('cors') var express = require('express'); +var compress = require('compression'); var bodyParser = require('body-parser'); var config = require('./config'); @@ -12,6 +13,7 @@ function init(backend) { // parse POST data app.use(cors()); + app.use(compress()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); diff --git a/package.json b/package.json index ae41b05d..20437458 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,8 @@ "buffertools": "*", "commander": "^2.3.0", "config": "^1.12.0", + "compression": "^1.4.1", + "cors": "^2.5.3", "cron": "^1.0.4", "express": "4.11.1", "glob": "*", From 40d82d877d84fd6ce5468205bfb3c5f9a6d31d47 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 27 Feb 2015 12:58:04 -0300 Subject: [PATCH 7/7] Remove config --- api/app.js | 1 - api/config.js | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 api/config.js diff --git a/api/app.js b/api/app.js index 55db77f4..3ca81b93 100644 --- a/api/app.js +++ b/api/app.js @@ -5,7 +5,6 @@ var express = require('express'); var compress = require('compression'); var bodyParser = require('body-parser'); -var config = require('./config'); var routes = require('./routes'); function init(backend) { diff --git a/api/config.js b/api/config.js deleted file mode 100644 index 89a83ace..00000000 --- a/api/config.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -var env = process.env; - -module.exports = { - port: env.BITCORED_HTTP_PORT || 8000 -}