001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.http;
021 
022 import js.ArrayLike;
023 import js.Disposable;
024 import js.Js;
025 import js.Vars;
026 import js.core.JsFunction;
027 import js.user.JsClient;
028 import js.user.JsDocument;
029 import js.user.JsXMLHttpRequest;
030 import jsx.client.Client;
031 import jsx.client.Browser;
032 import jsx.core.ArrayLikes;
033 
034 /**
035  * <p>An utility class providing static methods to manipulate HTTP connections and 
036  * transmissions eliminating browser dependencies.</p>
037  * <p>Users are encouraged to use the utilities provided by this class instead of the 
038  * <b>opaque</b> methods of {@link JsXMLHttpRequest} in consideration of the reuse benefit 
039  * for re-compilation results.</p>
040  * 
041  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
042  * @see Ajax
043  */
044 public final class Http extends Disposable
045 {
046     private Http() {}
047 
048     /**
049      * <p>Creates an HTTP request.</p>
050      * @return A {@link JsXMLHttpRequest} object constructed with {@link js.dom.DOM.XMLHttpRequest#create()} 
051      * or {@link js.dom.DOM.ActiveXObject#create(String)} for IE.
052      * @since 1.0
053      */
054     public static final JsXMLHttpRequest create() {
055         return Browser.hasXMLHttpRequest ? Client.XMLHttpRequest.var().create() : create4IE();
056     }
057 
058     /**
059      * <p>Creates an HTTP request that is Java simulated in JS Simulation mode.</p>
060      * @return A {@link JsXMLHttpRequest} object constructed with {@link Js#http()} 
061      * or {@link Js#activeX(String)} for IE.
062      * @since 1.0
063      */
064     public static final JsXMLHttpRequest create2() {
065         return Browser.hasXMLHttpRequest ? Js.http() : create4IE2();
066     }
067 
068     private final static ArrayLike<String> ACTIVEX = new Vars<String>()
069             .add("MSXML2.XMLHTTP.5.0")
070             .add("MSXML2.XMLHTTP.4.0")
071             .add("MSXML2.XMLHTTP.3.0")
072             .add("MSXML2.XMLHTTP")
073             .add("Microsoft.XMLHTTP").var();
074 
075     private static final JsXMLHttpRequest create4IE() {
076         JsXMLHttpRequest ret = null;
077         for (int i = 0, len = ArrayLikes.length(ACTIVEX); Js.not(ret) && i < len; i++) {
078             try {
079                 ret = new JsXMLHttpRequest(
080                         JsClient.ActiveXObject.with(Js.core()).create(ACTIVEX.get(i))
081                 );
082             } catch (Throwable t) {}
083         }
084         return ret;
085     }
086 
087     private static final JsXMLHttpRequest create4IE2() {
088         JsXMLHttpRequest ret = null;
089         for (int i = 0, len = ArrayLikes.length(ACTIVEX); Js.not(ret) && i < len; i++) {
090             try {
091                 ret = new JsXMLHttpRequest(Js.activeX(ACTIVEX.get(i)));
092             } catch (Throwable t) {}
093         }
094         return ret;
095     }
096 
097     /**
098      * <p>Cancels the current HTTP request, closing connections and stopping any pending 
099      * network activity.</p>
100      * <p>This method resets the {@link JsXMLHttpRequest} object to a {@link JsXMLHttpRequest#readyState} 
101      * of {@link JsXMLHttpRequest#UNINITIALIZED} and aborts any pending network activity. 
102      * You might call this method, for example, if a request has taken too long, and the 
103      * response is no longer necessary.</p>
104      * @param http The current HTTP request.
105      * @since 1.0
106      * @see JsXMLHttpRequest#abort()
107      */
108     public static final void abort(JsXMLHttpRequest http) {
109         http.abort();
110     }
111 
112     /**
113      * <p>Returns the HTTP response headers as an unparsed string.</p>
114      * @param http The current HTTP request.
115      * @return <tt>null</tt> if {@link JsXMLHttpRequest#readyState} is less than {@link JsXMLHttpRequest#RECEIVING}; 
116      * Otherwise, it returns all HTTP response headers, but not the status line, sent by 
117      * the server. The headers are returned as a single string, with one header per line. 
118      * Lines are delimited by "\r\n" line terminators.
119      * @since 1.0
120      * @see JsXMLHttpRequest#getAllResponseHeaders()
121      */
122     public static final String getAllResponseHeaders(JsXMLHttpRequest http) {
123         return http.getAllResponseHeaders();
124     }
125 
126     /**
127      * <p>Returns the value of a named HTTP response header.</p>
128      * @param http The current HTTP request.
129      * @param header The name of the HTTP response header whose value is to be returned. 
130      * the <tt>header</tt> name may be specified using any case, as the comparison to 
131      * response headers is case-insensitive.
132      * @return The value of the named HTTP response header, or the empty string if no 
133      * such header was received or if {@link JsXMLHttpRequest#readyState} is less than {@link JsXMLHttpRequest#RECEIVING}. 
134      * If more than one header with the specified name is received, the values of those 
135      * headers are concatenated and returned, using a comma and space as the delimiter.
136      * @since 1.0
137      * @see JsXMLHttpRequest#getResponseHeader(String)
138      */
139     public static final String getResponseHeader(JsXMLHttpRequest http, String header) {
140         return http.getResponseHeader(header);
141     }
142 
143     /**
144      * <p>Returns the {@link JsXMLHttpRequest#onreadystatechange} event handler of the 
145      * current HTTP request.</p>
146      * @param http The current HTTP request.
147      * @return The {@link JsXMLHttpRequest#onreadystatechange} event handler of the 
148      * current HTTP request.
149      * @since 1.0
150      */
151     public static final JsFunction<?> onReadyStateChange(JsXMLHttpRequest http) {
152         return JsXMLHttpRequest.onreadystatechange.with(http);
153     }
154 
155     /**
156      * <p>Sets the {@link JsXMLHttpRequest#onreadystatechange} event handler of the 
157      * current HTTP request to the specified function.</p>
158      * @param http The current HTTP request.
159      * @param f An event handler to be set.
160      * @since 1.0
161      */
162     public static final void onReadyStateChange(JsXMLHttpRequest http, JsFunction<?> f) {
163         JsXMLHttpRequest.onreadystatechange.with(http, f);
164     }
165 
166     /**
167      * <p>Initializes HTTP request parameters, such as the URL and HTTP method, but 
168      * does not send the request.</p>
169      * <p>This method initializes request parameters for later use by the {@link #send(JsXMLHttpRequest, Object)} 
170      * method. It sets {@link JsXMLHttpRequest#readyState} to {@link JsXMLHttpRequest#OPEN}, deletes any previously 
171      * specified request headers and previously received response headers, and sets the 
172      * {@link JsXMLHttpRequest#responseText}, {@link JsXMLHttpRequest#responseXML}, {@link JsXMLHttpRequest#status}, and {@link JsXMLHttpRequest#statusText} 
173      * properties to their default values. It is safe to call this method when {@link JsXMLHttpRequest#readyState} 
174      * is {@link JsXMLHttpRequest#UNINITIALIZED} {when the {@link JsXMLHttpRequest} object is just created 
175      * or after a call to {@link #abort(JsXMLHttpRequest)}), and when {@link JsXMLHttpRequest#readyState} is {@link JsXMLHttpRequest#LOADED}, 
176      * (after a response has been received). The behavior of this method is unspecified 
177      * when it is called from any other state.</p>
178      * <p>Other than storing request parameters for use by {@link #send(JsXMLHttpRequest, Object)} and 
179      * resetting the {@link JsXMLHttpRequest} object for reuse, this method has no other 
180      * behavior. In particular, note that implementations do not typically open a 
181      * network connection to the web server when this method is called.</p>
182      * @param http The current HTTP request.
183      * @param method The HTTP method to be used for the request. Reliably implemented 
184      * values include "GET", "POST", and "HEAD". Implementations may also support other 
185      * methods as well.
186      * @param url The URL that is the subject of the request. Most browsers impose a 
187      * same-origin security policy and require that this URL have the same host name and 
188      * port as the document that contains the script. Relative URLs are resolved in the 
189      * normal way, using the URL of the document that contains the script.
190      * @since 1.0
191      * @see #open(JsXMLHttpRequest, String, String, Boolean)
192      * @see #open(JsXMLHttpRequest, String, String, Boolean, String, String)
193      * @see #send(JsXMLHttpRequest, Object)
194      * @see JsXMLHttpRequest#open(String, String)
195      */
196     public static final void open(JsXMLHttpRequest http, String method, String url) {
197         http.open(method, url);
198     }
199 
200     /**
201      * <p>Initializes HTTP request parameters, such as the URL and HTTP method, but 
202      * does not send the request.</p>
203      * <p>This method initializes request parameters for later use by the {@link #send(JsXMLHttpRequest, Object)} 
204      * method. It sets {@link JsXMLHttpRequest#readyState} to {@link JsXMLHttpRequest#OPEN}, deletes any previously 
205      * specified request headers and previously received response headers, and sets the 
206      * {@link JsXMLHttpRequest#responseText}, {@link JsXMLHttpRequest#responseXML}, {@link JsXMLHttpRequest#status}, and {@link JsXMLHttpRequest#statusText} 
207      * properties to their default values. It is safe to call this method when {@link JsXMLHttpRequest#readyState} 
208      * is {@link JsXMLHttpRequest#UNINITIALIZED} {when the {@link JsXMLHttpRequest} object is just created 
209      * or after a call to {@link #abort(JsXMLHttpRequest)}), and when {@link JsXMLHttpRequest#readyState} is {@link JsXMLHttpRequest#LOADED}, 
210      * (after a response has been received). The behavior of this method is unspecified 
211      * when it is called from any other state.</p>
212      * <p>Other than storing request parameters for use by {@link #send(JsXMLHttpRequest, Object)} and 
213      * resetting the {@link JsXMLHttpRequest} object for reuse, this method has no other 
214      * behavior. In particular, note that implementations do not typically open a 
215      * network connection to the web server when this method is called.</p>
216      * @param http The current HTTP request.
217      * @param method The HTTP method to be used for the request. Reliably implemented 
218      * values include "GET", "POST", and "HEAD". Implementations may also support other 
219      * methods as well.
220      * @param url The URL that is the subject of the request. Most browsers impose a 
221      * same-origin security policy and require that this URL have the same host name and 
222      * port as the document that contains the script. Relative URLs are resolved in the 
223      * normal way, using the URL of the document that contains the script.
224      * @param async Specifies whether the request should be performed asynchronously or 
225      * not. If this argument is <tt>false</tt>, the request is synchronous, and a 
226      * subsequent call to {@link #send(JsXMLHttpRequest, Object)} will block until the response is fully 
227      * received. If this argument is <tt>true</tt> or is undefined, the request is 
228      * asynchronous, and an {@link JsXMLHttpRequest#onreadystatechange} event handler is typically 
229      * required.
230      * @since 1.0
231      * @see #open(JsXMLHttpRequest, String, String)
232      * @see #open(JsXMLHttpRequest, String, String, Boolean, String, String)
233      * @see #send(JsXMLHttpRequest, Object)
234      * @see JsXMLHttpRequest#open(String, String, Boolean)
235      */
236     public static final void open(JsXMLHttpRequest http, String method, String url, Boolean async) {
237         http.open(method, url, async);
238     }
239 
240     /**
241      * <p>Initializes HTTP request parameters, such as the URL and HTTP method, but 
242      * does not send the request.</p>
243      * <p>This method initializes request parameters for later use by the {@link #send(JsXMLHttpRequest, Object)} 
244      * method. It sets {@link JsXMLHttpRequest#readyState} to {@link JsXMLHttpRequest#OPEN}, deletes any previously 
245      * specified request headers and previously received response headers, and sets the 
246      * {@link JsXMLHttpRequest#responseText}, {@link JsXMLHttpRequest#responseXML}, {@link JsXMLHttpRequest#status}, and {@link JsXMLHttpRequest#statusText} 
247      * properties to their default values. It is safe to call this method when {@link JsXMLHttpRequest#readyState} 
248      * is {@link JsXMLHttpRequest#UNINITIALIZED} {when the {@link JsXMLHttpRequest} object is just created 
249      * or after a call to {@link #abort(JsXMLHttpRequest)}), and when {@link JsXMLHttpRequest#readyState} is {@link JsXMLHttpRequest#LOADED}, 
250      * (after a response has been received). The behavior of this method is unspecified 
251      * when it is called from any other state.</p>
252      * <p>Other than storing request parameters for use by {@link #send(JsXMLHttpRequest, Object)} and 
253      * resetting the {@link JsXMLHttpRequest} object for reuse, this method has no other 
254      * behavior. In particular, note that implementations do not typically open a 
255      * network connection to the web server when this method is called.</p>
256      * @param http The current HTTP request.
257      * @param method The HTTP method to be used for the request. Reliably implemented 
258      * values include "GET", "POST", and "HEAD". Implementations may also support other 
259      * methods as well.
260      * @param url The URL that is the subject of the request. Most browsers impose a 
261      * same-origin security policy and require that this URL have the same host name and 
262      * port as the document that contains the script. Relative URLs are resolved in the 
263      * normal way, using the URL of the document that contains the script.
264      * @param async Specifies whether the request should be performed asynchronously or 
265      * not. If this argument is <tt>false</tt>, the request is synchronous, and a 
266      * subsequent call to {@link #send(JsXMLHttpRequest, Object)} will block until the response is fully 
267      * received. If this argument is <tt>true</tt> or is undefined, the request is 
268      * asynchronous, and an {@link JsXMLHttpRequest#onreadystatechange} event handler is typically 
269      * required.
270      * @param username An optional argument specifying authorization user name for use 
271      * with URLs that require authorization. If specified, it overrides the user name 
272      * specified in the URL itself.
273      * @param password An optional argument specifying authorization password for use 
274      * with URLs that require authorization. If specified, it overrides the password 
275      * specified in the URL itself.
276      * @since 1.0
277      * @see #open(JsXMLHttpRequest, String, String)
278      * @see #open(JsXMLHttpRequest, String, String, Boolean)
279      * @see #send(JsXMLHttpRequest, Object)
280      * @see JsXMLHttpRequest#open(String, String, Boolean, String, String)
281      */
282     public static final void open(
283             JsXMLHttpRequest http, String method, String url, Boolean async, String username, String password) {
284         http.open(method, url, async, username, password);
285     }
286 
287     /**
288      * <p>Returns the {@link JsXMLHttpRequest#readyState} property of the current HTTP request.</p>
289      * @param http The current HTTP request.
290      * @return The value of the {@link JsXMLHttpRequest#readyState} property of the current HTTP request.
291      * @since 1.0
292      */
293     public static final Number readyState(JsXMLHttpRequest http) {
294         return JsXMLHttpRequest.readyState.with(http);
295     }
296 
297     /**
298      * <p>Returns the {@link JsXMLHttpRequest#responseText} property of the current HTTP request.</p>
299      * @param http The current HTTP request.
300      * @return The value of the {@link JsXMLHttpRequest#responseText} property of the current HTTP request.
301      * @since 1.0
302      */
303     public static final String responseText(JsXMLHttpRequest http) {
304         return JsXMLHttpRequest.responseText.with(http);
305     }
306 
307     /**
308      * <p>Returns the {@link JsXMLHttpRequest#responseXML} property of the current HTTP request.</p>
309      * @param http The current HTTP request.
310      * @return The value of the {@link JsXMLHttpRequest#responseXML} property of the current HTTP request.
311      * @since 1.0
312      */
313     public static final JsDocument responseXML(JsXMLHttpRequest http) {
314         return JsXMLHttpRequest.responseXML.with(http);
315     }
316 
317     /**
318      * <p>Sends the HTTP request, using parameters passed to the {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)} 
319      * method and an optional request <tt>body</tt> passed to this method.</p>
320      * <p>This method causes an HTTP request to be issued. If there has been no previous 
321      * call to {@link #open(JsXMLHttpRequest, String, String, Boolean)}, or, more generally, if {@link JsXMLHttpRequest#readyState} 
322      * is not {@link JsXMLHttpRequest#OPEN}, this method throws an error. Otherwise, it issues an HTTP 
323      * request that consists of:
324      * <ul>
325      * <li>The HTTP method, URL, and authorization credentials (if any) specified in the 
326      * previous call to {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)}.</li>
327      * <li>The request headers, if any, specified by previous calls to {@link #setRequestHeader(JsXMLHttpRequest, String, String)}.</li>
328      * <li>The <tt>body</tt> argument passed to this method.</li>
329      * </ul>
330      * Once the request has been issued, this method sets {@link JsXMLHttpRequest#readyState} to {@link JsXMLHttpRequest#SENT} 
331      * and triggers the {@link JsXMLHttpRequest#onreadystatechange} event handler.</p>
332      * <p>If the <tt>async</tt> argument to the previous call to {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)} 
333      * was <tt>false</tt>, this method blocks and does not return until {@link JsXMLHttpRequest#readyState} 
334      * is {@link JsXMLHttpRequest#LOADED} and the server's response has been fully received. Otherwise, 
335      * if the <tt>async</tt> argument is <tt>true</tt> or if that argument is undefined, 
336      * this method returns immediately, and the server's response is processed on a 
337      * background thread.</p>
338      * <p>If the server responds with an HTTP redirect, this method or the background 
339      * thread follow the redirect automatically. When all HTTP response headers have 
340      * been received, this method or the background thread sets {@link JsXMLHttpRequest#readyState} to 
341      * {@link JsXMLHttpRequest#RECEIVING} and triggers the {@link JsXMLHttpRequest#onreadystatechange} event handler. 
342      * If the response is long, this method or the background thread may trigger the 
343      * {@link JsXMLHttpRequest#onreadystatechange} more than once while in state {@link JsXMLHttpRequest#RECEIVING}. 
344      * This can serve as a download progress indicator. Finally, when the response is 
345      * complete, this method or the background thread sets {@link JsXMLHttpRequest#readyState} to {@link JsXMLHttpRequest#LOADED} 
346      * and triggers the event handler one last time.</p>
347      * @param http The current HTTP request.
348      * @since 1.0
349      * @see #open(JsXMLHttpRequest, String, String)
350      * @see #open(JsXMLHttpRequest, String, String, Boolean)
351      * @see #open(JsXMLHttpRequest, String, String, Boolean, String, String)
352      * @see JsXMLHttpRequest#send(Object)
353      */
354     public static final void send(JsXMLHttpRequest http) {
355         http.send(null);
356     }
357 
358     /**
359      * <p>Sends the HTTP request, using parameters passed to the {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)} 
360      * method and an optional request <tt>body</tt> passed to this method.</p>
361      * <p>This method causes an HTTP request to be issued. If there has been no previous 
362      * call to {@link #open(JsXMLHttpRequest, String, String, Boolean)}, or, more generally, if {@link JsXMLHttpRequest#readyState} 
363      * is not {@link JsXMLHttpRequest#OPEN}, this method throws an error. Otherwise, it issues an HTTP 
364      * request that consists of:
365      * <ul>
366      * <li>The HTTP method, URL, and authorization credentials (if any) specified in the 
367      * previous call to {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)}.</li>
368      * <li>The request headers, if any, specified by previous calls to {@link #setRequestHeader(JsXMLHttpRequest, String, String)}.</li>
369      * <li>The <tt>body</tt> argument passed to this method.</li>
370      * </ul>
371      * Once the request has been issued, this method sets {@link JsXMLHttpRequest#readyState} to {@link JsXMLHttpRequest#SENT} 
372      * and triggers the {@link JsXMLHttpRequest#onreadystatechange} event handler.</p>
373      * <p>If the <tt>async</tt> argument to the previous call to {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)} 
374      * was <tt>false</tt>, this method blocks and does not return until {@link JsXMLHttpRequest#readyState} 
375      * is {@link JsXMLHttpRequest#LOADED} and the server's response has been fully received. Otherwise, 
376      * if the <tt>async</tt> argument is <tt>true</tt> or if that argument is undefined, 
377      * this method returns immediately, and the server's response is processed on a 
378      * background thread.</p>
379      * <p>If the server responds with an HTTP redirect, this method or the background 
380      * thread follow the redirect automatically. When all HTTP response headers have 
381      * been received, this method or the background thread sets {@link JsXMLHttpRequest#readyState} to 
382      * {@link JsXMLHttpRequest#RECEIVING} and triggers the {@link JsXMLHttpRequest#onreadystatechange} event handler. 
383      * If the response is long, this method or the background thread may trigger the 
384      * {@link JsXMLHttpRequest#onreadystatechange} more than once while in state {@link JsXMLHttpRequest#RECEIVING}. 
385      * This can serve as a download progress indicator. Finally, when the response is 
386      * complete, this method or the background thread sets {@link JsXMLHttpRequest#readyState} to {@link JsXMLHttpRequest#LOADED} 
387      * and triggers the event handler one last time.</p>
388      * @param http The current HTTP request.
389      * @param body If the HTTP method specified by the call to {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)} 
390      * is "POST" or "PUT", this argument specifies the body of the request, as a string 
391      * or {@link js.user.JsDocument} object, or <tt>null</tt> if no body is necessary. For any 
392      * other method, this argument is unused and should be <tt>null</tt>, but some 
393      * implementations do not allow you to omit this argument.
394      * @since 1.0
395      * @see #open(JsXMLHttpRequest, String, String)
396      * @see #open(JsXMLHttpRequest, String, String, Boolean)
397      * @see #open(JsXMLHttpRequest, String, String, Boolean, String, String)
398      * @see JsXMLHttpRequest#send(Object)
399      */
400     public static final void send(JsXMLHttpRequest http, Object body) {
401         http.send(body);
402     }
403 
404     /**
405      * <p>Sets or adds an HTTP request header to an open but unsent request.</p>
406      * <p>This method specifies an HTTP request header that should be included in the 
407      * request issued by a subsequent call to {@link #send(JsXMLHttpRequest, Object)}. This method may be 
408      * called only when {@link JsXMLHttpRequest#readyState} is {@link JsXMLHttpRequest#OPEN}, that is, after a call to 
409      * {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)} but before a call to {@link #send(JsXMLHttpRequest, Object)}.</p>
410      * <p>If a header with the specified name has already been specified, the new value 
411      * for that header is the previously specified value, plus a comma, a space, and the 
412      * value specified in this call.</p>
413      * <p>If the call to {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)} specifies 
414      * authorization credentials, {@link js.user.JsClient#XMLHttpRequest} automatically sends an 
415      * appropriate <tt>Authorization</tt> request header. You can append to this header 
416      * with this method, however. Similarly, if the web browser has stored cookies 
417      * associated with the URL passed to {@link #open(JsXMLHttpRequest, String, String, Boolean, String, String)}, 
418      * appropriate <tt>Cookie</tt> or <tt>Cookie2</tt> headers are automatically included 
419      * with the request. You can append additional cookies to these headers by calling 
420      * this method. {@link js.user.JsClient#XMLHttpRequest} may also provide a default value for 
421      * the <tt>User-Agent</tt> header. If it does this, any value you specify for that 
422      * header is appended to the default value.</p>
423      * <p>Some request headers are automatically set by the {@link js.user.JsClient#XMLHttpRequest} 
424      * for conformance to the HTTP protocol and may not be set with this method. These 
425      * include proxy-related headers as well as the following:
426      * <ul>
427      * <li><tt>Host</tt></li>
428      * <li><tt>Connection</tt></li>
429      * <li><tt>Keep-Alive</tt></li>
430      * <li><tt>Accept-Charset</tt></li>
431      * <li><tt>Accept-Encoding</tt></li>
432      * <li><tt>If-Modified-Since</tt></li>
433      * <li><tt>If-None-Match</tt></li>
434      * <li><tt>If-Range</tt></li>
435      * <li><tt>Range</tt></li>
436      * </ul></p>
437      * @param http The current HTTP request.
438      * @param name The name of the header to be set. This argument should not contain 
439      * spaces, colons, linefeeds, or newlines.
440      * @param value The value for the header. This argument should not contain 
441      * linefeeds or newlines.
442      * @since 1.0
443      * @see JsXMLHttpRequest#setRequestHeader(String, String)
444      */
445     public static final void setRequestHeader(JsXMLHttpRequest http, String name, String value) {
446         http.setRequestHeader(name, value);
447     }
448 
449     /**
450      * <p>Returns the {@link JsXMLHttpRequest#status} property of the current HTTP request.</p>
451      * @param http The current HTTP request.
452      * @return The value of the {@link JsXMLHttpRequest#status} property of the current HTTP request.
453      * @since 1.0
454      */
455     public static final Number status(JsXMLHttpRequest http) {
456         return isLoaded(http) ? JsXMLHttpRequest.status.with(http) : null;
457     }
458 
459     /**
460      * <p>Returns the {@link JsXMLHttpRequest#statusText} property of the current HTTP request.</p>
461      * @param http The current HTTP request.
462      * @return The value of the {@link JsXMLHttpRequest#statusText} property of the current HTTP request.
463      * @since 1.0
464      */
465     public static final String statusText(JsXMLHttpRequest http) {
466         return isLoaded(http) ? JsXMLHttpRequest.statusText.with(http) : null;
467     }
468 
469     /**
470      * <p>Determines if the current HTTP request is open.</p>
471      * @param http The current HTTP request.
472      * @return <tt>true</tt> if the current HTTP request is open; <tt>false</tt>, otherwise.
473      * @since 1.0
474      */
475     public static final boolean isOpen(JsXMLHttpRequest http) {
476         return Js.be(http) && Js.eq(JsXMLHttpRequest.readyState.with(http), JsXMLHttpRequest.OPEN);
477     }
478 
479     /**
480      * <p>Determines if the current HTTP request is loaded.</p>
481      * @param http The current HTTP request.
482      * @return <tt>true</tt> if the current HTTP request is loaded; <tt>false</tt>, otherwise.
483      * @since 1.0
484      */
485     public static final boolean isLoaded(JsXMLHttpRequest http) {
486         return Js.be(http) && Js.eq(JsXMLHttpRequest.readyState.with(http), JsXMLHttpRequest.LOADED);
487     }
488 }