Route caching bug fix, simplify routing (#763)

* move window.apiPrefix into Angular service

* avoid routing by accept headers, integrate api service

* Revert "Fixed over-matching of index route."

This reverts commit 62e1225dd3.

* better name for index template file
This commit is contained in:
Jason Dreyzehner 2017-05-04 12:42:17 -04:00 committed by GitHub
parent cc7c6f81d4
commit 340decd978
19 changed files with 144 additions and 104 deletions

View File

@ -1,5 +1,7 @@
'use strict';
// var config = require('insight-config.json');
module.exports = function(grunt) {
//Load NPM tasks
@ -10,10 +12,27 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-markdown');
grunt.loadNpmTasks('grunt-macreload');
grunt.loadNpmTasks('grunt-angular-gettext');
grunt.loadNpmTasks('grunt-replace');
// Project Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
replace: {
dist: {
options: {
patterns: [
{
match: 'INSIGHT_API_PREFIX',
replacement: '<%= pkg.insightConfig.apiPrefix %>'
}
],
usePrefix: false
},
files: [
{src: ['public/src/templates/api.js'], dest: 'public/src/js/services/api.js'}
]
}
},
concat: {
options: {
process: function(src, filepath) {
@ -117,13 +136,13 @@ module.exports = function(grunt) {
grunt.option('force', true);
//Default task(s).
grunt.registerTask('default', ['watch']);
grunt.registerTask('default', ['replace', 'watch']);
//Update .pot file
grunt.registerTask('translate', ['nggettext_extract']);
//Compile task (concat + minify)
grunt.registerTask('compile', ['nggettext_compile', 'concat', 'uglify', 'cssmin']);
grunt.registerTask('compile', ['replace', 'nggettext_compile', 'concat', 'uglify', 'cssmin']);
};

View File

@ -23,24 +23,42 @@ Open a web browser to `http://localhost:3001/insight/`
## Development
To run Insight UI locally in development mode:
Install bower dependencies:
To build Insight UI locally:
```
$ bower install
$ npm run build
```
To compile and minify the web application's assets:
A watch task is also available:
```
$ grunt compile
$ npm run watch
```
There is a convenient Gruntfile.js for automation during editing the code
## Changing routePrefix and apiPrefix
By default, the `insightConfig` in `package.json` is:
```json
"insightConfig": {
"apiPrefix": "insight-api",
"routePrefix": "insight"
}
```
To change these routes, first make your changes to `package.json`, for example:
```json
"insightConfig": {
"apiPrefix": "api",
"routePrefix": ""
}
```
Then rebuild the `insight-ui` service:
```
$ grunt
$ npm run build
```
## Multilanguage support

View File

@ -3,19 +3,15 @@
var BaseService = require('./service');
var inherits = require('util').inherits;
var fs = require('fs');
var pkg = require('../package');
var InsightUI = function(options) {
BaseService.call(this, options);
if (typeof options.apiPrefix !== 'undefined') {
this.apiPrefix = options.apiPrefix;
} else {
this.apiPrefix = 'insight-api';
}
if (typeof options.routePrefix !== 'undefined') {
this.routePrefix = options.routePrefix;
} else {
this.routePrefix = 'insight';
}
// we don't use the options object for routePrefix and apiPrefix, since the
// client must be rebuilt with the proper options. A future version of
// Bitcore should allow for a service "build" step to make this better.
this.apiPrefix = pkg.insightConfig.apiPrefix;
this.routePrefix = pkg.insightConfig.routePrefix;
};
InsightUI.dependencies = ['insight-api'];
@ -23,20 +19,8 @@ InsightUI.dependencies = ['insight-api'];
inherits(InsightUI, BaseService);
InsightUI.prototype.start = function(callback) {
var self = this;
var indexFile = __dirname + '/../public/index.html';
fs.readFile(indexFile, { encoding: 'utf8' }, function(err, data) {
if(err) {
return callback(err);
}
self.indexFile = self.filterIndexHTML(data);
callback();
});
this.indexFile = this.filterIndexHTML(fs.readFileSync(__dirname + '/../public/index-template.html', {encoding: 'utf8'}));
setImmediate(callback);
};
InsightUI.prototype.getRoutePrefix = function() {
@ -45,26 +29,19 @@ InsightUI.prototype.getRoutePrefix = function() {
InsightUI.prototype.setupRoutes = function(app, express) {
var self = this;
app.use('/', function(req, res, next){
if (req.url === '/') {
res.send(self.indexFile);
} else {
express.static(__dirname + '/../public')(req, res, next);
}
app.use(express.static(__dirname + '/../public'));
// if not in found, fall back to indexFile (404 is handled client-side)
app.use(function(req, res, next) {
res.setHeader('Content-Type', 'text/html');
res.send(self.indexFile);
});
};
InsightUI.prototype.filterIndexHTML = function(data) {
var transformed = data
.replace(/apiPrefix = '\/api'/, "apiPrefix = '/" + this.apiPrefix + "'");
if (this.routePrefix) {
transformed = transformed.replace(/<base href=\"\/\"/, '<base href="/' + this.routePrefix + '/"');
var transformed = data;
if (this.routePrefix !== '') {
transformed = transformed.replace('<base href="/"', '<base href="/' + this.routePrefix + '/"');
}
return transformed;
};

View File

@ -39,19 +39,27 @@
"front-end"
],
"bitcoreNode": "bitcore-node",
"dependencies": {
"insightConfig": {
"apiPrefix": "insight-api",
"routePrefix": "insight"
},
"scripts": {
"build": "bower install && grunt compile",
"watch": "grunt"
},
"dependencies": {},
"devDependencies": {
"bower": "~1.2.8",
"bower": "~1.8.0",
"grunt": "~0.4.2",
"grunt-angular-gettext": "^0.2.15",
"grunt-cli": "~0.1.11",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-uglify": "~0.3.2",
"grunt-contrib-watch": "*",
"grunt-macreload": "*",
"grunt-css": "~0.5.4",
"grunt-macreload": "*",
"grunt-markdown": "~0.5.0",
"grunt-angular-gettext": "^0.2.15"
"grunt-replace": "^1.0.1"
}
}

View File

@ -8,7 +8,7 @@
<meta name="fragment" content="!">
<title data-ng-bind="$root.title + $root.titleDetail + ' | Insight'">Insight</title>
<meta name="keywords" content="bitcoins, transactions, blocks, address, block chain, best block, mining difficulty, hash serialized">
<meta name="description" content="Bitcoin Insight. View detailed information on all bitcoin transactions and block. {{ $root.title + $root.titleDetail }}">
<meta name="description" content="Bitcoin Insight. View detailed information on all bitcoin transactions and blocks.">
<link rel="shortcut icon" href="img/icons/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,400italic">
<link rel="stylesheet" href="css/main.min.css">
@ -66,7 +66,6 @@
<a class="insight m10v pull-right" target="_blank" href="http://insight.is">insight <small>API v{{version}}</small></a>
</div>
</div>
<script language="javascript">window.apiPrefix = '/api';</script>
<script src="/socket.io/socket.io.js"></script>
<script src="js/vendors.min.js"></script>
<script src="js/angularjs-all.min.js"></script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,6 +15,7 @@ angular.module('insight',[
'angularMoment',
'insight.system',
'insight.socket',
'insight.api',
'insight.blocks',
'insight.transactions',
'insight.address',
@ -27,6 +28,7 @@ angular.module('insight',[
angular.module('insight.system', []);
angular.module('insight.socket', []);
angular.module('insight.api', []);
angular.module('insight.blocks', []);
angular.module('insight.transactions', []);
angular.module('insight.address', []);

View File

@ -1,7 +1,7 @@
'use strict';
angular.module('insight.messages').controller('VerifyMessageController',
function($scope, $http) {
function($scope, $http, Api) {
$scope.message = {
address: '',
signature: '',
@ -22,7 +22,7 @@ angular.module('insight.messages').controller('VerifyMessageController',
$scope.verify = function() {
$scope.verification.status = 'loading';
$scope.verification.address = $scope.message.address;
$http.post(window.apiPrefix + '/messages/verify', $scope.message)
$http.post(Api.apiPrefix + '/messages/verify', $scope.message)
.success(function(data, status, headers, config) {
if(typeof(data.result) != 'boolean') {
// API returned 200 but result was not true or false

View File

@ -175,7 +175,7 @@ function($scope, $rootScope, $routeParams, $location, Global, Transaction, Trans
});
angular.module('insight.transactions').controller('SendRawTransactionController',
function($scope, $http) {
function($scope, $http, Api) {
$scope.transaction = '';
$scope.status = 'ready'; // ready|loading|sent|error
$scope.txid = '';
@ -189,7 +189,7 @@ angular.module('insight.transactions').controller('SendRawTransactionController'
rawtx: $scope.transaction
};
$scope.status = 'loading';
$http.post(window.apiPrefix + '/tx/send', postData)
$http.post(Api.apiPrefix + '/tx/send', postData)
.success(function(data, status, headers, config) {
if(typeof(data.txid) != 'string') {
// API returned 200 but the format is not known

View File

@ -1,8 +1,8 @@
'use strict';
angular.module('insight.address').factory('Address',
function($resource) {
return $resource(window.apiPrefix + '/addr/:addrStr/?noTxList=1', {
function($resource, Api) {
return $resource(Api.apiPrefix + '/addr/:addrStr/?noTxList=1', {
addrStr: '@addStr'
}, {
get: {
@ -21,4 +21,4 @@ angular.module('insight.address').factory('Address',
});
});

View File

@ -0,0 +1,9 @@
'use strict';
angular.module('insight.api')
.factory('Api',
function() {
return {
apiPrefix: '/insight-api'
}
});

View File

@ -2,8 +2,8 @@
angular.module('insight.blocks')
.factory('Block',
function($resource) {
return $resource(window.apiPrefix + '/block/:blockHash', {
function($resource, Api) {
return $resource(Api.apiPrefix + '/block/:blockHash', {
blockHash: '@blockHash'
}, {
get: {
@ -22,10 +22,10 @@ angular.module('insight.blocks')
});
})
.factory('Blocks',
function($resource) {
return $resource(window.apiPrefix + '/blocks');
function($resource, Api) {
return $resource(Api.apiPrefix + '/blocks');
})
.factory('BlockByHeight',
function($resource) {
return $resource(window.apiPrefix + '/block-index/:blockHeight');
function($resource, Api) {
return $resource(Api.apiPrefix + '/block-index/:blockHeight');
});

View File

@ -1,6 +1,6 @@
'use strict';
angular.module('insight.currency').factory('Currency',
function($resource) {
return $resource(window.apiPrefix + '/currency');
function($resource, Api) {
return $resource(Api.apiPrefix + '/currency');
});

View File

@ -7,6 +7,6 @@ angular.module('insight.system')
}
])
.factory('Version',
function($resource) {
return $resource(window.apiPrefix + '/version');
function($resource, Api) {
return $resource(Api.apiPrefix + '/version');
});

View File

@ -2,16 +2,16 @@
angular.module('insight.status')
.factory('Status',
function($resource) {
return $resource(window.apiPrefix + '/status', {
function($resource, Api) {
return $resource(Api.apiPrefix + '/status', {
q: '@q'
});
})
.factory('Sync',
function($resource) {
return $resource(window.apiPrefix + '/sync');
function($resource, Api) {
return $resource(Api.apiPrefix + '/sync');
})
.factory('PeerSync',
function($resource) {
return $resource(window.apiPrefix + '/peer');
function($resource, Api) {
return $resource(Api.apiPrefix + '/peer');
});

View File

@ -2,8 +2,8 @@
angular.module('insight.transactions')
.factory('Transaction',
function($resource) {
return $resource(window.apiPrefix + '/tx/:txId', {
function($resource, Api) {
return $resource(Api.apiPrefix + '/tx/:txId', {
txId: '@txId'
}, {
get: {
@ -22,18 +22,18 @@ angular.module('insight.transactions')
});
})
.factory('TransactionsByBlock',
function($resource) {
return $resource(window.apiPrefix + '/txs', {
function($resource, Api) {
return $resource(Api.apiPrefix + '/txs', {
block: '@block'
});
})
.factory('TransactionsByAddress',
function($resource) {
return $resource(window.apiPrefix + '/txs', {
function($resource, Api) {
return $resource(Api.apiPrefix + '/txs', {
address: '@address'
});
})
.factory('Transactions',
function($resource) {
return $resource(window.apiPrefix + '/txs');
function($resource, Api) {
return $resource(Api.apiPrefix + '/txs');
});

View File

@ -0,0 +1,9 @@
'use strict';
angular.module('insight.api')
.factory('Api',
function() {
return {
apiPrefix: '/INSIGHT_API_PREFIX'
}
});