CXM_http_get_common.anubis
6.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
*Project* The Anubis Project
*Title* Getting a document from the Web.
*Copyright* Copyright (c) Alain Prouté 2001.
*Author* Alain Prouté
This file contains the types and functions which are common to 'http_get' and
'https_get'.
read tools/basis.anubis
read tools/findstring.anubis
read system/string.anubis
read CXM_common.anubis
read web/html.anubis
Body of HTTP requests may also contain name-value pairs. We call them HTTP arguments:
public type HTTP_argument:
http_argument(String name, String value).
We begin by several simple tools.
'crlf' and 'crlfcrlf' are defined in 'basis.anubis'.
public define Maybe(Int32)
has_double_crlf
(
String s,
) =
find(crlfcrlf,s,0).
Formatting a list of HTTP arguments.
public define String
format_http_args
(
List(HTTP_argument) l
) =
if l is
{
[ ] then "",
[h . t] then
if t is
{
[ ] then if h is http_argument(n,v) then n + "=" + v,
[_._] then if h is http_argument(n,v) then n + "=" + v + "&" + format_http_args(t)
}
}.
Formatting the headers.
public define String
format_headers
(
List(HTTP_header) headers
) =
if headers is
{
[ ] then "",
[h . t] then if h is http_header(n,v) then
n + ": " + v + crlf + format_headers(t)
}.
public define String
format
(
DNS_Result r
) =
if r is
{
host_not_found then "host not found",
no_address_found then "no address found for this host",
try_again then "DNS server is busy, try again later",
non_recoverable_error then "non recoverable DNS error",
ok(n) then alert // should never happen
}.
public define String
format
(
NetworkConnectError e
) =
if e is
{
cannot_create_the_socket then "cannot create the socket",
address_port_not_available then "address:port not available",
connection_refused then "connection refused",
network_unreachable then "network is unreachable",
address_port_already_in_use then "address:port already in use",
out_of_time then "out of time"
}.
public define String
format
(
SSLConnectError e
) =
if e is
{
tcp_error(nce) then format(nce),
cannot_create_SSL_object then "cannot create SSL object",
cannot_connect_under_SSL then "cannot connect under SSL",
cannot_trust_server_certificate then "cannot trust server certificate"
}.
The next function empties the standard input (the keybord normally).
define One
empty_stdin
(
One dummy
) =
if *stdin is
{
failure then unique,
success(c) then
if c = 10
then unique
else empty_stdin(dummy)
}.
The next function returns true if the user answers Y or y.
public define Bool
yes
=
if *stdin is
{
failure then alert, // this can never happen, because stdin is never closed
success(c) then
empty_stdin(unique);
(c = 'Y' | c = 'y')
}.
Separating the server name from the port.
public define (String,Int32)
separate_name_port
(
String server_name,
Int32 default_port
) =
if find(":",server_name,0) is
{
failure then (server_name,default_port),
success(n) then
(substr(server_name,0,n),
if string_to_integer(substr(server_name,n+1,length(server_name)-n-1)) is
{
failure then default_port,
success(p) then p
})
}.
Separating the headers. The headers are comming in the form of a unique string. They
should be put in the form of a list of pairs of strings (one list element per header).
We do that in two steps. (1) separate the headers into a list of strings (one per
header), and (2) separate each string into a pair of strings (name,value).
define HTTP_header
separate_header
(
String header,
Int32 i
) =
if nth(i,header) is
{
failure then http_header(header,""),
success(c) then
if c = ':' // separator
then http_header(substr(header,0,i),substr(header,i+1,length(header)-i-1))
else separate_header(header,i+1)
}.
Headers are separated from each other by CRLF not followed by a blank character.
define List(HTTP_header)
separate_headers
(
String headers,
Int32 start,
) =
if find("\r\n",headers,start) is
{
failure then [separate_header(substr(headers,start,length(headers)-start),0)],
success(end) then
[separate_header(substr(headers,start,end-start),0) . separate_headers(headers,end+2)]
}.
public define List(HTTP_header)
separate_headers
(
String headers,
) =
separate_headers(headers,0).
public define One
print_headers
(
List(HTTP_header) headers
) =
if headers is
{
[ ] then unique,
[h . t] then
if h is http_header(l,r) then
print(" "); print(l); print(": "); print(r); print("\n"); print_headers(t)
}.
public define Word8
force_nth
(
Int32 n,
String s
) =
if nth(n,s) is
{
failure then 0,
success(c) then c
}.
public define List(HTTP_header)
get_headers
(
List(String) args
) =
if args is
{
[ ] then [ ],
[h . t] then if nth(0,h) is
{
failure then alert,
success(c) then if c = '='
then if t is
{
[ ] then [http_header(substr(h,1,length(h)-1),"")],
[u . v] then [http_header(substr(h,1,length(h)-1),u) . get_headers(v)]
}
else get_headers(t)
}
}.
public define List(HTTP_argument)
get_arguments
(
List(String) args
) =
if args is
{
[ ] then [ ],
[h . t] then if nth(0,h) is
{
failure then alert,
success(c) then if c = '='
then if t is
{
[ ] then [ ],
[u . v] then get_arguments(v)
}
else if c = '-'
then get_arguments(t)
else if t is
{
[ ] then [http_argument(h,"")],
[u . v] then [http_argument(h,u) . get_arguments(v)]
}
}
}.