stdweb/webapi/
xml_http_request.rs

1use webapi::event_target::{IEventTarget, EventTarget};
2use webapi::dom_exception::{InvalidAccessError, InvalidStateError};
3use webcore::unsafe_typed_array::UnsafeTypedArray;
4use webcore::value::{
5    Reference,
6    Value,
7};
8use webcore::try_from::{TryFrom, TryInto};
9use private::TODO;
10
11/// Use XmlHttpRequest (XHR) objects to interact with servers.
12/// You can retrieve data from a URL without having to do a full page refresh.
13/// This enables a Web page to update just part of a page without disrupting
14/// what the user is doing. XmlHttpRequest is used heavily in Ajax programming.
15///
16/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XmlHttpRequest)
17// https://xhr.spec.whatwg.org/#xmlhttprequest
18#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
19#[reference(instance_of = "XMLHttpRequest")]
20#[reference(subclass_of(EventTarget))]
21pub struct XmlHttpRequest( Reference );
22
23/// An enum indicating the state of the `XmlHttpRequest`.
24///
25/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState)
26// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
27#[derive(Copy, Clone, PartialEq, Eq, Debug)]
28pub enum XhrReadyState {
29    /// Client has been created. [open()](struct.XmlHttpRequest.html#method.open) not called yet.
30    Unsent,
31    /// [open()](struct.XmlHttpRequest.html#method.open) has been called.
32    Opened,
33    /// [send()](struct.XmlHttpRequest.html#method.send) has been called, and headers and [status()](struct.XmlHttpRequest.html#method.status) are available.
34    HeadersReceived,
35    /// Downloading; [reponse_text()](struct.XmlHttpRequest.html#method.reponse_text) holds partial data.
36    Loading,
37    /// The operation is complete.
38    Done,
39}
40
41/// An enum describing the type of the response to `XmlHttpRequest`
42///
43/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType)
44// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-responsetype
45#[derive(Copy, Clone, PartialEq, Eq, Debug)]
46pub enum XhrResponseType {
47    /// A JavaScript ArrayBuffer containing binary data
48    ArrayBuffer,
49    /// A Blob object container the binary data
50    Blob,
51    /// An HTML Document or XML XMLDocument
52    Document,
53    /// A JavaScript object parsed from JSON
54    Json,
55    /// Text in a String object
56    Text
57}
58
59impl IEventTarget for XmlHttpRequest {}
60
61error_enum_boilerplate! {
62    /// An error returned from `XmlHttpRequest::set_response_type`
63    XhrSetResponseTypeError,
64
65    #[allow(missing_docs)]
66    InvalidStateError,
67    #[allow(missing_docs)]
68    InvalidAccessError
69}
70
71impl XmlHttpRequest {
72    /// Creates new `XmlHttpRequest`.
73    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest
74    pub fn new() -> XmlHttpRequest {
75        js!( return new XMLHttpRequest(); ).try_into().unwrap()
76    }
77
78    /// Returns the current state of the request as a [XhrReadyState](enum.XhrReadyState.html).
79    ///
80    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState)
81    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-readystate
82    pub fn ready_state(&self) -> XhrReadyState {
83        use self::XhrReadyState::*;
84        let state: u16 = js!( return @{self}.readyState; ).try_into().unwrap();
85        match state {
86            0 => Unsent,
87            1 => Opened,
88            2 => HeadersReceived,
89            3 => Loading,
90            4 => Done,
91            _ => unreachable!( "Unexpected value of XMLHttpRequest::readyState: {}", state )
92        }
93    }
94
95    /// Returns the type of the request as a [XhrResponseType](enum.XhrResponseType.html)
96    ///
97    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType)
98    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-responsetype
99    pub fn response_type(&self) -> XhrResponseType {
100        use self::XhrResponseType::*;
101        let repsonse_type: String = js! ( return @{self}.responseType; ).try_into().unwrap();
102        match repsonse_type.as_str() {
103            "arraybuffer" => ArrayBuffer,
104            "blob" => Blob,
105            "document" => Document,
106            "json" => Json,
107            "text" | "" => Text,
108            x => unreachable!( "Unexpected value of XMLHttpRequest::responseType:: {}", x)
109        }
110    }
111
112    /// Set the type that the XmlHttpRequest should return
113    ///
114    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType)
115    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-responsetype
116    pub fn set_response_type(&self, kind: XhrResponseType) -> Result<(), XhrSetResponseTypeError> {
117        use self::XhrResponseType::*;
118        let response_type = match kind {
119            ArrayBuffer => "arraybuffer",
120            Blob => "blob",
121            Document => "document",
122            Json => "json",
123            Text => "text"
124        };
125
126        js_try!(
127            @{self}.responseType = @{response_type};
128        ).unwrap()
129    }
130
131    /// Returns a string that contains the response to the request as text, or None
132    /// if the request was unsuccessful or has not yet been sent.
133    ///
134    ///[(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText)
135    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-responsetext
136    pub fn response_text(&self) -> Result< Option< String >, TODO > {
137        let response = js!(return @{self}.responseText;);
138        match response {
139            Value::Null => Ok( None ),
140            Value::String( resp ) => Ok( Some( resp ) ),
141            _ => unreachable!(),
142        }
143    }
144
145    /// Returns the object representing the response
146    ///
147    ///[(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response)
148    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-response
149    pub fn raw_response(&self) -> Value {
150        js!(return @{self}.response;)
151    }
152
153    /// Returns an unsigned short with the status of the response of the request.
154    ///
155    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/status)
156    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-status
157    pub fn status(&self) -> u16 {
158        js!(return @{self}.status;).try_into().unwrap()
159    }
160
161    /// Open connection with given method (ie GET or POST), and the url to hit.
162    ///
163    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open)
164    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-open
165    pub fn open(&self, method: &str, url: &str) -> Result< (), TODO > {
166        js! { @(no_return)
167            @{self}.open(@{method}, @{url}, true);
168        };
169
170        Ok(())
171    }
172
173    /// Returns the string containing the text of the specified header. If there
174    /// are multiple response headers with the same name, then their values are
175    /// returned as a single concatenated string.
176    ///
177    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/getResponseHeader)
178    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-getresponseheader
179    pub fn get_response_header(&self, header: &str) -> Option<String> {
180        let header = js!( return @{self}.getResponseHeader(@{header}); );
181        match header {
182            Value::Null => None,
183            Value::String(text) => Some(text),
184            _ => unreachable!(),
185        }
186    }
187
188    /// Sets the value of an HTTP request header. Must be called after `open()`,
189    /// but before `send()`. If this method is called several times with the same
190    /// header, the values are merged into one single request header.
191    ///
192    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader)
193    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-setrequestheader
194    pub fn set_request_header(&self, header: &str, value: &str) -> Result< (), TODO > {
195        js! { @(no_return)
196            @{self}.setRequestHeader(@{header}, @{value});
197        };
198
199        Ok(())
200    }
201
202    /// Send request on an open connection with no data
203    ///
204    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
205    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-send
206    pub fn send(&self) -> Result< (), TODO > {
207        js! { @(no_return)
208            @{self}.send();
209        };
210
211        Ok(())
212    }
213
214    /// Send request on an open connection with string body
215    ///
216    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
217    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-send
218    pub fn send_with_string(&self, body: &str) -> Result< (), TODO > {
219        js! { @(no_return)
220            @{self}.send(@{body});
221        };
222
223        Ok(())
224    }
225
226    /// Send request on an open connection with a byte array body
227    ///
228    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send)
229    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-send
230    pub fn send_with_bytes(&self, body: &[u8]) -> Result< (), TODO > {
231        js! { @(no_return)
232            @{self}.send(@{UnsafeTypedArray(body)});
233        };
234
235        Ok(())
236    }
237
238    /// Aborts the request if it has already been sent.
239    /// When a request is aborted, its [ready_state](struct.XmlHttpRequest.html#method.ready_state) is changed to [Done](enum.XhrReadyState.html#variant.Done)
240    /// and the [status](struct.XmlHttpRequest.html#method.status) code is set to
241    /// [Unsent](enum.XhrReadyState.html#variant.Unsent).
242    ///
243    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/abort)
244    // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest-abort
245    pub fn abort(&self) {
246        js! { @(no_return)
247            @{self}.abort();
248        };
249    }
250}