diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-25 22:01:37 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-25 22:01:37 +0000 |
commit | bee46b39bf5b29e559b2152e4b32d2f37ee71a8e (patch) | |
tree | 0d05cdff82bcfda622b431819ab6492f7590a152 /src | |
parent | f6b95052256fa9609a8f8a2c8abfe0af1e18706f (diff) | |
download | luasocket-bee46b39bf5b29e559b2152e4b32d2f37ee71a8e.tar.gz luasocket-bee46b39bf5b29e559b2152e4b32d2f37ee71a8e.tar.bz2 luasocket-bee46b39bf5b29e559b2152e4b32d2f37ee71a8e.zip |
HTTP is now generic, with function http_request.
RFC is more strictly followed.
Diffstat (limited to 'src')
-rw-r--r-- | src/http.lua | 425 |
1 files changed, 258 insertions, 167 deletions
diff --git a/src/http.lua b/src/http.lua index 8f08725..7212728 100644 --- a/src/http.lua +++ b/src/http.lua | |||
@@ -1,5 +1,6 @@ | |||
1 | ----------------------------------------------------------------------------- | 1 | ----------------------------------------------------------------------------- |
2 | -- Simple HTTP/1.1 support for the Lua language using the LuaSocket toolkit. | 2 | -- Full HTTP/1.1 client support for the Lua language using the |
3 | -- LuaSocket 1.2 toolkit. | ||
3 | -- Author: Diego Nehab | 4 | -- Author: Diego Nehab |
4 | -- Date: 26/12/2000 | 5 | -- Date: 26/12/2000 |
5 | -- Conforming to: RFC 2068 | 6 | -- Conforming to: RFC 2068 |
@@ -9,165 +10,171 @@ | |||
9 | -- Program constants | 10 | -- Program constants |
10 | ----------------------------------------------------------------------------- | 11 | ----------------------------------------------------------------------------- |
11 | -- connection timeout in seconds | 12 | -- connection timeout in seconds |
12 | local TIMEOUT = 60 | 13 | local TIMEOUT = 60 |
13 | -- default port for document retrieval | 14 | -- default port for document retrieval |
14 | local PORT = 80 | 15 | local PORT = 80 |
15 | -- user agent field sent in request | 16 | -- user agent field sent in request |
16 | local USERAGENT = "LuaSocket/HTTP 1.0" | 17 | local USERAGENT = "LuaSocket 1.2 HTTP 1.1" |
17 | 18 | ||
18 | ----------------------------------------------------------------------------- | 19 | ----------------------------------------------------------------------------- |
19 | -- Tries to get a line from the server or close socket if error | 20 | -- Tries to get a pattern from the server and closes socket on error |
20 | -- sock: socket connected to the server | 21 | -- sock: socket connected to the server |
22 | -- pattern: pattern to receive | ||
21 | -- Returns | 23 | -- Returns |
22 | -- line: line received or nil in case of error | 24 | -- data: line received or nil in case of error |
23 | -- err: error message if any | 25 | -- err: error message if any |
24 | ----------------------------------------------------------------------------- | 26 | ----------------------------------------------------------------------------- |
25 | local try_getline = function(sock) | 27 | local try_get = function(...) |
26 | line, err = sock:receive() | 28 | local sock = arg[1] |
27 | if err then | 29 | local data, err = call(sock.receive, arg) |
28 | sock:close() | 30 | if err then |
29 | return nil, err | 31 | sock:close() |
30 | end | 32 | return nil, err |
31 | return line | 33 | end |
34 | return data | ||
32 | end | 35 | end |
33 | 36 | ||
34 | ----------------------------------------------------------------------------- | 37 | ----------------------------------------------------------------------------- |
35 | -- Tries to send a line to the server or close socket if error | 38 | -- Tries to send data to the server and closes socket on error |
36 | -- sock: socket connected to the server | 39 | -- sock: socket connected to the server |
37 | -- line: line to send | 40 | -- data: data to send |
38 | -- Returns | 41 | -- Returns |
39 | -- err: error message if any | 42 | -- err: error message if any, nil if successfull |
40 | ----------------------------------------------------------------------------- | 43 | ----------------------------------------------------------------------------- |
41 | local try_sendline = function(sock, line) | 44 | local try_send = function(sock, data) |
42 | err = sock:send(line) | 45 | err = sock:send(data) |
43 | if err then sock:close() end | 46 | if err then sock:close() end |
44 | return err | 47 | return err |
45 | end | 48 | end |
46 | 49 | ||
47 | ----------------------------------------------------------------------------- | 50 | ----------------------------------------------------------------------------- |
48 | -- Retrieves status from http reply | 51 | -- Retrieves status code from http status line |
49 | -- Input | 52 | -- Input |
50 | -- reply: http reply string | 53 | -- line: http status line |
51 | -- Returns | 54 | -- Returns |
52 | -- status: integer with status code | 55 | -- code: integer with status code |
53 | ----------------------------------------------------------------------------- | 56 | ----------------------------------------------------------------------------- |
54 | local get_status = function(reply) | 57 | local get_statuscode = function(line) |
55 | local _,_, status = strfind(reply, " (%d%d%d) ") | 58 | local _,_, code = strfind(line, " (%d%d%d) ") |
56 | return tonumber(status) | 59 | return tonumber(code) |
57 | end | 60 | end |
58 | 61 | ||
59 | ----------------------------------------------------------------------------- | 62 | ----------------------------------------------------------------------------- |
60 | -- Receive server reply messages | 63 | -- Receive server reply messages |
61 | -- Input | 64 | -- Input |
62 | -- sock: server socket | 65 | -- sock: socket connected to the server |
63 | -- Returns | 66 | -- Returns |
64 | -- status: server reply status code or nil if error | 67 | -- code: server status code or nil if error |
65 | -- reply: full server reply | 68 | -- line: full http status line |
66 | -- err: error message if any | 69 | -- err: error message if any |
67 | ----------------------------------------------------------------------------- | 70 | ----------------------------------------------------------------------------- |
68 | local get_reply = function(sock) | 71 | local get_status = function(sock) |
69 | local reply, err | 72 | local line, err |
70 | reply, err = %try_getline(sock) | 73 | line, err = %try_get(sock) |
71 | if not err then return %get_status(reply), reply | 74 | if not err then return %get_statuscode(line), line |
72 | else return nil, nil, err end | 75 | else return nil, nil, err end |
73 | end | 76 | end |
74 | 77 | ||
75 | ----------------------------------------------------------------------------- | 78 | ----------------------------------------------------------------------------- |
76 | -- Receive and parse mime headers | 79 | -- Receive and parse responce header fields |
77 | -- Input | 80 | -- Input |
78 | -- sock: server socket | 81 | -- sock: socket connected to the server |
79 | -- mime: a table that might already contain mime headers | 82 | -- headers: a table that might already contain headers |
80 | -- Returns | 83 | -- Returns |
81 | -- mime: a table with all mime headers in the form | 84 | -- headers: a table with all headers fields in the form |
82 | -- {name_1 = "value_1", name_2 = "value_2" ... name_n = "value_n"} | 85 | -- {name_1 = "value_1", name_2 = "value_2" ... name_n = "value_n"} |
83 | -- all name_i are lowercase | 86 | -- all name_i are lowercase |
84 | -- nil and error message in case of error | 87 | -- nil and error message in case of error |
85 | ----------------------------------------------------------------------------- | 88 | ----------------------------------------------------------------------------- |
86 | local get_mime = function(sock, mime) | 89 | local get_headers = function(sock, headers) |
87 | local line, err | 90 | local line, err |
88 | local name, value | 91 | local name, value |
89 | -- get first line | 92 | -- get first line |
90 | line, err = %try_getline(sock) | 93 | line, err = %try_get(sock) |
91 | if err then return nil, err end | 94 | if err then return nil, err end |
92 | -- headers go until a blank line is found | 95 | -- headers go until a blank line is found |
93 | while line ~= "" do | 96 | while line ~= "" do |
94 | -- get field-name and value | 97 | -- get field-name and value |
95 | _,_, name, value = strfind(line, "(.-):%s*(.*)") | 98 | _,_, name, value = strfind(line, "(.-):%s*(.*)") |
99 | if not name or not value then | ||
100 | sock:close() | ||
101 | return nil, "malformed reponse headers" | ||
102 | end | ||
96 | name = strlower(name) | 103 | name = strlower(name) |
97 | -- get next line (value might be folded) | 104 | -- get next line (value might be folded) |
98 | line, err = %try_getline(sock) | 105 | line, err = %try_get(sock) |
99 | if err then return nil, err end | 106 | if err then return nil, err end |
100 | -- unfold any folded values | 107 | -- unfold any folded values |
101 | while not err and line ~= "" and (strsub(line, 1, 1) == " ") do | 108 | while not err and strfind(line, "^%s") do |
102 | value = value .. line | 109 | value = value .. line |
103 | line, err = %try_getline(sock) | 110 | line, err = %try_get(sock) |
104 | if err then return nil, err end | 111 | if err then return nil, err end |
105 | end | 112 | end |
106 | -- save pair in table | 113 | -- save pair in table |
107 | if mime[name] then | 114 | if headers[name] then headers[name] = headers[name] .. ", " .. value |
108 | -- join any multiple field | 115 | else headers[name] = value end |
109 | mime[name] = mime[name] .. ", " .. value | ||
110 | else | ||
111 | -- new field | ||
112 | mime[name] = value | ||
113 | end | ||
114 | end | 116 | end |
115 | return mime | 117 | return headers |
118 | end | ||
119 | |||
120 | ----------------------------------------------------------------------------- | ||
121 | -- Receives a chunked message body | ||
122 | -- Input | ||
123 | -- sock: socket connected to the server | ||
124 | -- Returns | ||
125 | -- body: a string containing the body of the message | ||
126 | -- nil and error message in case of error | ||
127 | ----------------------------------------------------------------------------- | ||
128 | local try_getchunked = function(sock) | ||
129 | local chunk_size, line, err | ||
130 | local body = "" | ||
131 | repeat | ||
132 | -- get chunk size, skip extention | ||
133 | line, err = %try_get(sock) | ||
134 | if err then return nil, err end | ||
135 | chunk_size = tonumber(gsub(line, ";.*", ""), 16) | ||
136 | if not chunk_size then | ||
137 | sock:close() | ||
138 | return nil, "invalid chunk size" | ||
139 | end | ||
140 | -- get chunk | ||
141 | line, err = %try_get(sock, chunk_size) | ||
142 | if err then return nil, err end | ||
143 | -- concatenate new chunk | ||
144 | body = body .. line | ||
145 | -- skip blank line | ||
146 | _, err = %try_get(sock) | ||
147 | if err then return nil, err end | ||
148 | until chunk_size <= 0 | ||
149 | return body | ||
116 | end | 150 | end |
117 | 151 | ||
118 | ----------------------------------------------------------------------------- | 152 | ----------------------------------------------------------------------------- |
119 | -- Receives http body | 153 | -- Receives http body |
120 | -- Input | 154 | -- Input |
121 | -- sock: server socket | 155 | -- sock: socket connected to the server |
122 | -- mime: initial mime headers | 156 | -- headers: response header fields |
123 | -- Returns | 157 | -- Returns |
124 | -- body: a string containing the body of the document | 158 | -- body: a string containing the body of the document |
125 | -- nil and error message in case of error | 159 | -- nil and error message in case of error |
126 | -- Obs: | 160 | -- Obs: |
127 | -- mime: headers might be modified by chunked transfer | 161 | -- headers: headers might be modified by chunked transfer |
128 | ----------------------------------------------------------------------------- | 162 | ----------------------------------------------------------------------------- |
129 | local get_body = function(sock, mime) | 163 | local get_body = function(sock, headers) |
130 | local body, err | 164 | local body, err |
131 | if mime["transfer-encoding"] == "chunked" then | 165 | if headers["transfer-encoding"] == "chunked" then |
132 | local chunk_size, line | 166 | body, err = %try_getchunked(sock) |
133 | body = "" | 167 | if err then return nil, err end |
134 | repeat | 168 | -- store extra entity headers |
135 | -- get chunk size, skip extention | 169 | --_, err = %get_headers(sock, headers) |
136 | line, err = %try_getline(sock) | 170 | --if err then return nil, err end |
137 | if err then return nil, err end | 171 | elseif headers["content-length"] then |
138 | chunk_size = tonumber(gsub(line, ";.*", ""), 16) | 172 | body, err = %try_get(sock, tonumber(headers["content-length"])) |
139 | if not chunk_size then | 173 | if err then return nil, err end |
140 | sock:close() | ||
141 | return nil, "invalid chunk size" | ||
142 | end | ||
143 | -- get chunk | ||
144 | line, err = sock:receive(chunk_size) | ||
145 | if err then | ||
146 | sock:close() | ||
147 | return nil, err | ||
148 | end | ||
149 | -- concatenate new chunk | ||
150 | body = body .. line | ||
151 | -- skip blank line | ||
152 | _, err = %try_getline(sock) | ||
153 | if err then return nil, err end | ||
154 | until chunk_size <= 0 | ||
155 | -- store extra mime headers | ||
156 | --_, err = %get_mime(sock, mime) | ||
157 | --if err then return nil, err end | ||
158 | elseif mime["content-length"] then | ||
159 | body, err = sock:receive(tonumber(mime["content-length"])) | ||
160 | if err then | ||
161 | sock:close() | ||
162 | return nil, err | ||
163 | end | ||
164 | else | 174 | else |
165 | -- get it all until connection closes! | 175 | -- get it all until connection closes! |
166 | body, err = sock:receive("*a") | 176 | body, err = %try_get(sock, "*a") |
167 | if err then | 177 | if err then return nil, err end |
168 | sock:close() | ||
169 | return nil, err | ||
170 | end | ||
171 | end | 178 | end |
172 | -- return whole body | 179 | -- return whole body |
173 | return body | 180 | return body |
@@ -175,10 +182,9 @@ end | |||
175 | 182 | ||
176 | ----------------------------------------------------------------------------- | 183 | ----------------------------------------------------------------------------- |
177 | -- Parses a url and returns its scheme, user, password, host, port | 184 | -- Parses a url and returns its scheme, user, password, host, port |
178 | -- and path components, according to RFC 1738, Uniform Resource Locators (URL), | 185 | -- and path components, according to RFC 1738 |
179 | -- of December 1994 | ||
180 | -- Input | 186 | -- Input |
181 | -- url: unique resource locator desired | 187 | -- url: uniform resource locator of request |
182 | -- default: table containing default values to be returned | 188 | -- default: table containing default values to be returned |
183 | -- Returns | 189 | -- Returns |
184 | -- table with the following fields: | 190 | -- table with the following fields: |
@@ -213,47 +219,99 @@ local split_url = function(url, default) | |||
213 | end | 219 | end |
214 | 220 | ||
215 | ----------------------------------------------------------------------------- | 221 | ----------------------------------------------------------------------------- |
216 | -- Sends a GET message through socket | 222 | -- Tries to send request body, using chunked transfer-encoding |
223 | -- Apache, for instance, accepts only 8kb of body in a post to a CGI script | ||
224 | -- if we use only the content-length header field... | ||
217 | -- Input | 225 | -- Input |
218 | -- socket: http connection socket | 226 | -- sock: socket connected to the server |
219 | -- path: path requested | 227 | -- body: body to be sent in request |
220 | -- mime: mime headers to send in request | ||
221 | -- Returns | 228 | -- Returns |
222 | -- err: nil in case of success, error message otherwise | 229 | -- err: nil in case of success, error message otherwise |
223 | ----------------------------------------------------------------------------- | 230 | ----------------------------------------------------------------------------- |
224 | local send_get = function(sock, path, mime) | 231 | local try_sendchunked = function(sock, body) |
225 | local err = %try_sendline(sock, "GET " .. path .. " HTTP/1.1\r\n") | 232 | local wanted = strlen(body) |
226 | if err then return err end | 233 | local first = 1 |
227 | for i, v in mime do | 234 | local chunk_size |
228 | err = %try_sendline(sock, i .. ": " .. v .. "\r\n") | 235 | local err |
229 | if err then return err end | 236 | while wanted > 0 do |
230 | end | 237 | chunk_size = min(wanted, 1024) |
231 | err = %try_sendline(sock, "\r\n") | 238 | err = %try_send(sock, format("%x\r\n", chunk_size)) |
232 | return err | 239 | if err then return err end |
240 | err = %try_send(sock, strsub(body, first, first + chunk_size - 1)) | ||
241 | if err then return err end | ||
242 | err = %try_send(sock, "\r\n") | ||
243 | if err then return err end | ||
244 | wanted = wanted - chunk_size | ||
245 | first = first + chunk_size | ||
246 | end | ||
247 | err = %try_send(sock, "0\r\n") | ||
248 | return err | ||
249 | end | ||
250 | |||
251 | ----------------------------------------------------------------------------- | ||
252 | -- Sends a http request message through socket | ||
253 | -- Input | ||
254 | -- sock: socket connected to the server | ||
255 | -- method: request method to be used | ||
256 | -- path: url path | ||
257 | -- headers: request headers to be sent | ||
258 | -- body: request message body, if any | ||
259 | -- Returns | ||
260 | -- err: nil in case of success, error message otherwise | ||
261 | ----------------------------------------------------------------------------- | ||
262 | local send_request = function(sock, method, path, headers, body) | ||
263 | local err = %try_send(sock, method .. " " .. path .. " HTTP/1.1\r\n") | ||
264 | if err then return err end | ||
265 | for i, v in headers do | ||
266 | err = %try_send(sock, i .. ": " .. v .. "\r\n") | ||
267 | if err then return err end | ||
268 | end | ||
269 | err = %try_send(sock, "\r\n") | ||
270 | --if not err and body then err = %try_sendchunked(sock, body) end | ||
271 | if not err and body then err = %try_send(sock, body) end | ||
272 | return err | ||
273 | end | ||
274 | |||
275 | ----------------------------------------------------------------------------- | ||
276 | -- Determines if we should read a message body from the server response | ||
277 | -- Input | ||
278 | -- method: method used in request | ||
279 | -- code: server response status code | ||
280 | -- Returns | ||
281 | -- 1 if a message body should be processed, nil otherwise | ||
282 | ----------------------------------------------------------------------------- | ||
283 | function has_responsebody(method, code) | ||
284 | if method == "HEAD" then return nil end | ||
285 | if code == 204 or code == 304 then return nil end | ||
286 | if code >= 100 and code < 200 then return nil end | ||
287 | return 1 | ||
233 | end | 288 | end |
234 | 289 | ||
235 | ----------------------------------------------------------------------------- | 290 | ----------------------------------------------------------------------------- |
236 | -- Converts field names to lowercase | 291 | -- Converts field names to lowercase and add message body size specification |
237 | -- Input | 292 | -- Input |
238 | -- headers: user header fields | 293 | -- headers: request header fields |
239 | -- parsed: parsed url components | 294 | -- parsed: parsed url components |
295 | -- body: request message body, if any | ||
240 | -- Returns | 296 | -- Returns |
241 | -- mime: a table with the same headers, but with lowercase field names | 297 | -- lower: a table with the same headers, but with lowercase field names |
242 | ----------------------------------------------------------------------------- | 298 | ----------------------------------------------------------------------------- |
243 | local fill_headers = function(headers, parsed) | 299 | local fill_headers = function(headers, parsed, body) |
244 | local mime = {} | 300 | local lower = {} |
245 | headers = headers or {} | 301 | headers = headers or {} |
246 | for i,v in headers do | 302 | for i,v in headers do |
247 | mime[strlower(i)] = v | 303 | lower[strlower(i)] = v |
248 | end | 304 | end |
249 | mime["connection"] = "close" | 305 | --if body then lower["transfer-encoding"] = "chunked" end |
250 | mime["host"] = parsed.host | 306 | if body then lower["content-length"] = tostring(strlen(body)) end |
251 | mime["user-agent"] = %USERAGENT | 307 | lower["connection"] = "close" |
252 | if parsed.user and parsed.pass then -- Basic Authentication | 308 | lower["host"] = parsed.host |
253 | mime["authorization"] = "Basic ".. | 309 | lower["user-agent"] = %USERAGENT |
254 | base64(parsed.user .. ":" .. parsed.pass) | 310 | if parsed.user and parsed.pass then -- Basic Authentication |
255 | end | 311 | lower["authorization"] = "Basic ".. |
256 | return mime | 312 | base64(parsed.user .. ":" .. parsed.pass) |
313 | end | ||
314 | return lower | ||
257 | end | 315 | end |
258 | 316 | ||
259 | ----------------------------------------------------------------------------- | 317 | ----------------------------------------------------------------------------- |
@@ -262,51 +320,84 @@ end | |||
262 | dofile("base64.lua") | 320 | dofile("base64.lua") |
263 | 321 | ||
264 | ----------------------------------------------------------------------------- | 322 | ----------------------------------------------------------------------------- |
265 | -- Downloads and receives a http url, with its mime headers | 323 | -- Sends a HTTP request and retrieves the server reply |
266 | -- Input | 324 | -- Input |
267 | -- url: unique resource locator desired | 325 | -- method: "GET", "PUT", "POST" etc |
268 | -- headers: headers to send with request | 326 | -- url: target uniform resource locator |
269 | -- tried: is this an authentication retry? | 327 | -- headers: request headers to send |
328 | -- body: request message body | ||
270 | -- Returns | 329 | -- Returns |
271 | -- body: document body, if successfull | 330 | -- resp_body: response message body, if successfull |
272 | -- mime: headers received with document, if sucessfull | 331 | -- resp_hdrs: response header fields received, if sucessfull |
273 | -- reply: server reply, if successfull | 332 | -- line: server response status line, if successfull |
274 | -- err: error message, if any | 333 | -- err: error message if any |
275 | ----------------------------------------------------------------------------- | 334 | ----------------------------------------------------------------------------- |
276 | function http_get(url, headers) | 335 | function http_request(method, url, headers, body) |
277 | local sock, err, mime, body, status, reply | 336 | local sock, err |
337 | local resp_hdrs, response_body | ||
338 | local line, code | ||
278 | -- get url components | 339 | -- get url components |
279 | local parsed = %split_url(url, {port = %PORT, path ="/"}) | 340 | local parsed = %split_url(url, {port = %PORT, path ="/"}) |
280 | -- fill default headers | 341 | -- methods are case sensitive |
281 | headers = %fill_headers(headers, parsed) | 342 | method = strupper(method) |
282 | -- try connection | 343 | -- fill default headers |
344 | headers = %fill_headers(headers, parsed, body) | ||
345 | -- try connection | ||
283 | sock, err = connect(parsed.host, parsed.port) | 346 | sock, err = connect(parsed.host, parsed.port) |
284 | if not sock then return nil, nil, nil, err end | 347 | if not sock then return nil, nil, nil, err end |
285 | -- set connection timeout | 348 | -- set connection timeout |
286 | sock:timeout(%TIMEOUT) | 349 | sock:timeout(%TIMEOUT) |
287 | -- send request | 350 | -- send request |
288 | err = %send_get(sock, parsed.path, headers) | 351 | err = %send_request(sock, method, parsed.path, headers, body) |
289 | if err then return nil, nil, nil, err end | 352 | if err then return nil, nil, nil, err end |
290 | -- get server message | 353 | -- get server message |
291 | status, reply, err = %get_reply(sock) | 354 | code, line, err = %get_status(sock) |
292 | if err then return nil, nil, nil, err end | 355 | if err then return nil, nil, nil, err end |
293 | -- get url accordingly | 356 | -- deal with reply |
294 | if status == 200 then -- ok, go on and get it | 357 | resp_hdrs, err = %get_headers(sock, {}) |
295 | mime, err = %get_mime(sock, {}) | 358 | if err then return nil, nil, line, err end |
296 | if err then return nil, nil, reply, err end | 359 | -- get body if status and method allow one |
297 | body, err = %get_body(sock, mime) | 360 | if has_responsebody(method, code) then |
298 | if err then return nil, mime, reply, err end | 361 | resp_body, err = %get_body(sock, resp_hdrs) |
299 | sock:close() | 362 | if err then return nil, resp_hdrs, line, err end |
300 | return body, mime, reply | 363 | end |
301 | elseif status == 301 then -- moved permanently, try again | 364 | sock:close() |
302 | mime = %get_mime(sock, {}) | 365 | -- should we automatically retry? |
303 | sock:close() | 366 | if (code == 301 or code == 302) then |
304 | if mime["location"] then return http_get(mime["location"], headers) | 367 | if (method == "GET" or method == "HEAD") and resp_hdrs["location"] then |
305 | else return nil, mime, reply end | 368 | return http_request(method, resp_hdrs["location"], headers, body) |
306 | elseif status == 401 then | 369 | else return nil, resp_hdrs, line end |
307 | mime, err = %get_mime(sock, {}) | 370 | end |
308 | if err then return nil, nil, reply, err end | 371 | return resp_body, resp_hdrs, line |
309 | return nil, mime, reply | 372 | end |
310 | end | 373 | |
311 | return nil, nil, reply | 374 | ----------------------------------------------------------------------------- |
375 | -- Retrieves a URL by the method "GET" | ||
376 | -- Input | ||
377 | -- url: target uniform resource locator | ||
378 | -- headers: request headers to send | ||
379 | -- Returns | ||
380 | -- body: response message body, if successfull | ||
381 | -- headers: response header fields, if sucessfull | ||
382 | -- line: response status line, if successfull | ||
383 | -- err: error message, if any | ||
384 | ----------------------------------------------------------------------------- | ||
385 | function http_get(url, headers) | ||
386 | return http_request("GET", url, headers) | ||
387 | end | ||
388 | |||
389 | ----------------------------------------------------------------------------- | ||
390 | -- Retrieves a URL by the method "GET" | ||
391 | -- Input | ||
392 | -- url: target uniform resource locator | ||
393 | -- body: request message body | ||
394 | -- headers: request headers to send | ||
395 | -- Returns | ||
396 | -- body: response message body, if successfull | ||
397 | -- headers: response header fields, if sucessfull | ||
398 | -- line: response status line, if successfull | ||
399 | -- err: error message, if any | ||
400 | ----------------------------------------------------------------------------- | ||
401 | function http_post(url, body, headers) | ||
402 | return http_request("POST", url, headers, body) | ||
312 | end | 403 | end |