From e842d4b44a2eb8305ba367991abe53244cf548aa Mon Sep 17 00:00:00 2001 From: Joachim Viide Date: Wed, 9 Nov 2016 14:36:35 +0200 Subject: [PATCH] Support trap URL suffixes & return 404 for traps Now any trap URL path can be suffixed with a string that begins with either "." or "/". Also query strings are supported. These suffixes (path suffix + query string) are stored for potential later use. Implements changes suggested in #28. --- browser/visits.js | 2 +- server/app.jsx | 114 +++++++++++++++++++++------------------------- 2 files changed, 53 insertions(+), 63 deletions(-) diff --git a/browser/visits.js b/browser/visits.js index b5bf1c2..0923729 100644 --- a/browser/visits.js +++ b/browser/visits.js @@ -87,7 +87,7 @@ function updateTable(_props, rootElement, minInterval=1000, maxInterval=15000) { render(, rootElement); const baseUrl = props.updateUrl; - const cursor = props.updateCursor; + const cursor = props.cursor; fetchUpdates(baseUrl, cursor, minInterval, minInterval, maxInterval, null, (err, visits) => { if (err) { props = Object.assign({}, props, { diff --git a/server/app.jsx b/server/app.jsx index f0bb63a..651430a 100644 --- a/server/app.jsx +++ b/server/app.jsx @@ -99,28 +99,40 @@ app.get("/new", (req, res, next) => { .catch(next); }); -app.get("/:id([a-zA-Z0-9_-]{22})", (req, res, next) => { - const id = req.params.id; - store.get(id) - .then(item => { - if (!item) { - next(); - return; - } +function getData(req, target, cursor) { + return store.list(target, cursor).then(({ cursor, visits }) => { + return { + trapUrl: fullUrl(req, target), + cursor: cursor, + visits: visits.map(entity => { + return mergeAndClean(entity.info, { + timestamp: entity.timestamp + }); + }) + }; + }); +} - analytics.pageView(req).catch(errors.report); +app.get(/^\/([a-zA-Z0-9_-]{22})([./].*)?$/, (req, res, next) => { + const id = req.params[0]; + const rest = req.params[1]; - if (!item.isView) { + store.get(id) + .then(item => { + if (item && !item.isView) { analytics.event(req, "trap", "view").catch(errors.report); + const suffix = req.url.substring(1 + id.length) || undefined; return taskQueue.publish("trap-topic", { target: id, timestamp: Date.now(), - info: extractInfo(req) + info: mergeAndClean(extractInfo(req), { + suffix: suffix || undefined + }) }).then(() => { const styles = [asset("common", "css")]; const scripts = [asset("common", "js")]; - res.send(render( + res.status(404).send(render( @@ -128,65 +140,43 @@ app.get("/:id([a-zA-Z0-9_-]{22})", (req, res, next) => { }); } - return store.list(item.other).then(({ cursor, visits }) => { - const initialData = { - js: false, - trapUrl: fullUrl(req, item.other), - updateUrl: fullUrl(req, id + ".json"), - updateCursor: cursor, - visits: visits.map(entity => { - return mergeAndClean(entity.info, { - timestamp: entity.timestamp - }); - }) - }; - - const styles = [asset("common", "css"), asset("visits", "css")]; - const scripts = [asset("common", "js"), asset("visits", "js")]; - res.send(render( - - - - - )); - }); - }) - .catch(next); -}); + if (item && item.isView && !rest) { + analytics.pageView(req).catch(errors.report); -app.get("/:id([a-zA-Z0-9_-]{22}).json", (req, res, next) => { - const id = req.params.id; + return getData(req, item.other).then(data => { + const initialData = mergeAndClean({ + js: false, + updateUrl: fullUrl(req, id + ".json") + }, data); - let cursor = req.query.cursor; - if (Array.isArray(cursor)) { - return res.sendStatus(400); - } - if (cursor !== undefined) { - cursor = Number(cursor); - } + const styles = [asset("common", "css"), asset("visits", "css")]; + const scripts = [asset("common", "js"), asset("visits", "js")]; + res.send(render( + + + + + )); + }); + } - store.get(id) - .then(item => { - if (!item || !item.isView) { - next(); - return; + if (item && item.isView && rest === ".json") { + let cursor = req.query.cursor; + if (Array.isArray(cursor)) { + return res.sendStatus(400); + } + if (cursor !== undefined) { + cursor = Number(cursor); + } + return getData(req, item.other, cursor).then(data => res.json(data)); } - return store.list(item.other, cursor).then(({ cursor, visits }) => { - res.json({ - cursor: cursor, - trapUrl: fullUrl(req, item.other), - visits: visits.map(entity => { - return mergeAndClean(entity.info, { - timestamp: entity.timestamp - }); - }) - }); - }); + next(); }) .catch(next); }); + app.use(errors.express); const server = app.listen(process.env.PORT || 8080, () => {