summaryrefslogtreecommitdiff
path: root/share/server/render.js
diff options
context:
space:
mode:
Diffstat (limited to 'share/server/render.js')
-rw-r--r--share/server/render.js400
1 files changed, 0 insertions, 400 deletions
diff --git a/share/server/render.js b/share/server/render.js
deleted file mode 100644
index 946701ef5..000000000
--- a/share/server/render.js
+++ /dev/null
@@ -1,400 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-
-var Mime = (function() {
- // registerType(name, mime-type, mime-type, ...)
- //
- // Available in query server sandbox. TODO: The list is cleared on reset.
- // This registers a particular name with the set of mimetypes it can handle.
- // Whoever registers last wins.
- //
- // Example:
- // registerType("html", "text/html; charset=utf-8");
-
- var mimesByKey = {};
- var keysByMime = {};
- function registerType() {
- var mimes = [], key = arguments[0];
- for (var i=1; i < arguments.length; i++) {
- mimes.push(arguments[i]);
- };
- mimesByKey[key] = mimes;
- for (var i=0; i < mimes.length; i++) {
- keysByMime[mimes[i]] = key;
- };
- }
-
- // Some default types
- // Ported from Ruby on Rails
- // Build list of Mime types for HTTP responses
- // http://www.iana.org/assignments/media-types/
- // http://dev.rubyonrails.org/svn/rails/trunk/actionpack/lib/action_controller/mime_types.rb
-
- registerType("all", "*/*");
- registerType("text", "text/plain; charset=utf-8", "txt");
- registerType("html", "text/html; charset=utf-8");
- registerType("xhtml", "application/xhtml+xml", "xhtml");
- registerType("xml", "application/xml", "text/xml", "application/x-xml");
- registerType("js", "text/javascript", "application/javascript", "application/x-javascript");
- registerType("css", "text/css");
- registerType("ics", "text/calendar");
- registerType("csv", "text/csv");
- registerType("rss", "application/rss+xml");
- registerType("atom", "application/atom+xml");
- registerType("yaml", "application/x-yaml", "text/yaml");
- // just like Rails
- registerType("multipart_form", "multipart/form-data");
- registerType("url_encoded_form", "application/x-www-form-urlencoded");
- // http://www.ietf.org/rfc/rfc4627.txt
- registerType("json", "application/json", "text/x-json");
-
-
- var providesUsed = false;
- var mimeFuns = [];
- var responseContentType = null;
-
- function provides(type, fun) {
- providesUsed = true;
- mimeFuns.push([type, fun]);
- };
-
- function resetProvides() {
- // set globals
- providesUsed = false;
- mimeFuns = [];
- responseContentType = null;
- };
-
- function runProvides(req, ddoc) {
- var supportedMimes = [], bestFun, bestKey = null, accept = req.headers["Accept"];
- if (req.query && req.query.format) {
- bestKey = req.query.format;
- responseContentType = mimesByKey[bestKey][0];
- } else if (accept) {
- // log("using accept header: "+accept);
- mimeFuns.reverse().forEach(function(mimeFun) {
- var mimeKey = mimeFun[0];
- if (mimesByKey[mimeKey]) {
- supportedMimes = supportedMimes.concat(mimesByKey[mimeKey]);
- }
- });
- responseContentType = Mimeparse.bestMatch(supportedMimes, accept);
- bestKey = keysByMime[responseContentType];
- } else {
- // just do the first one
- bestKey = mimeFuns[0][0];
- responseContentType = mimesByKey[bestKey][0];
- }
-
- if (bestKey) {
- for (var i=0; i < mimeFuns.length; i++) {
- if (mimeFuns[i][0] == bestKey) {
- bestFun = mimeFuns[i][1];
- break;
- }
- };
- };
-
- if (bestFun) {
- return bestFun.call(ddoc);
- } else {
- var supportedTypes = mimeFuns.map(function(mf) {
- return mimesByKey[mf[0]].join(', ') || mf[0];
- });
- throw(["error","not_acceptable",
- "Content-Type "+(accept||bestKey)+" not supported, try one of: "+supportedTypes.join(', ')]);
- }
- };
-
-
- return {
- registerType : registerType,
- provides : provides,
- resetProvides : resetProvides,
- runProvides : runProvides,
- providesUsed : function () {
- return providesUsed;
- },
- responseContentType : function () {
- return responseContentType;
- }
- };
-})();
-
-
-
-
-////
-//// Render dispatcher
-////
-////
-////
-////
-
-var Render = (function() {
- var new_header = false;
- var chunks = [];
-
-
- // Start chunks
- var startResp = {};
- function start(resp) {
- startResp = resp || {};
- new_header = true;
- };
-
- function sendStart() {
- startResp = applyContentType((startResp || {}), Mime.responseContentType());
- respond(["start", chunks, startResp]);
- chunks = [];
- startResp = {};
- new_header = false;
- }
-
- function applyContentType(resp, responseContentType) {
- resp["headers"] = resp["headers"] || {};
- if (responseContentType) {
- resp["headers"]["Content-Type"] = resp["headers"]["Content-Type"] || responseContentType;
- }
- return resp;
- }
-
- function send(chunk) {
- chunks.push(chunk.toString());
- };
-
- function blowChunks(label) {
- if (new_header) {
- respond([label||"chunks", chunks, startResp]);
- new_header = false;
- }
- else {
- respond([label||"chunks", chunks]);
- }
- chunks = [];
- };
-
- var gotRow = false, lastRow = false;
- function getRow() {
- if (lastRow) return null;
- if (!gotRow) {
- gotRow = true;
- sendStart();
- } else {
- blowChunks();
- }
- var json = JSON.parse(readline());
- if (json[0] == "list_end") {
- lastRow = true;
- return null;
- }
- if (json[0] != "list_row") {
- throw(["fatal", "list_error", "not a row '" + json[0] + "'"]);
- }
- return json[1];
- };
-
-
- function maybeWrapResponse(resp) {
- var type = typeof resp;
- if ((type == "string") || (type == "xml")) {
- return {body:resp};
- } else {
- return resp;
- }
- };
-
- // from http://javascript.crockford.com/remedial.html
- function typeOf(value) {
- var s = typeof value;
- if (s === 'object') {
- if (value) {
- if (value instanceof Array) {
- s = 'array';
- }
- } else {
- s = 'null';
- }
- }
- return s;
- };
-
- function isDocRequestPath(info) {
- var path = info.path;
- return path.length > 5;
- };
-
- function runShow(fun, ddoc, args) {
- try {
- resetList();
- Mime.resetProvides();
- var resp = fun.apply(ddoc, args) || {};
- resp = maybeWrapResponse(resp);
-
- // handle list() style API
- if (chunks.length && chunks.length > 0) {
- resp.headers = resp.headers || {};
- for(var header in startResp) {
- resp.headers[header] = startResp[header];
- }
- resp.body = chunks.join("") + (resp.body || "");
- resetList();
- }
-
- if (Mime.providesUsed()) {
- var provided_resp = Mime.runProvides(args[1], ddoc) || {};
- provided_resp = maybeWrapResponse(provided_resp);
- resp.body = (resp.body || "") + chunks.join("");
- resp.body += provided_resp.body || "";
- resp = applyContentType(resp, Mime.responseContentType());
- resetList();
- }
-
- var type = typeOf(resp);
- if (type == 'object' || type == 'string') {
- respond(["resp", maybeWrapResponse(resp)]);
- } else {
- throw(["error", "render_error", "undefined response from show function"]);
- }
- } catch(e) {
- if (args[0] === null && isDocRequestPath(args[1])) {
- throw(["error", "not_found", "document not found"]);
- } else {
- renderError(e, fun.toString());
- }
- }
- };
-
- function runUpdate(fun, ddoc, args) {
- try {
- var method = args[1].method;
- // for analytics logging applications you might want to remove the next line
- if (method == "GET") throw(["error","method_not_allowed","Update functions do not allow GET"]);
- var result = fun.apply(ddoc, args);
- var doc = result[0];
- var resp = result[1];
- var type = typeOf(resp);
- if (type == 'object' || type == 'string') {
- respond(["up", doc, maybeWrapResponse(resp)]);
- } else {
- throw(["error", "render_error", "undefined response from update function"]);
- }
- } catch(e) {
- renderError(e, fun.toString());
- }
- };
-
- function resetList() {
- gotRow = false;
- lastRow = false;
- chunks = [];
- startResp = {};
- new_header = false;
- };
-
- function runList(listFun, ddoc, args) {
- try {
- Mime.resetProvides();
- resetList();
- var head = args[0];
- var req = args[1];
- var tail = listFun.apply(ddoc, args);
-
- if (Mime.providesUsed()) {
- tail = Mime.runProvides(req, ddoc);
- }
- if (!gotRow) getRow();
- if (typeof tail != "undefined") {
- chunks.push(tail);
- }
- blowChunks("end");
- } catch(e) {
- renderError(e, listFun.toString());
- }
- };
-
- function runRewrite(fun, ddoc, args) {
- var result;
- try {
- result = fun.apply(ddoc, args);
- } catch(error) {
- renderError(error, fun.toString(), "rewrite_error");
- }
-
- if (!result) {
- respond(["no_dispatch_rule"]);
- return;
- }
-
- if (typeof result === "string") {
- result = {path: result, method: args[0].method};
- }
- respond(["ok", result]);
- }
-
- function renderError(e, funSrc, errType) {
- if (e.error && e.reason || e[0] == "error" || e[0] == "fatal") {
- throw(e);
- } else {
- var logMessage = "function raised error: " +
- (e.toSource ? e.toSource() : e.toString()) + " \n" +
- "stacktrace: " + e.stack;
- log(logMessage);
- throw(["error", errType || "render_error", logMessage]);
- }
- };
-
- function escapeHTML(string) {
- return string && string.replace(/&/g, "&amp;")
- .replace(/</g, "&lt;")
- .replace(/>/g, "&gt;");
- };
-
-
- return {
- start : start,
- send : send,
- getRow : getRow,
- show : function(fun, ddoc, args) {
- // var showFun = Couch.compileFunction(funSrc);
- runShow(fun, ddoc, args);
- },
- update : function(fun, ddoc, args) {
- // var upFun = Couch.compileFunction(funSrc);
- runUpdate(fun, ddoc, args);
- },
- list : function(fun, ddoc, args) {
- runList(fun, ddoc, args);
- },
- rewrite : function(fun, ddoc, args) {
- runRewrite(fun, ddoc, args);
- }
- };
-})();
-
-// send = Render.send;
-// getRow = Render.getRow;
-// start = Render.start;
-
-// unused. this will be handled in the Erlang side of things.
-// function htmlRenderError(e, funSrc) {
-// var msg = ["<html><body><h1>Render Error</h1>",
-// "<p>JavaScript function raised error: ",
-// e.toString(),
-// "</p><h2>Stacktrace:</h2><code><pre>",
-// escapeHTML(e.stack),
-// "</pre></code><h2>Function source:</h2><code><pre>",
-// escapeHTML(funSrc),
-// "</pre></code></body></html>"].join('');
-// return {body:msg};
-// };