├── .editorconfig ├── .gitignore ├── controllers └── index.js ├── newrelic.js ├── package.json ├── readme.md └── server.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | [package.json] 19 | indent_size = 2 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /controllers/index.js: -------------------------------------------------------------------------------- 1 | var boom = require('boom'); 2 | var superagent = require('superagent'); 3 | var Throttle = require('superagent-throttle'); 4 | 5 | function controller(request, reply) { 6 | this.throttle = new Throttle({ 7 | active: true, 8 | rate: 5, 9 | ratePer: 10000, 10 | concurrent: 3 11 | }); 12 | 13 | superagent 14 | .get(controller.getUrl(request.query.url)) 15 | .use(this.throttle.plugin) 16 | .end(function(error, response) { 17 | if (error || !response.ok) { 18 | return reply(controller.getError(response.error)); 19 | } else { 20 | return reply(controller.getResult(response.body.pageStats)); 21 | } 22 | }); 23 | } 24 | 25 | controller.getUrl = function(url) { 26 | var decodedUrl = decodeURIComponent(url); 27 | var endpoint = 'https://www.googleapis.com/pagespeedonline/v2/runPagespeed?url=' + decodedUrl; 28 | 29 | if (process.env.API_KEY) { 30 | endpoint += '&key=' + process.env.API_KEY; 31 | } 32 | 33 | return endpoint; 34 | } 35 | 36 | controller.getError = function(data) { 37 | var message = JSON.parse(data.text).error.errors[0].message; 38 | 39 | return boom.create(data.status, message); 40 | } 41 | 42 | controller.getResult = function(data) { 43 | var result = { 44 | html : parseInt(data.htmlResponseBytes, 10) || 0, 45 | css : parseInt(data.cssResponseBytes, 10) || 0, 46 | image : parseInt(data.imageResponseBytes, 10) || 0, 47 | js : parseInt(data.javascriptResponseBytes, 10) || 0, 48 | other : parseInt(data.otherResponseBytes, 10) || 0 49 | }; 50 | 51 | result.total = result.html + result.image + result.css + result.js + result.other; 52 | 53 | return result; 54 | } 55 | 56 | module.exports = controller; 57 | -------------------------------------------------------------------------------- /newrelic.js: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | app_name: [process.env.NEW_RELIC_APP_NAME], 3 | license_key: process.env.NEW_RELIC_LICENSE_KEY 4 | }; 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browser-calories-api", 3 | "private": true, 4 | "main": "server.js", 5 | "scripts": { 6 | "start": "node server.js" 7 | }, 8 | "dependencies": { 9 | "boom": "^3.1.2", 10 | "good": "^6.1.2", 11 | "good-console": "^5.0.0", 12 | "hapi": "^13.3.0", 13 | "newrelic": "^1.26.2", 14 | "superagent": "^1.8.3", 15 | "superagent-throttle": "0.0.9" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Browser Calories API 2 | 3 | [![Build Status](http://img.shields.io/travis/zenorocha/browser-calories-api/master.svg?style=flat)](https://travis-ci.org/zenorocha/browser-calories-api) 4 | [![Dependencies Status](http://img.shields.io/david/zenorocha/browser-calories-api.svg?style=flat)](https://david-dm.org/zenorocha/browser-calories-api) 5 | 6 | > A microservice that fetches web performance metrics from a particular URL. 7 | 8 | Built with [Node](http://nodejs.org/), [Hapi](http://hapijs.com/) and [PageSpeed](https://developers.google.com/speed/docs/insights/v2/getting-started). Hosted on [Heroku](https://heroku.com/). Monitored on [New Relic](https://newrelic.com/). 9 | 10 | ## Setup 11 | 12 | Install dependencies: 13 | 14 | ``` 15 | npm install 16 | ``` 17 | 18 | Run it: 19 | 20 | ``` 21 | npm start 22 | ``` 23 | 24 | The server should be initialized at `localhost:4000`. 25 | 26 | ## Usage 27 | 28 | Just include the `url` parameter on your request and have fun! 29 | 30 | ``` 31 | curl http://localhost:4000/?url=https://github.com/zenorocha 32 | ``` 33 | 34 | ## License 35 | 36 | [MIT License](http://zenorocha.mit-license.org/) © Zeno Rocha 37 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | if (process.env.PRODUCTION) { 2 | require('newrelic'); 3 | } 4 | 5 | var Hapi = require('hapi'); 6 | 7 | // -- Setup -------------------------------------------------------------------- 8 | 9 | var server = new Hapi.Server(); 10 | 11 | server.connection({ 12 | port: process.env.PORT || 4000 13 | }); 14 | 15 | server.route([ 16 | { 17 | method: 'GET', 18 | path: '/', 19 | handler: require('./controllers/index') 20 | } 21 | ]); 22 | 23 | // -- Start -------------------------------------------------------------------- 24 | 25 | server.register({ 26 | register: require('good'), 27 | options: { 28 | reporters: [{ 29 | reporter: require('good-console'), 30 | events: { 31 | log: '*', 32 | error: '*' 33 | } 34 | }] 35 | } 36 | }, function (err) { 37 | if (err) { 38 | throw err; 39 | } 40 | 41 | if (!module.parent) { 42 | server.start(function () { 43 | server.log('info', 'Server running at: ' + server.info.uri); 44 | }); 45 | } 46 | }); 47 | 48 | module.exports = server; 49 | --------------------------------------------------------------------------------