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