From c95f92fa4c42ef86cd994ca0361cb3c1909e6f2d Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Wed, 4 Jul 2012 13:36:51 +0200 Subject: o Sending 405 on bad method, 406 on bad Accept values. --- routes/index.js | 173 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 129 insertions(+), 44 deletions(-) (limited to 'routes') diff --git a/routes/index.js b/routes/index.js index 23af53d..ba2ca23 100644 --- a/routes/index.js +++ b/routes/index.js @@ -45,23 +45,41 @@ function pager(req, count) { function after(res, callback) { return function(err, queryResult) { if(err) { - res.writeHead(500, {"Content-Type" : "text/plain"}); - return res.end("Error! " + util.inspect(err)) + res.writeHead(500, {'Content-Type' : 'text/plain'}); + return res.end('Error! ' + util.inspect(err)) } callback(queryResult) } } -exports.index = function(req, res) { - switch(req.accept.types.getBestMatch(["text/html", "application/vnd.collection+json"])) { - case "text/html": +function method(handlers) { + return function(req, res) { + var handler = handlers[req.method]; + if(handler) { + return handler(req, res) + } + // I'm just too lazy to include two rows + if(req.method == 'HEAD') { + var handler = handlers[req.method]; + if(handler) { + return handler(req, res) + } + } + res.header('Allow', _.keys(handlers)); + return res.send(405); + } +} + +function getIndex(req, res) { + switch(req.accept.types.getBestMatch(['text/html', 'application/vnd.collection+json'])) { + case 'text/html': res.render('index', { title: 'Employee DB', urlgenerator: res.urlgenerator }); break; - case "application/vnd.collection+json": - default: + case 'application/vnd.collection+json': + case '*/*': var c = {collection: { links: [ { rel: 'departments', @@ -76,10 +94,16 @@ exports.index = function(req, res) { res.contentType('application/vnd.collection+json'); res.send(JSON.stringify(collection_json.fromObject(c)), 200); break; + default: + res.send(406); } }; -exports.departments = function(req, res) { +exports.index = method({ + GET: getIndex +}); + +function getDepartments(req, res) { pg.connect(process.env.DATABASE_URL, function(err, client) { if(err) throw err; var sql = 'SELECT n_live_tup FROM pg_stat_user_tables WHERE relname=\'departments\''; @@ -87,45 +111,53 @@ exports.departments = function(req, res) { client.query(sql, after(res, function(rs) { var p = pager(req, parseInt(rs.rows[0].n_live_tup)); client.query(sql2, [ p.offset, p.limit ], after(res, function(rs2) { - switch(req.accept.types.getBestMatch(["text/html", "application/vnd.collection+json"])) { - case "text/html": + switch(req.accept.types.getBestMatch(['text/html', 'application/vnd.collection+json'])) { + case 'text/html': res.render('departments', { title: 'Department List', urlgenerator: res.urlgenerator, pager: p, query: req.query, departments: rs2.rows }); break; - case "application/vnd.collection+json": - default: + case 'application/vnd.collection+json': + case '*/*': var c = {collection: { href: res.urlgenerator.departments(), items: mapDepartments(res, rs2.rows) }}; res.contentType('application/vnd.collection+json'); res.send(JSON.stringify(collection_json.fromObject(c)), 200); + break; + default: + res.send(406); } })); })); }); }; -exports.department = function(req, res) { +exports.departments = method({ + GET: getDepartments +}); + +function getDepartment(req, res) { var dept_no = req.params.dept_no; - switch(req.accept.types.getBestMatch(["text/html", "application/vnd.collection+json"])) { - case "text/html": + switch(req.accept.types.getBestMatch(['text/html', 'application/vnd.collection+json'])) { + case 'text/html': res.render('department', { title: 'Department ' + dept_no, urlgenerator: res.urlgenerator, dept_no: dept_no }); - case "application/vnd.collection+json": - default: + break; + case 'application/vnd.collection+json': + case '*/*': var c = {collection: { href: res.urlgenerator.department(dept_no), links: [ { rel: 'employees', prompt: 'Employees in department ' + dept_no, - href: res.urlgenerator.employees_in_department(dept_no) + href: res.urlgenerator.employeesInDepartment(dept_no) },{ rel: 'departments', prompt: 'All departments', @@ -134,10 +166,17 @@ exports.department = function(req, res) { }}; res.contentType('application/vnd.collection+json'); res.send(JSON.stringify(collection_json.fromObject(c)), 200); + break; + default: + res.send(406); } } -exports.employees_in_department = function(req, res) { +exports.department = method({ + GET: getDepartment +}); + +function getEmployeesInDepartment(req, res) { pg.connect(process.env.DATABASE_URL, function(err, client) { if(err) throw err; var dept_no = req.params.dept_no; @@ -149,18 +188,19 @@ exports.employees_in_department = function(req, res) { client.query(sql1, [ dept_no ], after(res, function(rs1) { var p = pager(req, parseInt(rs1.rows[0].count)); client.query(sql2, [ dept_no, p.offset, p.limit ], after(res, function(rs2) { - switch(req.accept.types.getBestMatch(["text/html", "application/vnd.collection+json"])) { - case "text/html": - res.render('employees_in_department', { + switch(req.accept.types.getBestMatch(['text/html', 'application/vnd.collection+json'])) { + case 'text/html': + res.render('employeesInDepartment', { title: 'Department: #' + dept_no, urlgenerator: res.urlgenerator, pager: p, query: req.query, dept_no: dept_no, employees: rs2.rows }); - case "application/vnd.collection+json": - default: + break; + case 'application/vnd.collection+json': + case '*/*': var c = {collection: { - href: res.urlgenerator.employees_in_department(dept_no), + href: res.urlgenerator.employeesInDepartment(dept_no), links: [ { rel: 'department', prompt: 'Department: #' + dept_no, @@ -170,13 +210,22 @@ exports.employees_in_department = function(req, res) { }}; res.contentType('application/vnd.collection+json'); res.send(JSON.stringify(collection_json.fromObject(c)), 200); + break; + default: + res.send(406); } })); })); }); }; -exports.employees = function(req, res) { +exports.employeesInDepartment = method({ + GET: getEmployeesInDepartment +}); + +function getEmployees(req, res) { + var head = req.method == 'HEAD'; + pg.connect(process.env.DATABASE_URL, function(err, client) { if(err) throw err; var emp_no = req.params.emp_no; @@ -206,16 +255,27 @@ exports.employees = function(req, res) { sql2Params.push(p.offset); sql2Params.push(p.limit); client.query(sql2, sql2Params, after(res, function(rs2) { - switch(req.accept.types.getBestMatch(["text/html", "application/vnd.collection+json"])) { - case "text/html": - res.render('employees', { - title: 'Employee List', - urlgenerator: res.urlgenerator, pager: p, query: req.query, - employees: rs2.rows, - query: req.query - }); - case "application/vnd.collection+json": - default: + switch(req.accept.types.getBestMatch(['text/html', 'application/vnd.collection+json'])) { + case 'text/html': + if(head) { + // Can't be bothered to calculate Content-Length even if I + // should.. + res.writeHead(200, { + 'Content-Type': 'text/html', + }); + res.end(); + } + else { + res.render('employees', { + title: 'Employee List', + urlgenerator: res.urlgenerator, pager: p, query: req.query, + employees: rs2.rows, + query: req.query + }); + } + break; + case 'application/vnd.collection+json': + case '*/*': var links = []; if(_.isNumber(p.prevOffset)) { links.push({ @@ -240,41 +300,66 @@ exports.employees = function(req, res) { name: 'employee-search', prompt: 'Employee search', data: [ - { name: "name" } + { name: 'name' } ] }], items: mapEmployees(res, rs2.rows) }}; - res.contentType('application/vnd.collection+json'); - res.send(JSON.stringify(collection_json.fromObject(c)), 200); + var text = JSON.stringify(collection_json.fromObject(c)); + var headers = { + 'Content-Type': 'application/vnd.collection+json', + 'Content-Length': text.length + }; + if(head) { + res.writeHead(200, headers); + res.end(); + } + else { + res.send(text, headers, 200); + } + break; + default: + res.send(406); } })); })); }); }; -exports.employee = function(req, res) { +exports.employees = method({ + GET: getEmployees +}); + +function getEmployee(req, res) { pg.connect(process.env.DATABASE_URL, function(err, client) { if(err) throw err; var emp_no = req.params.emp_no; var sql = 'SELECT * FROM employees WHERE employees.emp_no=$1'; client.query(sql, [ emp_no ], after(res, function(rs) { - switch(req.accept.types.getBestMatch(["text/html", "application/vnd.collection+json"])) { - case "text/html": + switch(req.accept.types.getBestMatch(['text/html', 'application/vnd.collection+json', '*/*'])) { + case 'text/html': res.render('employee', { title: 'Employee: #' + emp_no, urlgenerator: res.urlgenerator, employee: rs.rows[0] }); - case "application/vnd.collection+json": - default: + break; + case 'application/vnd.collection+json': + case '*/*': var c = {collection: { href: res.urlgenerator.employee(emp_no), items: [ mapRow(rs.rows[0]) ], }}; res.contentType('application/vnd.collection+json'); res.send(JSON.stringify(collection_json.fromObject(c)), 200); + break; + default: + res.send(406); } })) }); } + +exports.employee = method({ + GET: getEmployee +}); -- cgit v1.2.3