Skip to content

Commit

Permalink
Fixes GoogleCloudPlatform#38 so errors will be logged properly. Clean…
Browse files Browse the repository at this point in the history
…ed up some code style and added some comments.
  • Loading branch information
jmdobry committed Feb 5, 2016
1 parent df3a7b6 commit 53ef68d
Show file tree
Hide file tree
Showing 18 changed files with 957 additions and 593 deletions.
16 changes: 10 additions & 6 deletions 2-structured-data/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,28 @@ app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.set('trust proxy', true);


// Books
var model = require('./books/model-' + config.dataBackend)(config);
app.use('/books', require('./books/crud')(model));
app.use('/api/books', require('./books/api')(model));


// Redirect root to /books
app.get('/', function(req, res) {
app.get('/', function (req, res) {
res.redirect('/books');
});

// Basic 404 handler
app.use(function (req, res) {
res.status(404).send('Not Found');
});

// Basic error handler
app.use(function(err, req, res, next) {
app.use(function (err, req, res, next) {
/* jshint unused:false */
console.error(err.stack);
res.status(500).send('Something broke!');
console.error(err);
// If our routes specified a specific response, then send that. Otherwise,
// send a generic message so as not to leak anything.
res.status(500).send(err.response || 'Something broke!');
});

if (module === require.main) {
Expand Down
96 changes: 59 additions & 37 deletions 2-structured-data/books/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,66 +16,88 @@
var express = require('express');
var bodyParser = require('body-parser');


module.exports = function(model) {
module.exports = function (model) {

var router = express.Router();

// Automatically parse request body as JSON
router.use(bodyParser.json());


function handleRpcError(err, res) {
if (err.code === 404) { return res.status(404); }
res.status(500).json({
message: err.message,
internalCode: err.code
});
}


router.get('/', function list(req, res) {
model.list(10, req.query.pageToken,
function(err, entities, cursor) {
if (err) { return handleRpcError(err, res); }
res.json({
items: entities,
nextPageToken: cursor
});
/**
* GET /api/books
*
* Retrieve a page of books (up to ten at a time).
*/
router.get('/', function list(req, res, next) {
model.list(10, req.query.pageToken, function (err, entities, cursor) {
if (err) { return next(err); }
res.json({
items: entities,
nextPageToken: cursor
});
});
});


router.post('/', function insert(req, res) {
model.create(req.body, function(err, entity) {
if (err) { return handleRpcError(err, res); }
/**
* POST /api/books
*
* Create a new book.
*/
router.post('/', function insert(req, res, next) {
model.create(req.body, function (err, entity) {
if (err) { return next(err); }
res.json(entity);
});
});


router.get('/:book(\\d+)', function get(req, res) {
model.read(req.params.book, function(err, entity) {
if (err) { return handleRpcError(err, res); }
/**
* GET /api/books/:id
*
* Retrieve a book.
*/
router.get('/:book(\\d+)', function get(req, res, next) {
model.read(req.params.book, function (err, entity) {
if (err) { return next(err); }
res.json(entity);
});
});


router.put('/:book(\\d+)', function update(req, res) {
model.update(req.params.book, req.body, function(err, entity) {
if (err) { return handleRpcError(err, res); }
/**
* PUT /api/books/:id
*
* Update a book.
*/
router.put('/:book(\\d+)', function update(req, res, next) {
model.update(req.params.book, req.body, function (err, entity) {
if (err) { return next(err); }
res.json(entity);
});
});


router.delete('/:book(\\d+)', function _delete(req, res) {
model.delete(req.params.book, function(err) {
if (err) { return handleRpcError(err, res); }
/**
* DELETE /api/books/:id
*
* Delete a book.
*/
router.delete('/:book(\\d+)', function _delete(req, res, next) {
model.delete(req.params.book, function (err) {
if (err) { return next(err); }
res.status(200).send('OK');
});
});

return router;
/**
* Errors on "/api/books/*" routes.
*/
router.use(function handleRpcError(err, req, res, next) {
// Format error and forward to generic error handler for logging and
// responding to the request
err.response = {
message: err.message,
internalCode: err.code
};
next(err);
});

return router;
};
127 changes: 78 additions & 49 deletions 2-structured-data/books/crud.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,100 +16,129 @@
var express = require('express');
var bodyParser = require('body-parser');


module.exports = function(model) {
module.exports = function (model) {

var router = express.Router();

router.use(bodyParser.urlencoded({extended: false}));


function handleRpcError(err, res) {
res.status(err.code || 500).send(err.message);
}
// Automatically parse request body as form data
router.use(bodyParser.urlencoded({ extended: false }));


router.use(function(req, res, next){
// Set Content-Type for all responses for these routes
router.use(function (req, res, next){
res.set('Content-Type', 'text/html');
next();
});


router.get('/', function list(req, res) {
model.list(10, req.query.pageToken,
function(err, entities, cursor) {
if (err) { return handleRpcError(err, res); }
res.render('books/list.jade', {
books: entities,
nextPageToken: cursor
});
}
);
/**
* GET /books/add
*
* Display a page of books (up to ten at a time).
*/
router.get('/', function list(req, res, next) {
model.list(10, req.query.pageToken, function (err, entities, cursor) {
if (err) { return next(err); }
res.render('books/list.jade', {
books: entities,
nextPageToken: cursor
});
});
});


// [START add_get]
/**
* GET /books/add
*
* Display a form for creating a book.
*/
// [START add_get]
router.get('/add', function addForm(req, res) {
res.render('books/form.jade', {
book: {},
action: 'Add'
});
});
// [END add_get]


// [START add_post]
router.post('/add', function insert(req, res) {
// [END add_get]

/**
* POST /books/add
*
* Create a book.
*/
// [START add_post]
router.post('/add', function insert(req, res, next) {
var data = req.body;

// Save the data to the database.
model.create(data, function(err, savedData) {
if (err) { return handleRpcError(err, res); }
model.create(data, function (err, savedData) {
if (err) { return next(err); }
res.redirect(req.baseUrl + '/' + savedData.id);
});
});
// [END add_post]


router.get('/:book/edit', function editForm(req, res) {
model.read(req.params.book, function(err, entity) {
if (err) { return handleRpcError(err, res); }
// [END add_post]

/**
* GET /books/:id/edit
*
* Display a book for editing.
*/
router.get('/:book/edit', function editForm(req, res, next) {
model.read(req.params.book, function (err, entity) {
if (err) { return next(err); }
res.render('books/form.jade', {
book: entity,
action: 'Edit'
});
});
});


router.post('/:book/edit', function update(req, res) {
/**
* POST /books/:id/edit
*
* Update a book.
*/
router.post('/:book/edit', function update(req, res, next) {
var data = req.body;

model.update(req.params.book, data, function(err, savedData) {
if (err) { return handleRpcError(err, res); }
model.update(req.params.book, data, function (err, savedData) {
if (err) { return next(err); }
res.redirect(req.baseUrl + '/' + savedData.id);
});
});


router.get('/:book', function get(req, res) {
model.read(req.params.book, function(err, entity) {
if (err) { return handleRpcError(err, res); }
/**
* GET /books/:id
*
* Display a book.
*/
router.get('/:book', function get(req, res, next) {
model.read(req.params.book, function (err, entity) {
if (err) { return next(err); }
res.render('books/view.jade', {
book: entity
});
});
});


router.get('/:book/delete', function _delete(req, res) {
model.delete(req.params.book, function(err) {
if (err) { return handleRpcError(err, res); }
/**
* GET /books/:id/delete
*
* Delete a book.
*/
router.get('/:book/delete', function _delete(req, res, next) {
model.delete(req.params.book, function (err) {
if (err) { return next(err); }
res.redirect(req.baseUrl);
});
});

/**
* Errors on "/books/*" routes.
*/
router.use(function handleRpcError(err, req, res, next) {
// Format error and forward to generic error handler for logging and
// responding to the request
err.response = err.message;
next(err);
});

return router;

};
17 changes: 10 additions & 7 deletions 3-binary-data/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.set('trust proxy', true);


// Setup modules and dependencies
var images = require('./lib/images')(config.gcloud, config.cloudStorageBucket);
var model = require('./books/model-' + config.dataBackend)(config);
Expand All @@ -33,21 +32,25 @@ var model = require('./books/model-' + config.dataBackend)(config);
app.use('/books', require('./books/crud')(model, images));
app.use('/api/books', require('./books/api')(model));


// Redirect root to /books
app.get('/', function(req, res) {
app.get('/', function (req, res) {
res.redirect('/books');
});

// Basic 404 handler
app.use(function (req, res) {
res.status(404).send('Not Found');
});

// Basic error handler
app.use(function(err, req, res, next) {
app.use(function (err, req, res, next) {
/* jshint unused:false */
console.error(err.stack);
res.status(500).send('Something broke!');
console.error(err);
// If our routes specified a specific response, then send that. Otherwise,
// send a generic message so as not to leak anything.
res.status(500).send(err.response || 'Something broke!');
});


if (module === require.main) {
// Start the server
var server = app.listen(config.port, function () {
Expand Down
Loading

0 comments on commit 53ef68d

Please sign in to comment.