1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
var asURIEncodedString = operator(); |
18 |
var serializeOn = operator(); |
19 |
var Parameter = function(name, value) { |
20 |
return objectWithAncestors(function(method) { |
21 |
method(asURIEncodedString, function(self) { |
22 |
return encodeURIComponent(name) + '=' + encodeURIComponent(value); |
23 |
}); |
24 |
|
25 |
method(serializeOn, function(self, query) { |
26 |
addParameter(query, self); |
27 |
}); |
28 |
}, Cell(name, value)); |
29 |
}; |
30 |
|
31 |
var addParameter = operator(); |
32 |
var addNameValue = operator(); |
33 |
var queryParameters = operator(); |
34 |
var addQuery = operator(); |
35 |
var appendToURI = operator(); |
36 |
var Query = function() { |
37 |
var parameters = []; |
38 |
return object(function(method) { |
39 |
method(queryParameters, function(self) { |
40 |
return parameters; |
41 |
}); |
42 |
|
43 |
method(addParameter, function(self, parameter) { |
44 |
append(parameters, parameter); |
45 |
return self; |
46 |
}); |
47 |
|
48 |
method(addNameValue, function(self, name, value) { |
49 |
append(parameters, Parameter(name, value)); |
50 |
return self; |
51 |
}); |
52 |
|
53 |
method(addQuery, function(self, appended) { |
54 |
serializeOn(appended, self); |
55 |
return self; |
56 |
}); |
57 |
|
58 |
method(serializeOn, function(self, query) { |
59 |
each(parameters, curry(addParameter, query)); |
60 |
}); |
61 |
|
62 |
method(asURIEncodedString, function(self) { |
63 |
return join(collect(parameters, asURIEncodedString), '&'); |
64 |
}); |
65 |
|
66 |
method(appendToURI, function(self, uri) { |
67 |
if (not(isEmpty(parameters))) { |
68 |
return uri + (contains(uri, '?') ? '&' : '?') + asURIEncodedString(self); |
69 |
} else { |
70 |
return uri; |
71 |
} |
72 |
}); |
73 |
|
74 |
method(asString, function(self) { |
75 |
return inject(parameters, '', function(tally, p) { |
76 |
return tally + '|' + key(p) + '=' + value(p) + '|\n'; |
77 |
}); |
78 |
}); |
79 |
}); |
80 |
}; |
81 |
|
82 |
var getSynchronously = operator(); |
83 |
var getAsynchronously = operator(); |
84 |
var postSynchronously = operator(); |
85 |
var postAsynchronously = operator(); |
86 |
var Client = function(autoclose) { |
87 |
var newNativeRequest; |
88 |
if (window.XMLHttpRequest) { |
89 |
newNativeRequest = function() { |
90 |
return new XMLHttpRequest(); |
91 |
}; |
92 |
} else if (window.ActiveXObject) { |
93 |
newNativeRequest = function() { |
94 |
return new window.ActiveXObject('Microsoft.XMLHTTP'); |
95 |
}; |
96 |
} else { |
97 |
throw 'cannot create XMLHttpRequest'; |
98 |
} |
99 |
|
100 |
function withNewQuery(setup) { |
101 |
var query = Query(); |
102 |
setup(query); |
103 |
return query; |
104 |
} |
105 |
|
106 |
var autoClose = autoclose ? close : noop; |
107 |
|
108 |
return object(function(method) { |
109 |
method(getAsynchronously, function(self, uri, setupQuery, setupRequest, onResponse) { |
110 |
var nativeRequestResponse = newNativeRequest(); |
111 |
var request = RequestProxy(nativeRequestResponse); |
112 |
var response = ResponseProxy(nativeRequestResponse); |
113 |
nativeRequestResponse.open('GET', appendToURI(withNewQuery(setupQuery), uri), true); |
114 |
setupRequest(request); |
115 |
nativeRequestResponse.onreadystatechange = function() { |
116 |
if (nativeRequestResponse.readyState == 4) { |
117 |
onResponse(response, request); |
118 |
autoClose(request); |
119 |
} |
120 |
}; |
121 |
nativeRequestResponse.send(''); |
122 |
return request; |
123 |
}); |
124 |
|
125 |
method(getSynchronously, function(self, uri, setupQuery, setupRequest, onResponse) { |
126 |
var nativeRequestResponse = newNativeRequest(); |
127 |
var request = RequestProxy(nativeRequestResponse); |
128 |
var response = ResponseProxy(nativeRequestResponse); |
129 |
nativeRequestResponse.open('GET', appendToURI(withNewQuery(setupQuery), uri), false); |
130 |
setupRequest(request); |
131 |
nativeRequestResponse.send(''); |
132 |
onResponse(response, request); |
133 |
autoClose(request); |
134 |
}); |
135 |
|
136 |
method(postAsynchronously, function(self, uri, setupQuery, setupRequest, onResponse) { |
137 |
var nativeRequestResponse = newNativeRequest(); |
138 |
var request = RequestProxy(nativeRequestResponse); |
139 |
var response = ResponseProxy(nativeRequestResponse); |
140 |
nativeRequestResponse.open('POST', uri, true); |
141 |
setupRequest(request); |
142 |
nativeRequestResponse.onreadystatechange = function() { |
143 |
if (nativeRequestResponse.readyState == 4) { |
144 |
onResponse(response, request); |
145 |
autoClose(request); |
146 |
} |
147 |
}; |
148 |
nativeRequestResponse.send(asURIEncodedString(withNewQuery(setupQuery))); |
149 |
return request; |
150 |
}); |
151 |
|
152 |
method(postSynchronously, function(self, uri, setupQuery, setupRequest, onResponse) { |
153 |
var nativeRequestResponse = newNativeRequest(); |
154 |
var request = RequestProxy(nativeRequestResponse); |
155 |
var response = ResponseProxy(nativeRequestResponse); |
156 |
nativeRequestResponse.open('POST', uri, false); |
157 |
setupRequest(request); |
158 |
nativeRequestResponse.send(asURIEncodedString(withNewQuery(setupQuery))); |
159 |
onResponse(response, request); |
160 |
autoClose(request); |
161 |
}); |
162 |
}); |
163 |
}; |
164 |
|
165 |
var close = operator(); |
166 |
var abort = operator(); |
167 |
var setHeader = operator(); |
168 |
var onResponse = operator(); |
169 |
var RequestProxy = function(nativeRequestResponse) { |
170 |
return object(function(method) { |
171 |
method(setHeader, function(self, name, value) { |
172 |
nativeRequestResponse.setRequestHeader(name, value); |
173 |
}); |
174 |
|
175 |
method(close, function(self) { |
176 |
nativeRequestResponse.onreadystatechange = noop; |
177 |
}); |
178 |
|
179 |
method(abort, function(self) { |
180 |
nativeRequestResponse.onreadystatechange = noop; |
181 |
nativeRequestResponse.abort(); |
182 |
method(abort, noop); |
183 |
}); |
184 |
}); |
185 |
}; |
186 |
|
187 |
var statusCode = operator(); |
188 |
var statusText = operator(); |
189 |
var getHeader = operator(); |
190 |
var getAllHeaders = operator(); |
191 |
var hasHeader = operator(); |
192 |
var contentAsText = operator(); |
193 |
var contentAsDOM = operator(); |
194 |
var ResponseProxy = function(nativeRequestResponse) { |
195 |
return object(function(method) { |
196 |
method(statusCode, function() { |
197 |
try { |
198 |
return nativeRequestResponse.status; |
199 |
} catch (e) { |
200 |
return 0; |
201 |
} |
202 |
}); |
203 |
|
204 |
method(statusText, function(self) { |
205 |
try { |
206 |
return nativeRequestResponse.statusText; |
207 |
} catch (e) { |
208 |
return ''; |
209 |
} |
210 |
}); |
211 |
|
212 |
method(hasHeader, function(self, name) { |
213 |
try { |
214 |
var header = nativeRequestResponse.getResponseHeader(name); |
215 |
return header && header != ''; |
216 |
} catch (e) { |
217 |
return false; |
218 |
} |
219 |
}); |
220 |
|
221 |
method(getHeader, function(self, name) { |
222 |
try { |
223 |
return nativeRequestResponse.getResponseHeader(name); |
224 |
} catch (e) { |
225 |
return null; |
226 |
} |
227 |
}); |
228 |
|
229 |
method(getAllHeaders, function(self, name) { |
230 |
try { |
231 |
return collect(reject(split(nativeRequestResponse.getAllResponseHeaders(), '\n'), isEmpty), function(pair) { |
232 |
var nameValue = split(pair, ': ') |
233 |
return Cell(nameValue[0], nameValue[1]); |
234 |
}); |
235 |
} catch (e) { |
236 |
return []; |
237 |
} |
238 |
}); |
239 |
|
240 |
method(contentAsText, function(self) { |
241 |
try { |
242 |
return nativeRequestResponse.responseText; |
243 |
} catch (e) { |
244 |
return ''; |
245 |
} |
246 |
}); |
247 |
|
248 |
method(contentAsDOM, function(self) { |
249 |
return nativeRequestResponse.responseXML; |
250 |
}); |
251 |
|
252 |
method(asString, function(self) { |
253 |
return inject(getAllHeaders(self), 'HTTP Response\n', function(result, header) { |
254 |
return result + key(header) + ': ' + value(header) + '\n'; |
255 |
}) + contentAsText(self); |
256 |
}); |
257 |
}); |
258 |
}; |
259 |
|
260 |
function OK(response) { |
261 |
return statusCode(response) == 200; |
262 |
} |
263 |
|
264 |
function NotFound(response) { |
265 |
return statusCode(response) == 404; |
266 |
} |
267 |
|
268 |
function ServerInternalError(response) { |
269 |
var code = statusCode(response); |
270 |
return code >= 500 && code < 600; |
271 |
} |
272 |
|
273 |
function FormPost(request) { |
274 |
setHeader(request, 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); |
275 |
} |