1 2 /** 3 * @fileOverview Helpers for reading data from the HTTP request. 4 */ 5 6 /** @ignore */ 7 var _ajn = appjet._native; 8 9 /** 10 * Note: you can call print(request) to see a nice display for debugging. 11 * 12 * @type object 13 */ 14 var request = {}; 15 16 /** 17 * The request path following the hostname. For example, if the user 18 * is visiting yourapp.appjet.net/foo, then this will be set to 19 * "/foo". 20 * 21 * This does not include CGI parameters or the domain name, and always 22 * begins with a "/". 23 * 24 * @type string 25 */ 26 request.path = _ajn.request_path(); 27 28 /** 29 * The value request query string. 30 * 31 * For example, if the user visits "yourapp.appjet.net/foo?id=20", then 32 * request.query will be "id=20". 33 * 34 * @type string 35 */ 36 request.query = _ajn.request_query(); 37 38 /** 39 * Either "GET" or "POST" (uppercase). 40 * @type string 41 */ 42 request.method = _ajn.request_method().toUpperCase(); 43 44 /** 45 * Whether the curent HTTP request is a GET request. 46 * @type boolean 47 */ 48 request.isGet = (request.method == "GET"); 49 50 /** @ignore COMPAT */ 51 request.isGET = request.isGet; 52 53 /** 54 * Whether the current HTTP request is a POST request. 55 * @type boolean 56 */ 57 request.isPost = (request.method == "POST"); 58 59 /** @ignore COMPAT */ 60 request.isPOST = request.isPost; 61 62 /** 63 * Whether the current HTTP request is a CRON request. 64 * @type boolean 65 */ 66 request.isCron = (request.method == "CRON"); 67 68 /** 69 * Holds the IP address of the user making the request. 70 * @type string 71 */ 72 request.clientAddr = _ajn.request_remoteAddr(); 73 74 /** @ignore COMPAT */ 75 request.param = function (paramName) { 76 return request.params[paramName]; 77 }; 78 79 /** 80 * Parameters associated with the request, either from the query string 81 * or from the contents of a POST, e.g. from a form. Parameters are accessible 82 * by name as properties of this object. The property value is either a 83 * string (typically) or an array of strings (if the parameter occurs 84 * multiple times in the request). 85 * 86 * @type object 87 */ 88 request.params = {}; 89 90 /** @ignore */ 91 (function () { 92 var paramNameArray = _ajn.request_paramNames(); 93 if (!paramNameArray) { return; } 94 paramNameArray.forEach(function (paramName) { 95 var val = _arrayToStringOrArray(_ajn.request_param(paramName)); 96 if (val != undefined) { 97 _addIfNotPresent(request.params, paramName, val); 98 } 99 }); 100 })(); 101 102 103 /** 104 * Used to access the HTTP headers of the current request. Properties are 105 * header names, and each value is either a string (typically) or an 106 * array of strings (if the header occurs multiple times in the request). 107 * 108 * @example 109 print(request.headers["User-Agent"]); 110 * 111 * @type object 112 */ 113 request.headers = {}; 114 115 /** @ignore */ 116 (function () { 117 var headerNameArray = _ajn.request_headerNames(); 118 if (!headerNameArray) { return; } 119 headerNameArray.forEach(function (headerName) { 120 var val = _arrayToStringOrArray(_ajn.request_header(headerName)); 121 if (val != undefined) { 122 _addIfNotPresent(request.headers, _headerCapitalize(headerName), val); 123 } 124 }); 125 })(); 126 127 /** @ignore COMPAT */ 128 request.getHeader = function(headerName) { 129 return request.headers[headerName]; 130 } 131 132 function _headerCapitalize(str) { 133 function initialCapitalize(str) { 134 if (str.length < 1) return str; 135 return str.substring(0,1).toUpperCase()+str.substring(1).toLowerCase(); 136 } 137 return str.split("-").map(initialCapitalize).join("-"); 138 } 139 140 /** 141 * Contains a map of name:value of all the cookies sent with the 142 * request. All values are strings. 143 * 144 * @example 145 if (request.cookies['SessionID'] == "25") { 146 // process session number 25 147 } 148 * 149 * @type object 150 */ 151 request.cookies = {}; 152 153 /** @ignore */ 154 (function () { 155 var cookieHeaderArray = _ajn.request_header('Cookie'); 156 if (!cookieHeaderArray) { return; } 157 var name, val; 158 cookieHeaderArray.forEach(function (cookieHeader) { 159 cookieHeader.split(';').forEach(function(cs) { 160 var parts = cs.split('='); 161 if (parts.length == 2) { 162 name = trim(parts[0]); 163 val = trim(unescape(parts[1])); 164 _addIfNotPresent(request.cookies, name, val); 165 } 166 }); 167 }); 168 })(); 169 170 function _addIfNotPresent(obj, key, value) { 171 if (!(key in obj)) obj[key] = value; 172 } 173 174 function _arrayToStringOrArray(value) { 175 if (value == undefined || !(value instanceof Array)) return undefined; 176 if (value.length < 1) return undefined; 177 if (value.length == 1) return value[0]; 178 return value; 179 } 180 181 /** 182 * Enables pretty-printing of request object for debugging. 183 * 184 * @return {string} html-formatted string. 185 */ 186 request.toHTML = function() { 187 function paramlist() { 188 var ul = UL(); 189 for(p in request.params) { 190 ul.push(LI(I(p), ": ", request.params[p])); 191 } 192 return ul; 193 } 194 function cookielist() { 195 var ul = UL(); 196 eachProperty(request.cookies, function(n, v) { 197 ul.push(LI(I(n), ": ", v.toString())); 198 }); 199 return ul; 200 } 201 var t = TABLE({border: 1, cellspacing: 0, cellpadding: 2}); 202 var fields = [ 203 ['method', this.method], 204 ['path', this.path], 205 ['query', this.query], 206 ['clientAddr', this.clientAddr], 207 ['params', paramlist()], 208 ['cookies', cookielist()] 209 ]; 210 fields.forEach(function(f) { 211 var v = f[1] !== undefined ? f[1] : ''; 212 t.push(TR(TD(f[0]), TD(v))); 213 }); 214 return t.toHTML(); 215 }; 216 217