1 /** 2 * @fileOverview Helpers for the HTTP response. 3 */ 4 5 /** @ignore */ 6 var _ajn = appjet._native; 7 8 /** 9 * @type object 10 */ 11 var response = {}; 12 13 /** 14 * Halts the program immediately and returns 403 Forbidden error to the user. 15 */ 16 response.forbid = function() { 17 _ajn.response_error(403, "Forbidden"); 18 }; 19 20 /** 21 * Halts the program immediately, optionally printing the page so far. 22 * 23 * @param {boolean} renderCurrentPage if false, an empty page will be rendered, 24 * otherwise calls to print() so far will be displayed. Either way, no more 25 * code will be executed. 26 */ 27 response.stop = function(renderCurrentPage) { 28 if (renderCurrentPage !== false) { 29 var p = page.render(); 30 if (p.length > 0) 31 _ajn.write(p.join('')); 32 } 33 _ajn.response_stop(); 34 }; 35 36 /** 37 * Halts the program immediately and returns a 404 not found error to the user. 38 */ 39 response.notFound = function() { 40 _ajn.response_error(404, "Not found"); 41 }; 42 43 /** 44 * Halts the program immediately and sends an HTTP redirect response (302), 45 * redirecting to the given path (relative or absolute). 46 * 47 * @param {string} path The new path 48 */ 49 response.redirect = function(path) { 50 if ((! path) && path != "") 51 throw new Error("Invalid redirect: "+path) 52 _ajn.response_redirect(path); 53 }; 54 55 /** 56 * Sets the status code in the HTTP response. 57 * 58 * @param {number} newCode 59 */ 60 response.setStatusCode = function(newCode) { 61 _ajn.response_setStatusCode(newCode); 62 }; 63 64 /** 65 * Sets any header of the HTTP response. 66 * 67 * @example 68 response.setHeader('Cache-Control', 'no-cache'); 69 * 70 * @param {string} name 71 * @param {string} value 72 */ 73 response.setHeader = function(name, value) { 74 _ajn.response_setHeader(name, value); 75 }; 76 77 /** 78 * Adds the name,value pair to the headers. Useful for headers that are 79 * allowed to repeat, such as Set-Cookie. 80 * 81 * @param {string} name 82 * @param {string} value 83 */ 84 response.addHeader = function(name, value) { 85 _ajn.response_addHeader(name, value); 86 }; 87 88 /** 89 * Low-level hook for writing raw data to the response. 90 * @param {string} data will be written, verbatim, to the HTTP resonse. 91 */ 92 response.write = function(data) { 93 _ajn.write(data); 94 }; 95 96 /** 97 * Low-level hook for writing raw byte data to the response. Especially 98 * useful for writing the result of a <code>wget</code> of image data, 99 * or writing an uploaded file. 100 * @param {string} data will be written, verbatim, to the HTTP resonse. 101 */ 102 response.writeBytes = function(data) { 103 _ajn.writeBytes(data); 104 }; 105 106 //---------------------------------------------------------------- 107 // Cookies! 108 //---------------------------------------------------------------- 109 110 /** 111 * Set a cookie in the response. 112 * 113 * @example 114 response.setCookie({ 115 name: "SessionID", 116 value: "25", 117 secure: true, 118 expires: 14 // 14 days 119 }); 120 * 121 * @param {object} cookieObject This may contain any of the following: 122 <ul> 123 <li>name (required): The name of the cookie</li> 124 <li>value (required): The value of the cookie. (Note: this value will be escaped). 125 <li>expires (optional): If an integer, means number of days until it expires; 126 if a Date object, means exact date on which to expire.</li> 127 <li>domain (optional): The cookie domain</li> 128 <li>path (optional): To restrict the cookie to a specific path.</li> 129 <li>secure (optional): Whether this cookie should only be sent securely.</li> 130 </ul> 131 */ 132 response.setCookie = function(cookieObject) { 133 response.addHeader('Set-Cookie', _cookiestring(cookieObject)); 134 }; 135 136 137 /** 138 * Tells the client to delete the cookie of the given name (by setting 139 * its expiration time to zero). 140 * @param {string} name The name of the cookie to delete. 141 */ 142 response.deleteCookie = function(name) { 143 response.setCookie({name: name, value: '', expires: 0}); 144 }; 145 146 /** 147 * Sets the Content-Type header of the response. If the content-type includes 148 * a charset, that charset is used to send the response. 149 * @param {string} contentType the new content-type 150 */ 151 response.setContentType = function(contentType) { 152 _ajn.response_setContentType(contentType); 153 } 154 155 /** @ignore */ 156 function _cookiestring(c) { 157 var x = ''; 158 if (!c.name) { throw new Error('cookie name is required'); } 159 if (!c.value) { c.value = ''; } 160 x += (c.name + '=' + escape(c.value)); 161 162 // expires 163 if (c.expires instanceof Date) { 164 x += ('; expires='+_cookiedate(c.expires)); 165 } 166 if (typeof(c.expires) == 'number') { 167 var today = (new Date()).valueOf(); 168 var d = new Date(today + 86400000*c.expires); 169 x += ('; expires='+_cookiedate(d)); 170 } 171 172 // domain 173 if (c.domain) { x += ('; domain='+c.domain); } 174 175 // path 176 if (c.path) { x += ('; path='+c.path); } 177 178 // secure 179 if (c.secure == true) { x += '; secure'; } 180 181 return x; 182 } 183 184 /** @ignore */ 185 function _cookiedate(d) { 186 var x = d.toGMTString(); 187 var p = x.split(' '); 188 return [p[0], [p[1], p[2], p[3]].join('-'), p[4], p[5]].join(' '); 189 } 190 191 /** 192 * Tells the client to cache the page. By default, clients are told to 193 * not never cache pages. (To send no caching-related headers at all, pass 194 * <code>undefined</code>.) 195 * @param {boolean} cacheable 196 */ 197 response.setCacheable = function(cacheable) { 198 appjet._internal.cacheable = cacheable; 199 } 200 201 /** @ignore */ 202 appjet._internal.cacheable = false; 203