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