aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-19 00:24:41 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-19 00:24:41 +0000
commit6ac82d50eecdf9bf55f4234ed3a5449afd7a2992 (patch)
tree8cd27e814359d60543428a89b104a8528d0e6bf2
parent3ea92711269153916990d6cd7999bf436775e647 (diff)
downloadluasocket-6ac82d50eecdf9bf55f4234ed3a5449afd7a2992.tar.gz
luasocket-6ac82d50eecdf9bf55f4234ed3a5449afd7a2992.tar.bz2
luasocket-6ac82d50eecdf9bf55f4234ed3a5449afd7a2992.zip
Added proxy support to http.lua
Changed callback.lua module, but need more work. Added local connect support.
-rw-r--r--TODO7
-rw-r--r--src/http.lua58
-rw-r--r--src/tcp.c6
-rw-r--r--test/httptest.lua121
4 files changed, 125 insertions, 67 deletions
diff --git a/TODO b/TODO
index 91b8830..ab88dbd 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,10 @@
1add callback module to manual
2change stay to redirect in http.lua and in manual
3add timeout to request table
4
5change code to mime
6change *all* modules to be namespace independent
7
1write some utilities that use the code.lua module and put them 8write some utilities that use the code.lua module and put them
2in etc, modify the README.etc file and makefile.dist (eol.lua is done) 9in etc, modify the README.etc file and makefile.dist (eol.lua is done)
3 10
diff --git a/src/http.lua b/src/http.lua
index f51da25..fb13d99 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -40,6 +40,7 @@ BLOCKSIZE = 8192
40local function try_receiving(sock, pattern) 40local function try_receiving(sock, pattern)
41 local data, err = sock:receive(pattern) 41 local data, err = sock:receive(pattern)
42 if not data then sock:close() end 42 if not data then sock:close() end
43--print(data)
43 return data, err 44 return data, err
44end 45end
45 46
@@ -53,6 +54,7 @@ end
53local function try_sending(sock, ...) 54local function try_sending(sock, ...)
54 local sent, err = sock:send(unpack(arg)) 55 local sent, err = sock:send(unpack(arg))
55 if not sent then sock:close() end 56 if not sent then sock:close() end
57--io.write(unpack(arg))
56 return err 58 return err
57end 59end
58 60
@@ -425,7 +427,10 @@ local function authorize(reqt, parsed, respt)
425 method = reqt.method, 427 method = reqt.method,
426 url = reqt.url, 428 url = reqt.url,
427 body_cb = reqt.body_cb, 429 body_cb = reqt.body_cb,
428 headers = reqt.headers 430 headers = reqt.headers,
431 timeout = reqt.timeout,
432 host = reqt.host,
433 port = reqt.port
429 } 434 }
430 return request_cb(autht, respt) 435 return request_cb(autht, respt)
431end 436end
@@ -439,11 +444,10 @@ end
439-- 1 if we should redirect, nil otherwise 444-- 1 if we should redirect, nil otherwise
440----------------------------------------------------------------------------- 445-----------------------------------------------------------------------------
441local function should_redirect(reqt, respt) 446local function should_redirect(reqt, respt)
442 local follow = not reqt.stay 447 return (reqt.redirect ~= false) and
443 follow = follow and (respt.code == 301 or respt.code == 302) 448 (respt.code == 301 or respt.code == 302) and
444 follow = follow and (reqt.method == "GET" or reqt.method == "HEAD") 449 (reqt.method == "GET" or reqt.method == "HEAD") and
445 follow = follow and not (reqt.nredirects and reqt.nredirects >= 5) 450 not (reqt.nredirects and reqt.nredirects >= 5)
446 return follow
447end 451end
448 452
449----------------------------------------------------------------------------- 453-----------------------------------------------------------------------------
@@ -465,7 +469,10 @@ local function redirect(reqt, respt)
465 -- servers do not respect that 469 -- servers do not respect that
466 url = socket.url.absolute(reqt.url, respt.headers["location"]), 470 url = socket.url.absolute(reqt.url, respt.headers["location"]),
467 body_cb = reqt.body_cb, 471 body_cb = reqt.body_cb,
468 headers = reqt.headers 472 headers = reqt.headers,
473 timeout = reqt.timeout,
474 host = reqt.host,
475 port = reqt.port
469 } 476 }
470 respt = request_cb(redirt, respt) 477 respt = request_cb(redirt, respt)
471 -- we pass the location header as a clue we tried to redirect 478 -- we pass the location header as a clue we tried to redirect
@@ -475,18 +482,24 @@ end
475 482
476----------------------------------------------------------------------------- 483-----------------------------------------------------------------------------
477-- Computes the request URI from the parsed request URL 484-- Computes the request URI from the parsed request URL
485-- If host and port are given in the request table, we use he
486-- absoluteURI format. Otherwise, we use the abs_path format.
478-- Input 487-- Input
479-- parsed: parsed URL 488-- parsed: parsed URL
480-- Returns 489-- Returns
481-- uri: request URI for parsed URL 490-- uri: request URI for parsed URL
482----------------------------------------------------------------------------- 491-----------------------------------------------------------------------------
483local function request_uri(parsed) 492local function request_uri(reqt, parsed)
484 local uri = "" 493 local url
485 if parsed.path then uri = uri .. parsed.path end 494 if not reqt.host and not reqt.port then
486 if parsed.params then uri = uri .. ";" .. parsed.params end 495 url = {
487 if parsed.query then uri = uri .. "?" .. parsed.query end 496 path = parsed.path,
488 if parsed.fragment then uri = uri .. "#" .. parsed.fragment end 497 params = parsed.params,
489 return uri 498 query = parsed.query,
499 fragment = parsed.fragment
500 }
501 else url = parsed end
502 return socket.url.build(url)
490end 503end
491 504
492----------------------------------------------------------------------------- 505-----------------------------------------------------------------------------
@@ -519,7 +532,7 @@ end
519-- user, password: authentication information 532-- user, password: authentication information
520-- headers: request headers to send, or nil if none 533-- headers: request headers to send, or nil if none
521-- body_cb: request message body send-callback, or nil if none 534-- body_cb: request message body send-callback, or nil if none
522-- stay: should we refrain from following a server redirect message? 535-- redirect: should we refrain from following a server redirect message?
523-- respt: a table with the following fields: 536-- respt: a table with the following fields:
524-- body_cb: response method body receive-callback 537-- body_cb: response method body receive-callback
525-- Returns 538-- Returns
@@ -552,16 +565,17 @@ function request_cb(reqt, respt)
552 sock, respt.error = socket.tcp() 565 sock, respt.error = socket.tcp()
553 if not sock then return respt end 566 if not sock then return respt end
554 -- set connection timeout so that we do not hang forever 567 -- set connection timeout so that we do not hang forever
555 sock:settimeout(TIMEOUT) 568 sock:settimeout(reqt.timeout or TIMEOUT)
556 local ret 569 local ret
557 ret, respt.error = sock:connect(parsed.host, parsed.port) 570 ret, respt.error = sock:connect(reqt.host or parsed.host,
571 reqt.port or parsed.port)
558 if not ret then 572 if not ret then
559 sock:close() 573 sock:close()
560 return respt 574 return respt
561 end 575 end
562 -- send request message 576 -- send request message
563 respt.error = send_request(sock, reqt.method, 577 respt.error = send_request(sock, reqt.method,
564 request_uri(parsed), reqt.headers, reqt.body_cb) 578 request_uri(reqt, parsed), reqt.headers, reqt.body_cb)
565 if respt.error then 579 if respt.error then
566 sock:close() 580 sock:close()
567 return respt 581 return respt
@@ -570,7 +584,7 @@ function request_cb(reqt, respt)
570 respt.code, respt.status, respt.error = receive_status(sock) 584 respt.code, respt.status, respt.error = receive_status(sock)
571 if respt.error then return respt end 585 if respt.error then return respt end
572 -- deal with continue 100 586 -- deal with continue 100
573 -- servers should not send them, but they might 587 -- servers should not send them, but some do!
574 if respt.code == 100 then 588 if respt.code == 100 then
575 respt.headers, respt.error = receive_headers(sock, {}) 589 respt.headers, respt.error = receive_headers(sock, {})
576 if respt.error then return respt end 590 if respt.error then return respt end
@@ -612,7 +626,7 @@ end
612-- user, password: authentication information 626-- user, password: authentication information
613-- headers: request header fields, or nil if none 627-- headers: request header fields, or nil if none
614-- body: request message body as a string, or nil if none 628-- body: request message body as a string, or nil if none
615-- stay: should we refrain from following a server redirect message? 629-- redirect: should we refrain from following a server redirect message?
616-- Returns 630-- Returns
617-- respt: a table with the following fields: 631-- respt: a table with the following fields:
618-- body: response message body, or nil if failed 632-- body: response message body, or nil if failed
@@ -623,9 +637,9 @@ end
623----------------------------------------------------------------------------- 637-----------------------------------------------------------------------------
624function request(reqt) 638function request(reqt)
625 local respt = {} 639 local respt = {}
626 reqt.body_cb = socket.callback.send_string(reqt.body) 640 reqt.body_cb = socket.callback.send.string(reqt.body)
627 local concat = socket.concat.create() 641 local concat = socket.concat.create()
628 respt.body_cb = socket.callback.receive_concat(concat) 642 respt.body_cb = socket.callback.receive.concat(concat)
629 respt = request_cb(reqt, respt) 643 respt = request_cb(reqt, respt)
630 respt.body = concat:getresult() 644 respt.body = concat:getresult()
631 respt.body_cb = nil 645 respt.body_cb = nil
diff --git a/src/tcp.c b/src/tcp.c
index 34dd71c..ce2ae17 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -230,15 +230,15 @@ static int meth_bind(lua_State *L)
230 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 230 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
231 const char *address = luaL_checkstring(L, 2); 231 const char *address = luaL_checkstring(L, 2);
232 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 232 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
233 int backlog = (int) luaL_optnumber(L, 4, 0); 233 int backlog = (int) luaL_optnumber(L, 4, 1);
234 const char *err = inet_trybind(&tcp->sock, address, port, backlog); 234 const char *err = inet_trybind(&tcp->sock, address, port, backlog);
235 if (err) { 235 if (err) {
236 lua_pushnil(L); 236 lua_pushnil(L);
237 lua_pushstring(L, err); 237 lua_pushstring(L, err);
238 return 2; 238 return 2;
239 } 239 }
240 /* turn master object into a server object */ 240 /* turn master object into a server object if there was a listen */
241 aux_setclass(L, "tcp{server}", 1); 241 if (backlog > 0) aux_setclass(L, "tcp{server}", 1);
242 lua_pushnumber(L, 1); 242 lua_pushnumber(L, 1);
243 return 1; 243 return 1;
244} 244}
diff --git a/test/httptest.lua b/test/httptest.lua
index 96c9378..3d0db87 100644
--- a/test/httptest.lua
+++ b/test/httptest.lua
@@ -3,6 +3,29 @@
3-- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi 3-- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi
4-- to "/luasocket-test-cgi" and "/luasocket-test-cgi/" 4-- to "/luasocket-test-cgi" and "/luasocket-test-cgi/"
5-- needs "AllowOverride AuthConfig" on /home/c/diego/tec/luasocket/test/auth 5-- needs "AllowOverride AuthConfig" on /home/c/diego/tec/luasocket/test/auth
6dofile("noglobals.lua")
7
8local host, proxyh, proxyp, request, response
9local ignore, expect, index, prefix, cgiprefix
10
11local t = socket.time()
12
13host = host or "diego.princeton.edu"
14proxyh = proxyh or "localhost"
15proxyp = proxyp or 3128
16prefix = prefix or "/luasocket-test"
17cgiprefix = cgiprefix or "/luasocket-test-cgi"
18
19local readfile = function(name)
20 local f = io.open(name, "r")
21 if not f then return nil end
22 local s = f:read("*a")
23 f:close()
24 return s
25end
26
27index = readfile("test/index.html")
28
6local similar = function(s1, s2) 29local similar = function(s1, s2)
7 return string.lower(string.gsub(s1 or "", "%s", "")) == 30 return string.lower(string.gsub(s1 or "", "%s", "")) ==
8 string.lower(string.gsub(s2 or "", "%s", "")) 31 string.lower(string.gsub(s2 or "", "%s", ""))
@@ -14,14 +37,6 @@ local fail = function(s)
14 os.exit() 37 os.exit()
15end 38end
16 39
17local readfile = function(name)
18 local f = io.open(name, "r")
19 if not f then return nil end
20 local s = f:read("*a")
21 f:close()
22 return s
23end
24
25local check = function (v, e) 40local check = function (v, e)
26 if v then print("ok") 41 if v then print("ok")
27 else fail(e) end 42 else fail(e) end
@@ -48,23 +63,12 @@ local check_request = function(request, expect, ignore)
48 print("ok") 63 print("ok")
49end 64end
50 65
51local host, request, response, ignore, expect, index, prefix, cgiprefix
52
53local t = socket.time()
54
55host = host or "localhost"
56prefix = prefix or "/luasocket-test"
57cgiprefix = cgiprefix or "/luasocket-test-cgi"
58index = readfile("test/index.html")
59
60io.write("testing request uri correctness: ") 66io.write("testing request uri correctness: ")
61local forth = cgiprefix .. "/request-uri?" .. "this+is+the+query+string" 67local forth = cgiprefix .. "/request-uri?" .. "this+is+the+query+string"
62local back, h, c, e = socket.http.get("http://" .. host .. forth) 68local back, h, c, e = socket.http.get("http://" .. host .. forth)
63if similar(back, forth) then print("ok") 69back = socket.url.parse(back)
64else 70if similar(back.query, "this+is+the+query+string") then print("ok")
65print(h, c, e) 71else fail() end
66fail()
67end
68 72
69io.write("testing query string correctness: ") 73io.write("testing query string correctness: ")
70forth = "this+is+the+query+string" 74forth = "this+is+the+query+string"
@@ -86,7 +90,19 @@ ignore = {
86} 90}
87check_request(request, expect, ignore) 91check_request(request, expect, ignore)
88 92
89socket.http.get("http://" .. host .. prefix .. "/lixo.html") 93io.write("testing redirect loop: ")
94request = {
95 url = "http://" .. host .. cgiprefix .. "/redirect-loop"
96}
97expect = {
98 code = 302
99}
100ignore = {
101 status = 1,
102 headers = 1,
103 body = 1
104}
105check_request(request, expect, ignore)
90 106
91io.write("testing post method: ") 107io.write("testing post method: ")
92-- wanted to test chunked post, but apache doesn't support it... 108-- wanted to test chunked post, but apache doesn't support it...
@@ -107,16 +123,35 @@ ignore = {
107} 123}
108check_request(request, expect, ignore) 124check_request(request, expect, ignore)
109 125
126io.write("testing proxy with post method: ")
127request = {
128 url = "http://" .. host .. cgiprefix .. "/cat",
129 method = "POST",
130 body = index,
131 headers = { ["content-length"] = string.len(index) },
132 port = proxyp,
133 host = proxyh
134}
135expect = {
136 body = index,
137 code = 200
138}
139ignore = {
140 status = 1,
141 headers = 1
142}
143check_request(request, expect, ignore)
144
110io.write("testing simple post function: ") 145io.write("testing simple post function: ")
111body = socket.http.post("http://" .. host .. cgiprefix .. "/cat", index) 146back = socket.http.post("http://" .. host .. cgiprefix .. "/cat", index)
112check(body == index) 147check(back == index)
113 148
114io.write("testing simple post function with table args: ") 149io.write("testing simple post function with table args: ")
115body = socket.http.post { 150back = socket.http.post {
116 url = "http://" .. host .. cgiprefix .. "/cat", 151 url = "http://" .. host .. cgiprefix .. "/cat",
117 body = index 152 body = index
118} 153}
119check(body == index) 154check(back == index)
120 155
121io.write("testing http redirection: ") 156io.write("testing http redirection: ")
122request = { 157request = {
@@ -132,6 +167,22 @@ ignore = {
132} 167}
133check_request(request, expect, ignore) 168check_request(request, expect, ignore)
134 169
170io.write("testing proxy with redirection: ")
171request = {
172 url = "http://" .. host .. prefix,
173 host = proxyh,
174 port = proxyp
175}
176expect = {
177 body = index,
178 code = 200
179}
180ignore = {
181 status = 1,
182 headers = 1
183}
184check_request(request, expect, ignore)
185
135 186
136io.write("testing automatic auth failure: ") 187io.write("testing automatic auth failure: ")
137request = { 188request = {
@@ -150,7 +201,7 @@ check_request(request, expect, ignore)
150io.write("testing http redirection failure: ") 201io.write("testing http redirection failure: ")
151request = { 202request = {
152 url = "http://" .. host .. prefix, 203 url = "http://" .. host .. prefix,
153 stay = 1 204 redirect = false
154} 205}
155expect = { 206expect = {
156 code = 301 207 code = 301
@@ -273,20 +324,6 @@ ignore = {
273} 324}
274check_request(request, expect, ignore) 325check_request(request, expect, ignore)
275 326
276io.write("testing redirect loop: ")
277request = {
278 url = "http://" .. host .. cgiprefix .. "/redirect-loop"
279}
280expect = {
281 code = 302
282}
283ignore = {
284 status = 1,
285 headers = 1,
286 body = 1
287}
288check_request(request, expect, ignore)
289
290io.write("testing wrong scheme: ") 327io.write("testing wrong scheme: ")
291request = { 328request = {
292 url = "wrong://" .. host .. cgiprefix .. "/cat", 329 url = "wrong://" .. host .. cgiprefix .. "/cat",