]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/javascript/opensrf_xhr.js
ccc3ffd93bdc2728052c604f3ca13d17ff345d41
[OpenSRF.git] / src / javascript / opensrf_xhr.js
1 /* -----------------------------------------------------------------------
2  * Copyright (C) 2008  Georgia Public Library Service
3  * Bill Erickson <erickson@esilibrary.com>
4  *  
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * ----------------------------------------------------------------------- */
15
16 var OSRF_HTTP_HEADER_TO = 'X-OpenSRF-to';
17 var OSRF_HTTP_HEADER_XID = 'X-OpenSRF-xid';
18 var OSRF_HTTP_HEADER_FROM = 'X-OpenSRF-from';
19 var OSRF_HTTP_HEADER_THREAD = 'X-OpenSRF-thread';
20 var OSRF_HTTP_HEADER_TIMEOUT = 'X-OpenSRF-timeout';
21 var OSRF_HTTP_HEADER_SERVICE = 'X-OpenSRF-service';
22 var OSRF_HTTP_HEADER_MULTIPART = 'X-OpenSRF-multipart';
23 var OSRF_HTTP_TRANSLATOR = '/osrf-http-translator'; /* XXX config */
24 var OSRF_POST_CONTENT_TYPE = 'application/x-www-form-urlencoded';
25
26
27 OpenSRF.XHRequest = function(osrf_msg, args) {
28     this.message = osrf_msg;
29     this.args = args;
30     try {
31         this.xreq =  new XMLHttpRequest();
32     } catch(e) {
33         try { 
34             this.xreq = new ActiveXObject("Msxml2.XMLHTTP"); 
35         } catch (e2) {
36             this.xreq = new ActiveXObject("Microsoft.XMLHTTP"); 
37         }
38     }
39 };
40
41 OpenSRF.XHRequest.prototype.send = function() {
42     var xhr_req = this;
43     var xreq = this.xreq;
44     
45     if(this.args.timeout) {
46         /* this is a standard blocking (non-multipart) call */
47         xreq.open('POST', OSRF_HTTP_TRANSLATOR, false);
48
49     } else {
50
51     /* Only Firefox supports multipart calls, but Safari / Chrome include
52            "Mozilla" in their user agent strings... sigh */
53         if(!navigator.userAgent.match(/mozilla/i) || navigator.userAgent.match(/webkit/i) || navigator.userAgent.match(/msie/i)) {
54             /* standard asynchronous call */
55             xreq.onreadystatechange = function() {
56                 if(xreq.readyState == 4)
57                     xhr_req.core_handler();
58             };
59             xreq.open('POST', OSRF_HTTP_TRANSLATOR, true);
60
61         } else {
62
63             /* asynchronous multipart call */
64             xreq.multipart = true;
65             xreq.onload = function(evt) {xhr_req.core_handler();};
66             xreq.open('POST', OSRF_HTTP_TRANSLATOR, true);
67             xreq.setRequestHeader(OSRF_HTTP_HEADER_MULTIPART, 'true');
68
69             /* multipart requests do not pass the status info to the onload if there 
70                is no new data to load.  Capture the status on the readystate handler */
71             xreq.onreadystatechange = function() {
72                 if(xreq.readyState == 4 && xreq.status >= 400)
73                     xhr_req.transport_error_handler();
74             };
75         }
76     }
77
78     xreq.setRequestHeader('Content-Type', OSRF_POST_CONTENT_TYPE);
79     xreq.setRequestHeader(OSRF_HTTP_HEADER_THREAD, this.args.thread);
80     if(this.args.rcpt) {
81         xreq.setRequestHeader(OSRF_HTTP_HEADER_TO, this.args.rcpt);
82     } else {
83         xreq.setRequestHeader(OSRF_HTTP_HEADER_SERVICE, this.args.rcpt_service);
84     }
85
86     var post = 'osrf-msg=' + encodeURIComponent(js2JSON([this.message.serialize()]));
87     xreq.send(post);
88
89     if(this.args.timeout) /* this was a blocking call, manually run the handler */
90         this.core_handler();
91
92     return this;
93 };
94
95 OpenSRF.XHRequest.prototype.core_handler = function() {
96     sender = this.xreq.getResponseHeader(OSRF_HTTP_HEADER_FROM);
97     thread = this.xreq.getResponseHeader(OSRF_HTTP_HEADER_THREAD);
98     json = this.xreq.responseText;
99     stat = this.xreq.status;
100
101     if(stat >= 400) 
102         return this.transport_error_handler();
103
104     OpenSRF.Stack.push(
105         new OpenSRF.NetMessage(null, sender, thread, json),
106         {
107             onresponse : this.args.onresponse,
108             oncomplete : this.args.oncomplete,
109             onerror : this.args.onerror,
110             onmethoderror : this.method_error_handler()
111         }
112     );
113 };
114
115
116 OpenSRF.XHRequest.prototype.method_error_handler = function() {
117     var xhr = this;
118     return function(req, status, status_text) {
119         if(xhr.args.onmethoderror) 
120             xhr.args.onmethoderror(req, status, status_text);
121         if(xhr.args.onerror)  
122             xhr.args.onerror(xhr.message, xhr.args.rcpt || xhr.args.rcpt_service, xhr.args.thread);
123     };
124 };
125
126 OpenSRF.XHRequest.prototype.transport_error_handler = function() {
127     if(this.args.ontransporterror) {
128         this.args.ontransporterror(this.xreq);
129     }
130     if(this.args.onerror) {
131         this.args.onerror(this.message, this.args.rcpt || this.args.rcpt_service, this.args.thread);
132     }
133 };
134
135