db.getView(view, req.query, function (err, data) { var current_req = (utils.currentRequest() || {}); if (current_req.uuid === req.uuid) { if (err) { return callback(err); } getRow = function () { return data.rows.shift(); }; start = function (res) { //console.log('start'); //console.log(res); exports.handleResponse(req, res); }; var head = exports.createHead(data); var res = exports.runList(fn, head, req); events.emit('afterResponse', info, req, res); if (res) { exports.handleResponse(req, res); } else { // returned without response, meaning cookies won't be set // by handleResponseHeaders if (flashmessages && req.outgoing_flash_messages) { flashmessages.setCookieBrowser( req, req.outgoing_flash_messages ); } } getRow = function () { return null; }; callback(); } });
db.getDoc(docid, req.query, function (err, doc) { var current_req = (utils.currentRequest() || {}); if (current_req.uuid === req.uuid) { if (err) { return callback(err); } exports.runUpdate(fn, doc, req, function (err, res) { if (err) { events.emit('updateFailure', err, info, req, res, doc); return callback(err); } events.emit('afterResponse', info, req, res); if (res) { exports.handleResponse(req, res[1]); } else { // returned without response, meaning cookies won't be // set by handleResponseHeaders if (flashmessages && req.outgoing_flash_messages) { flashmessages.setCookieBrowser( req, req.outgoing_flash_messages ); } } callback(); }); } });
exports.runShow = function (fn, doc, req) { if (flashmessages) { req = flashmessages.updateRequest(req); } utils.currentRequest(req); var info = { type: 'show', name: req.path[1], target: req.path[2], query: req.query, fn: fn }; events.emit('beforeRequest', info, req); var res = fn(doc, req); if (!(res instanceof Object)) { res = {code: 200, body: res}; } else { res = exports.parseResponse(req, res); } events.emit('beforeResponseStart', info, req, res); events.emit('beforeResponseData', info, req, res, res.body || ''); if (flashmessages) { res = flashmessages.updateResponse(req, res); } req.response_received = true; return res; };
exports.runList = function (fn, head, req) { if (flashmessages) { req = flashmessages.updateRequest(req); } utils.currentRequest(req); var info = { type: 'list', name: req.path[1], target: req.path[2], query: req.query, fn: fn }; // cache response from start call var start_res; var _start = start; start = function (res) { start_res = res; events.emit('beforeResponseStart', info, req, res); if (res.body) { events.emit('beforeResponseData', info, req, res, res.body); } if (flashmessages) { res = flashmessages.updateResponse(req, res); } _start(res); }; var _send = send; send = function (data) { if (!start_res.body) { start_res.body = ''; } // TODO: does it make sense to store data here and use up memory // on the server? start_res.body += data; events.emit('beforeResponseData', info, req, start_res, data); _send(data); }; events.emit('beforeRequest', info, req); var val = fn(head, req); if (val instanceof Object) { val = exports.parseResponse(req, val).body; } if (!start_res) { start_res = {code: 200, body: val}; events.emit('beforeResponseStart', info, req, start_res); events.emit('beforeResponseData', info, req, start_res, val); start = _start; send = _send; } else { start_res.body = start_res.body ? start_res.body + val: val; events.emit('beforeResponseData', info, req, start_res, val); } start = _start; send = _send; req.response_received = true; return val; };
exports.runUpdate = function (fn, doc, req, cb) { if (flashmessages) { req = flashmessages.updateRequest(req); } utils.currentRequest(req); var info = { type: 'update', name: req.path[1], target: req.path[2], query: req.query, fn: fn }; events.emit('beforeRequest', info, req); var val = fn(doc, req); var res = val ? val[1]: null; if (!(res instanceof Object)) { res = {code: 200, body: res}; } else { res = exports.parseResponse(req, res); } events.emit('beforeResponseStart', info, req, res); events.emit('beforeResponseData', info, req, res, res.body || ''); if (flashmessages) { res = flashmessages.updateResponse(req, res); } var r = [val ? val[0]: null, res]; if (req.client && r[0]) { db.saveDoc(r[0], function (err, res) { if (err) { return cb(err); } req.response_received = true; cb(null, r); }); } else { req.response_received = true; cb(null, r); } };
exports.createRequest(method, url, data, match, function (err, req) { if (err) { throw err; } //console.log(req); var msg = method + ' ' + url + ' -> ' + JSON.stringify(req.path.join('/')) + ' ' + JSON.stringify(req.query); if (data) { msg += ' data: ' + JSON.stringify(data); } console.log(msg); utils.currentRequest(req); var after = function () { if (parsed.hash) { // we have to handle in-page anchors manually because we've // hijacked the hash part of the url // TODO: don't re-handle the page if only the hash has // changed // test if a valid element name or id if (/#[A-Za-z_\-:\.]+/.test(parsed.hash)) { var el = $(parsed.hash); if (el.length) { window.scrollTo(0, el.offset().top); } } else if (parsed.hash === '#') { // scroll to top of page window.scrollTo(0, 0); } // TODO: handle invalid values? } }; var src, fn, name; if (req.path[0] === '_show') { exports.runShowBrowser( req, req.path[1], req.path.slice(2).join('/'), after ); } else if (req.path[0] === '_list') { exports.runListBrowser( req, req.path[1], req.path.slice(2).join('/'), after ); } else if (req.path[0] === '_update') { exports.runUpdateBrowser( req, req.path[1], req.path.slice(2).join('/'), after ); } else { console.log('Unknown rewrite target: ' + req.path.join('/')); var newurl = exports.getBaseURL() + '/_db/_design/' + settings.name + '/' + req.path.join('/'); console.log('redirecting to: ' + newurl); window.location = newurl; } });