From c43cb51021be5fc4c33c7de1635f045108773497 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 5 Jul 2012 16:52:59 +0200 Subject: o Implementing support for deleting items. --- app.js | 1 + public/javascripts/gui.js | 11 ----- routes/index.js | 91 +++++++++++++++++++++++------------- views/data.jade | 116 +++++++++++++++++++++++++++++++++------------- 4 files changed, 144 insertions(+), 75 deletions(-) diff --git a/app.js b/app.js index 3558bca..875cea8 100644 --- a/app.js +++ b/app.js @@ -26,6 +26,7 @@ app.configure('development', function(){ app.get('/', routes.index); app.get('/render', routes.render); +app.get('/delete', routes.delete); http.createServer(app).listen(app.get('port'), function(){ console.log("Express server listening on port " + app.get('port')); diff --git a/public/javascripts/gui.js b/public/javascripts/gui.js index f235f6d..e69de29 100644 --- a/public/javascripts/gui.js +++ b/public/javascripts/gui.js @@ -1,11 +0,0 @@ -$(document).ready(function() { - /* Needed if the static top navbar is being used. - * Add data-offset='60' to as well. - var offset = 60; - $('#navbar ul li a').click(function(event) { - event.preventDefault(); - $($(this).attr('href'))[0].scrollIntoView(); - scrollBy(0, -offset); - }); - */ -}); diff --git a/routes/index.js b/routes/index.js index e84f15d..73f82ab 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,34 +1,70 @@ var collection_json = require('collection_json') , http = require('http') , url = require('url') + , util = require('util') , _ = require('underscore'); function urlgenerator(req) { var host = req.headers.host; return { - render: function(u) { - return 'http://' + host + '/render?url=' + encodeURIComponent(u)} + render: function(u) { return 'http://' + host + '/render?url=' + encodeURIComponent(u)}, + delete: function(referer, u) { return 'http://' + host + '/delete?referer=' + encodeURIComponent(referer) + '&url=' + encodeURIComponent(u)}, + isUrl: function(u) { + try { + var x = url.parse(u); + return _.isString(x.protocol) && _.isString(x.host) && _.isString(path); + } + catch(e) { + return false; + } + } }; } -exports.index = function(req, res){ +function sendErr(req, res, err, httpResponse) { + res.render('data', { + urlgenerator: urlgenerator(req), + url: req.query.url, referer: req.query.referer, + err: err, + httpResponse: httpResponse + }); +} + +exports.index = function(req, res) { res.render('index', { host: req.headers.host }); }; -exports.render = function(req, res) { - function sendErr(req, err, statusCode, status, headers, rawBody) { +exports.delete = function(req, res) { + var options = url.parse(req.query.url, false); + options.method = 'DELETE'; + function done(message, httpResponse) { res.render('data', { urlgenerator: urlgenerator(req), - url: req.query.url, - err: err, - statusCode: statusCode, - status: status, - headers: headers, - rawBody: rawBody + url: req.query.url, referer: req.query.referer, + httpResponse: httpResponse }); } + http.request(options, function(httpResponse) { + httpResponse.setEncoding('utf8'); + var body = ''; + httpResponse.on('data', function (chunk) { + body += chunk; + }).on('end', function (chunk) { + done(undefined, { + statusCode: httpResponse.statusCode, + status: '', + headers: httpResponse.headers, + body: body + }); + }); + }).on('error', function(e) { + done(util.inspect(e)); + }).end(); +} + +exports.render = function(req, res) { var u = url.parse(req.query.url, true); var params = _.reduce(req.query, function(q, value, key) { if(!key.match(/^param-/)) { @@ -38,39 +74,25 @@ exports.render = function(req, res) { return q; }, {}); u.query = _.extend({}, u.query, params); - fetchCollection(url.format(u), function(err, statusCode, status, headers, body) { + fetchCollection(url.format(u), function(err, httpResponse) { if(err) { - sendErr(req, err, statusCode, status, headers, body); + sendErr(req, res, err, httpResponse); return; } var parsedBody; try { - parsedBody = JSON.parse(body); + parsedBody = JSON.parse(httpResponse.body); } catch(e) { - sendErr(req, 'Unable to parse JSON: ' + e, statusCode, status, headers, body); + sendErr(req, res, 'Unable to parse JSON: ' + e, httpResponse); return; } var collection = collection_json.fromObject(parsedBody).collection; - var isUrl = function(u) { - try { - var x = url.parse(u); - return _.isString(x.protocol) && _.isString(x.host) && _.isString(path); - } - catch(e) { - return false; - } - }; res.render('data', { - isUrl: isUrl, urlgenerator: urlgenerator(req), - url: req.query.url, + url: req.query.url, referer: req.query.referer, params: params, collection: collection, - statusCode: statusCode, - status: status, - headers: headers, - headers: headers, - rawBody: body, + httpResponse: httpResponse, formattedBody: JSON.stringify(parsedBody, null, ' ') }); }); @@ -88,7 +110,12 @@ function fetchCollection(u, cb) { body += chunk; }); res.on('end', function (chunk) { - cb(undefined, res.stausCode, "", res.headers, body); + cb(undefined, { + statusCode: res.statusCode, + status: '', + headers: res.headers, + body: body + }); }); }).on('error', function() { cb('Unable to fetch ' + u); diff --git a/views/data.jade b/views/data.jade index edaa4d6..75a382a 100644 --- a/views/data.jade +++ b/views/data.jade @@ -29,7 +29,7 @@ block link block href dt rel dd - if isUrl(link.rel) + if urlgenerator.isUrl(link.rel) a(href=link.rel) #{link.rel} else | #{link.rel} @@ -44,21 +44,23 @@ block link block meta div(class='row-fluid') div(class='span12') - p - - var href=collection.href - dl - dt version - dd #{collection.version} - dt href - dd: block href + - var href=collection.href + dl + dt version + dd #{collection.version} + dt href + dd: block href div(class='row-fluid') div(class='span12') p - a(class='btn btn-primary', href=urlgenerator.render(href)) Explore - | - a(class='btn btn-primary', href=href) Raw - | + if href + a(class='btn btn-primary', href=urlgenerator.render(href)) Explore + | + a(class='btn btn-primary', href=href) Raw + | + a(class='btn btn-danger', href=urlgenerator.delete(url, href)) Delete + | form(action='http://redbot.org') input(type='text', name='uri', value=url, type='hidden') input(type='text', name='req_hdr', value='Accept: application/vnd.collection+json', type='hidden') @@ -81,13 +83,18 @@ block items else // p The feed has #{collection.items.length} items. each item, i in collection.items + - var href=item.href h2(id='item-#{i+1}') Item ##{i+1} - div - a(class='btn btn-primary btn-mini', href=urlgenerator.render(href)) Explore - | - a(class='btn btn-primary btn-mini', href=href) Raw + if href + div(class='fluid-row') + div(class='span12') + p + a(class='btn btn-primary btn-mini', href=urlgenerator.render(href)) Explore + | + a(class='btn btn-primary btn-mini', href=href) Raw + | + a(class='btn btn-danger btn-mini', href=urlgenerator.delete(url, href)) Delete - - var href=item.href dl dt href dd: block href @@ -128,16 +135,49 @@ block queries div(class='controls') input(type='submit') Execute -block http_response +block error div(class='row-fluid') + if typeof collection.error == 'undefined' + p Collection didn't include an error condition. + else + dl + dt title + dd + if collection.error.title + | #{collection.error.title} + else + i No title + dt code + dd + if collection.error.code + | #{collection.error.code} + else + i No code + dt message + dd + if collection.error.message + | #{collection.error.message} + else + i No message + +block httpResponse + div(class='row-fluid') + dl + dt URL + dd: a(href=urlgenerator.render(url)) #{url} + if typeof referer != 'undefined' + dt Referer + dd: a(href=urlgenerator.render(referer)) #{referer} pre table - each value, key in headers + tr + td(colspan='2') #{httpResponse.statusCode} #{httpResponse.status} + each value, key in httpResponse.headers tr td #{key}: td #{value} | - | #{rawBody} + | #{httpResponse.body} block navbar div(class='navbar navbar-fixed-top') @@ -166,9 +206,10 @@ block sidebar div(id='navbar', class='sidebar-nav sidebar-nav-fixed') ul(class='nav nav-list') if typeof err != 'undefined' - li(class='nav-header'): a(href='#error') Error - else - li(class='nav-header'): a(href='#meta') Meta + li(class='nav-header'): a(href='#server-error') Server Error + + if typeof collection != 'undefined' + li(class='nav-header active'): a(href='#meta') Meta each link, i in collection.links li: a(href='#link-' + (i + 1)) mixin get_name(link, 'Link', i) @@ -176,23 +217,27 @@ block sidebar each item, i in collection.items li: a(href='#item-' + (i + 1)) ##{i + 1} li(class='nav-header'): a(href='#queries') Queries + li(class='nav-header'): a(href='#error') Error each query, i in collection.queries li: a(href='#query-' + (i + 1)) mixin get_name(query, 'Query', i) li(class='nav-header'): a(href='#formatted-body') Formatted Body - li(class='nav-header'): a(href='#http-response') HTTP Response + + if typeof httpResponse != 'undefined' + li(class='nav-header'): a(href='#http-response') HTTP Response block inner_content if typeof err != 'undefined' - section(id='error') + section(id='server-error') div(class='page-header') - h1 Error + h1 Server Error div(class='row-fluid') p Error rendering: #{url} a(class='btn btn-primary btn-mini', href=urlgenerator.render(url)) Retry p= err - else + + if typeof collection != 'undefined' section(id='meta') div(class='page-header') h1 Meta @@ -207,15 +252,22 @@ block inner_content div(class='page-header') h1 Queries block queries + section(id='error') + div(class='page-header') + h1 Error + block error section(id='formatted-body') div(class='page-header') h1 Formatted Body - pre= formattedBody + div(class='row-fluid') + div(class='span12') + pre= formattedBody - section(id='http-response') - div(class='page-header') - h1 HTTP Response - block http_response + if typeof httpResponse != 'undefined' + section(id='http-response') + div(class='page-header') + h1 HTTP Response + block httpResponse block content div(class='row-fluid') -- cgit v1.2.3