diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2005-06-17 04:04:55 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2005-06-17 04:04:55 +0000 |
commit | 4d455c6206747ca65b14d65f75d34e16450d352b (patch) | |
tree | 4607fc690526e4d227e5c5148025ffa9ba879843 | |
parent | 65c35845c54c7f84b1cf5b0e3d4c7bbdaf1014e3 (diff) | |
download | luasocket-4d455c6206747ca65b14d65f75d34e16450d352b.tar.gz luasocket-4d455c6206747ca65b14d65f75d34e16450d352b.tar.bz2 luasocket-4d455c6206747ca65b14d65f75d34e16450d352b.zip |
Using core.so instead of csocket.so and cmime.so.
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | src/http.lua | 98 | ||||
-rw-r--r-- | src/luasocket.c | 2 | ||||
-rw-r--r-- | src/luasocket.h | 2 | ||||
-rw-r--r-- | src/mime.c | 2 | ||||
-rw-r--r-- | src/mime.h | 2 | ||||
-rw-r--r-- | src/mime.lua | 6 | ||||
-rw-r--r-- | src/socket.lua | 37 | ||||
-rw-r--r-- | test/httptest.lua | 6 |
9 files changed, 89 insertions, 69 deletions
@@ -1,3 +1,6 @@ | |||
1 | clean timeout argument to open functions in SMTP, HTTP and FTP | ||
2 | add create field to FTP and SMTP | ||
3 | talk about new create field in HTTP, FTP and SMTP | ||
1 | talk about the non-blocking connect in the manual | 4 | talk about the non-blocking connect in the manual |
2 | test it on Windows!!! | 5 | test it on Windows!!! |
3 | 6 | ||
diff --git a/src/http.lua b/src/http.lua index 1a7b101..91c52da 100644 --- a/src/http.lua +++ b/src/http.lua | |||
@@ -28,9 +28,40 @@ PORT = 80 | |||
28 | USERAGENT = socket._VERSION | 28 | USERAGENT = socket._VERSION |
29 | 29 | ||
30 | ----------------------------------------------------------------------------- | 30 | ----------------------------------------------------------------------------- |
31 | -- Reads MIME headers from a connection, unfolding where needed | ||
32 | ----------------------------------------------------------------------------- | ||
33 | local function receiveheaders(sock, headers) | ||
34 | local line, name, value, err | ||
35 | headers = headers or {} | ||
36 | -- get first line | ||
37 | line, err = sock:receive() | ||
38 | if err then return nil, err end | ||
39 | -- headers go until a blank line is found | ||
40 | while line ~= "" do | ||
41 | -- get field-name and value | ||
42 | name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) | ||
43 | if not (name and value) then return nil, "malformed reponse headers" end | ||
44 | name = string.lower(name) | ||
45 | -- get next line (value might be folded) | ||
46 | line, err = sock:receive() | ||
47 | if err then return nil, err end | ||
48 | -- unfold any folded values | ||
49 | while string.find(line, "^%s") do | ||
50 | value = value .. line | ||
51 | line = sock:receive() | ||
52 | if err then return nil, err end | ||
53 | end | ||
54 | -- save pair in table | ||
55 | if headers[name] then headers[name] = headers[name] .. ", " .. value | ||
56 | else headers[name] = value end | ||
57 | end | ||
58 | return headers | ||
59 | end | ||
60 | |||
61 | ----------------------------------------------------------------------------- | ||
31 | -- Extra sources and sinks | 62 | -- Extra sources and sinks |
32 | ----------------------------------------------------------------------------- | 63 | ----------------------------------------------------------------------------- |
33 | socket.sourcet["http-chunked"] = function(sock) | 64 | socket.sourcet["http-chunked"] = function(sock, headers) |
34 | return base.setmetatable({ | 65 | return base.setmetatable({ |
35 | getfd = function() return sock:getfd() end, | 66 | getfd = function() return sock:getfd() end, |
36 | dirty = function() return sock:dirty() end | 67 | dirty = function() return sock:dirty() end |
@@ -42,18 +73,15 @@ socket.sourcet["http-chunked"] = function(sock) | |||
42 | local size = base.tonumber(string.gsub(line, ";.*", ""), 16) | 73 | local size = base.tonumber(string.gsub(line, ";.*", ""), 16) |
43 | if not size then return nil, "invalid chunk size" end | 74 | if not size then return nil, "invalid chunk size" end |
44 | -- was it the last chunk? | 75 | -- was it the last chunk? |
45 | if size <= 0 then | 76 | if size > 0 then |
46 | -- skip trailer headers, if any | 77 | -- if not, get chunk and skip terminating CRLF |
47 | local line, err = sock:receive() | ||
48 | while not err and line ~= "" do | ||
49 | line, err = sock:receive() | ||
50 | end | ||
51 | return nil, err | ||
52 | else | ||
53 | -- get chunk and skip terminating CRLF | ||
54 | local chunk, err, part = sock:receive(size) | 78 | local chunk, err, part = sock:receive(size) |
55 | if chunk then sock:receive() end | 79 | if chunk then sock:receive() end |
56 | return chunk, err | 80 | return chunk, err |
81 | else | ||
82 | -- if it was, read trailers into headers table | ||
83 | headers, err = receiveheaders(sock, headers) | ||
84 | if not headers then return nil, err end | ||
57 | end | 85 | end |
58 | end | 86 | end |
59 | }) | 87 | }) |
@@ -78,8 +106,8 @@ end | |||
78 | local metat = { __index = {} } | 106 | local metat = { __index = {} } |
79 | 107 | ||
80 | -- default connect function, respecting the timeout | 108 | -- default connect function, respecting the timeout |
81 | local function connect(host, port) | 109 | local function connect(host, port, create) |
82 | local c, e = socket.tcp() | 110 | local c, e = (create or socket.tcp)() |
83 | if not c then return nil, e end | 111 | if not c then return nil, e end |
84 | c:settimeout(TIMEOUT) | 112 | c:settimeout(TIMEOUT) |
85 | local r, e = c:connect(host, port or PORT) | 113 | local r, e = c:connect(host, port or PORT) |
@@ -90,9 +118,9 @@ local function connect(host, port) | |||
90 | return c | 118 | return c |
91 | end | 119 | end |
92 | 120 | ||
93 | function open(host, port, user) | 121 | function open(host, port, create) |
94 | -- create socket with user connect function, or with default | 122 | -- create socket with user connect function, or with default |
95 | local c = socket.try((user or connect)(host, port)) | 123 | local c = socket.try(connect(host, port, create)) |
96 | -- create our http request object, pointing to the socket | 124 | -- create our http request object, pointing to the socket |
97 | local h = base.setmetatable({ c = c }, metat) | 125 | local h = base.setmetatable({ c = c }, metat) |
98 | -- make sure the object close gets called on exception | 126 | -- make sure the object close gets called on exception |
@@ -130,37 +158,16 @@ function metat.__index:receivestatusline() | |||
130 | end | 158 | end |
131 | 159 | ||
132 | function metat.__index:receiveheaders() | 160 | function metat.__index:receiveheaders() |
133 | local line, name, value | 161 | return self.try(receiveheaders(self.c)) |
134 | local headers = {} | ||
135 | -- get first line | ||
136 | line = self.try(self.c:receive()) | ||
137 | -- headers go until a blank line is found | ||
138 | while line ~= "" do | ||
139 | -- get field-name and value | ||
140 | name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) | ||
141 | self.try(name and value, "malformed reponse headers") | ||
142 | name = string.lower(name) | ||
143 | -- get next line (value might be folded) | ||
144 | line = self.try(self.c:receive()) | ||
145 | -- unfold any folded values | ||
146 | while string.find(line, "^%s") do | ||
147 | value = value .. line | ||
148 | line = self.try(self.c:receive()) | ||
149 | end | ||
150 | -- save pair in table | ||
151 | if headers[name] then headers[name] = headers[name] .. ", " .. value | ||
152 | else headers[name] = value end | ||
153 | end | ||
154 | return headers | ||
155 | end | 162 | end |
156 | 163 | ||
157 | function metat.__index:receivebody(headers, sink, step) | 164 | function metat.__index:receivebody(headers, sink, step) |
158 | sink = sink or ltn12.sink.null() | 165 | sink = sink or ltn12.sink.null() |
159 | step = step or ltn12.pump.step | 166 | step = step or ltn12.pump.step |
160 | local length = base.tonumber(headers["content-length"]) | 167 | local length = base.tonumber(headers["content-length"]) |
161 | local TE = headers["transfer-encoding"] | 168 | local t = headers["transfer-encoding"] -- shortcut |
162 | local mode = "default" -- connection close | 169 | local mode = "default" -- connection close |
163 | if TE and TE ~= "identity" then mode = "http-chunked" | 170 | if t and t ~= "identity" then mode = "http-chunked" |
164 | elseif base.tonumber(headers["content-length"]) then mode = "by-length" end | 171 | elseif base.tonumber(headers["content-length"]) then mode = "by-length" end |
165 | return self.try(ltn12.pump.all(socket.source(mode, self.c, length), | 172 | return self.try(ltn12.pump.all(socket.source(mode, self.c, length), |
166 | sink, step)) | 173 | sink, step)) |
@@ -198,16 +205,21 @@ local function adjustproxy(reqt) | |||
198 | end | 205 | end |
199 | 206 | ||
200 | local function adjustheaders(headers, host) | 207 | local function adjustheaders(headers, host) |
201 | local lower = {} | 208 | -- default headers |
202 | -- override with user values | 209 | local lower = { |
210 | ["user-agent"] = USERAGENT, | ||
211 | ["host"] = host, | ||
212 | ["connection"] = "close, TE", | ||
213 | ["te"] = "trailers" | ||
214 | } | ||
215 | -- override with user headers | ||
203 | for i,v in pairs(headers or lower) do | 216 | for i,v in pairs(headers or lower) do |
204 | lower[string.lower(i)] = v | 217 | lower[string.lower(i)] = v |
205 | end | 218 | end |
206 | lower["user-agent"] = lower["user-agent"] or USERAGENT | ||
207 | lower["host"] = lower["host"] or host | ||
208 | return lower | 219 | return lower |
209 | end | 220 | end |
210 | 221 | ||
222 | -- default url parts | ||
211 | local default = { | 223 | local default = { |
212 | host = "", | 224 | host = "", |
213 | port = PORT, | 225 | port = PORT, |
@@ -280,7 +292,7 @@ end | |||
280 | 292 | ||
281 | function trequest(reqt) | 293 | function trequest(reqt) |
282 | reqt = adjustrequest(reqt) | 294 | reqt = adjustrequest(reqt) |
283 | local h = open(reqt.host, reqt.port, reqt.connect) | 295 | local h = open(reqt.host, reqt.port, reqt.create) |
284 | h:sendrequestline(reqt.method, reqt.uri) | 296 | h:sendrequestline(reqt.method, reqt.uri) |
285 | h:sendheaders(reqt.headers) | 297 | h:sendheaders(reqt.headers) |
286 | if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end | 298 | if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end |
diff --git a/src/luasocket.c b/src/luasocket.c index 2c3b526..ed26b1f 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
@@ -108,7 +108,7 @@ static int base_open(lua_State *L) { | |||
108 | /*-------------------------------------------------------------------------*\ | 108 | /*-------------------------------------------------------------------------*\ |
109 | * Initializes all library modules. | 109 | * Initializes all library modules. |
110 | \*-------------------------------------------------------------------------*/ | 110 | \*-------------------------------------------------------------------------*/ |
111 | LUASOCKET_API int luaopen_csocket(lua_State *L) { | 111 | LUASOCKET_API int luaopen_socketcore(lua_State *L) { |
112 | int i; | 112 | int i; |
113 | base_open(L); | 113 | base_open(L); |
114 | for (i = 0; mod[i].name; i++) mod[i].func(L); | 114 | for (i = 0; mod[i].name; i++) mod[i].func(L); |
diff --git a/src/luasocket.h b/src/luasocket.h index 768e335..34a7693 100644 --- a/src/luasocket.h +++ b/src/luasocket.h | |||
@@ -27,6 +27,6 @@ | |||
27 | /*-------------------------------------------------------------------------*\ | 27 | /*-------------------------------------------------------------------------*\ |
28 | * Initializes the library. | 28 | * Initializes the library. |
29 | \*-------------------------------------------------------------------------*/ | 29 | \*-------------------------------------------------------------------------*/ |
30 | LUASOCKET_API int luaopen_csocket(lua_State *L); | 30 | LUASOCKET_API int luaopen_socketcore(lua_State *L); |
31 | 31 | ||
32 | #endif /* LUASOCKET_H */ | 32 | #endif /* LUASOCKET_H */ |
@@ -78,7 +78,7 @@ static UC b64unbase[256]; | |||
78 | /*-------------------------------------------------------------------------*\ | 78 | /*-------------------------------------------------------------------------*\ |
79 | * Initializes module | 79 | * Initializes module |
80 | \*-------------------------------------------------------------------------*/ | 80 | \*-------------------------------------------------------------------------*/ |
81 | MIME_API int luaopen_cmime(lua_State *L) | 81 | MIME_API int luaopen_mimecore(lua_State *L) |
82 | { | 82 | { |
83 | luaL_openlib(L, "mime", func, 0); | 83 | luaL_openlib(L, "mime", func, 0); |
84 | /* initialize lookup tables */ | 84 | /* initialize lookup tables */ |
@@ -19,6 +19,6 @@ | |||
19 | #define MIME_API extern | 19 | #define MIME_API extern |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | MIME_API int luaopen_cmime(lua_State *L); | 22 | MIME_API int luaopen_mimecore(lua_State *L); |
23 | 23 | ||
24 | #endif /* MIME_H */ | 24 | #endif /* MIME_H */ |
diff --git a/src/mime.lua b/src/mime.lua index f6509a0..e112f8a 100644 --- a/src/mime.lua +++ b/src/mime.lua | |||
@@ -10,7 +10,9 @@ | |||
10 | ----------------------------------------------------------------------------- | 10 | ----------------------------------------------------------------------------- |
11 | local base = _G | 11 | local base = _G |
12 | local ltn12 = require("ltn12") | 12 | local ltn12 = require("ltn12") |
13 | local mime = require("cmime") | 13 | local mime = require("mime.core") |
14 | local io = require("io") | ||
15 | local string = require("string") | ||
14 | module("mime") | 16 | module("mime") |
15 | 17 | ||
16 | -- encode, decode and wrap algorithm tables | 18 | -- encode, decode and wrap algorithm tables |
@@ -49,8 +51,6 @@ decodet['quoted-printable'] = function() | |||
49 | return ltn12.filter.cycle(unqp, "") | 51 | return ltn12.filter.cycle(unqp, "") |
50 | end | 52 | end |
51 | 53 | ||
52 | local io, string = io, string | ||
53 | |||
54 | local function format(chunk) | 54 | local function format(chunk) |
55 | if chunk then | 55 | if chunk then |
56 | if chunk == "" then return "''" | 56 | if chunk == "" then return "''" |
diff --git a/src/socket.lua b/src/socket.lua index d1c7846..13b474d 100644 --- a/src/socket.lua +++ b/src/socket.lua | |||
@@ -10,13 +10,13 @@ | |||
10 | local base = _G | 10 | local base = _G |
11 | local string = require("string") | 11 | local string = require("string") |
12 | local math = require("math") | 12 | local math = require("math") |
13 | local socket = require("csocket") | 13 | local socket = require("socket.core") |
14 | module("socket") | 14 | module("socket") |
15 | 15 | ||
16 | ----------------------------------------------------------------------------- | 16 | ----------------------------------------------------------------------------- |
17 | -- Auxiliar functions | 17 | -- Exported auxiliar functions |
18 | ----------------------------------------------------------------------------- | 18 | ----------------------------------------------------------------------------- |
19 | function socket.connect(address, port, laddress, lport) | 19 | function connect(address, port, laddress, lport) |
20 | local sock, err = socket.tcp() | 20 | local sock, err = socket.tcp() |
21 | if not sock then return nil, err end | 21 | if not sock then return nil, err end |
22 | if laddress then | 22 | if laddress then |
@@ -28,7 +28,7 @@ function socket.connect(address, port, laddress, lport) | |||
28 | return sock | 28 | return sock |
29 | end | 29 | end |
30 | 30 | ||
31 | function socket.bind(host, port, backlog) | 31 | function bind(host, port, backlog) |
32 | local sock, err = socket.tcp() | 32 | local sock, err = socket.tcp() |
33 | if not sock then return nil, err end | 33 | if not sock then return nil, err end |
34 | sock:setoption("reuseaddr", true) | 34 | sock:setoption("reuseaddr", true) |
@@ -39,9 +39,9 @@ function socket.bind(host, port, backlog) | |||
39 | return sock | 39 | return sock |
40 | end | 40 | end |
41 | 41 | ||
42 | socket.try = socket.newtry() | 42 | try = newtry() |
43 | 43 | ||
44 | function socket.choose(table) | 44 | function choose(table) |
45 | return function(name, opt1, opt2) | 45 | return function(name, opt1, opt2) |
46 | if base.type(name) ~= "string" then | 46 | if base.type(name) ~= "string" then |
47 | name, opt1, opt2 = "default", name, opt1 | 47 | name, opt1, opt2 = "default", name, opt1 |
@@ -56,12 +56,12 @@ end | |||
56 | -- Socket sources and sinks, conforming to LTN12 | 56 | -- Socket sources and sinks, conforming to LTN12 |
57 | ----------------------------------------------------------------------------- | 57 | ----------------------------------------------------------------------------- |
58 | -- create namespaces inside LuaSocket namespace | 58 | -- create namespaces inside LuaSocket namespace |
59 | socket.sourcet = {} | 59 | sourcet = {} |
60 | socket.sinkt = {} | 60 | sinkt = {} |
61 | 61 | ||
62 | socket.BLOCKSIZE = 2048 | 62 | BLOCKSIZE = 2048 |
63 | 63 | ||
64 | socket.sinkt["close-when-done"] = function(sock) | 64 | sinkt["close-when-done"] = function(sock) |
65 | return base.setmetatable({ | 65 | return base.setmetatable({ |
66 | getfd = function() return sock:getfd() end, | 66 | getfd = function() return sock:getfd() end, |
67 | dirty = function() return sock:dirty() end | 67 | dirty = function() return sock:dirty() end |
@@ -75,7 +75,7 @@ socket.sinkt["close-when-done"] = function(sock) | |||
75 | }) | 75 | }) |
76 | end | 76 | end |
77 | 77 | ||
78 | socket.sinkt["keep-open"] = function(sock) | 78 | sinkt["keep-open"] = function(sock) |
79 | return base.setmetatable({ | 79 | return base.setmetatable({ |
80 | getfd = function() return sock:getfd() end, | 80 | getfd = function() return sock:getfd() end, |
81 | dirty = function() return sock:dirty() end | 81 | dirty = function() return sock:dirty() end |
@@ -87,11 +87,11 @@ socket.sinkt["keep-open"] = function(sock) | |||
87 | }) | 87 | }) |
88 | end | 88 | end |
89 | 89 | ||
90 | socket.sinkt["default"] = socket.sinkt["keep-open"] | 90 | sinkt["default"] = sinkt["keep-open"] |
91 | 91 | ||
92 | socket.sink = socket.choose(socket.sinkt) | 92 | sink = choose(sinkt) |
93 | 93 | ||
94 | socket.sourcet["by-length"] = function(sock, length) | 94 | sourcet["by-length"] = function(sock, length) |
95 | return base.setmetatable({ | 95 | return base.setmetatable({ |
96 | getfd = function() return sock:getfd() end, | 96 | getfd = function() return sock:getfd() end, |
97 | dirty = function() return sock:dirty() end | 97 | dirty = function() return sock:dirty() end |
@@ -107,7 +107,7 @@ socket.sourcet["by-length"] = function(sock, length) | |||
107 | }) | 107 | }) |
108 | end | 108 | end |
109 | 109 | ||
110 | socket.sourcet["until-closed"] = function(sock) | 110 | sourcet["until-closed"] = function(sock) |
111 | local done | 111 | local done |
112 | return base.setmetatable({ | 112 | return base.setmetatable({ |
113 | getfd = function() return sock:getfd() end, | 113 | getfd = function() return sock:getfd() end, |
@@ -127,8 +127,9 @@ socket.sourcet["until-closed"] = function(sock) | |||
127 | end | 127 | end |
128 | 128 | ||
129 | 129 | ||
130 | socket.sourcet["default"] = socket.sourcet["until-closed"] | 130 | sourcet["default"] = sourcet["until-closed"] |
131 | 131 | ||
132 | socket.source = socket.choose(socket.sourcet) | 132 | source = choose(sourcet) |
133 | 133 | ||
134 | --getmetatable(_M).__index = nil | 134 | -- clear globals from namespace |
135 | getmetatable(_M).__index = nil | ||
diff --git a/test/httptest.lua b/test/httptest.lua index 963b947..86f14a4 100644 --- a/test/httptest.lua +++ b/test/httptest.lua | |||
@@ -22,7 +22,7 @@ http.TIMEOUT = 10 | |||
22 | 22 | ||
23 | local t = socket.gettime() | 23 | local t = socket.gettime() |
24 | 24 | ||
25 | host = host or "diego.student.princeton.edu" | 25 | host = host or "localhost" -- "diego.student.princeton.edu" |
26 | proxy = proxy or "http://localhost:3128" | 26 | proxy = proxy or "http://localhost:3128" |
27 | prefix = prefix or "/luasocket-test" | 27 | prefix = prefix or "/luasocket-test" |
28 | cgiprefix = cgiprefix or "/luasocket-test-cgi" | 28 | cgiprefix = cgiprefix or "/luasocket-test-cgi" |
@@ -146,6 +146,7 @@ ignore = { | |||
146 | check_request(request, expect, ignore) | 146 | check_request(request, expect, ignore) |
147 | 147 | ||
148 | ------------------------------------------------------------------------ | 148 | ------------------------------------------------------------------------ |
149 | --[[ | ||
149 | io.write("testing proxy with post method: ") | 150 | io.write("testing proxy with post method: ") |
150 | request = { | 151 | request = { |
151 | url = "http://" .. host .. cgiprefix .. "/cat", | 152 | url = "http://" .. host .. cgiprefix .. "/cat", |
@@ -163,6 +164,7 @@ ignore = { | |||
163 | headers = 1 | 164 | headers = 1 |
164 | } | 165 | } |
165 | check_request(request, expect, ignore) | 166 | check_request(request, expect, ignore) |
167 | ]] | ||
166 | 168 | ||
167 | ------------------------------------------------------------------------ | 169 | ------------------------------------------------------------------------ |
168 | io.write("testing simple post function: ") | 170 | io.write("testing simple post function: ") |
@@ -249,6 +251,7 @@ ignore = { | |||
249 | check_request(request, expect, ignore) | 251 | check_request(request, expect, ignore) |
250 | 252 | ||
251 | ------------------------------------------------------------------------ | 253 | ------------------------------------------------------------------------ |
254 | --[[ | ||
252 | io.write("testing proxy with redirection: ") | 255 | io.write("testing proxy with redirection: ") |
253 | request = { | 256 | request = { |
254 | url = "http://" .. host .. prefix, | 257 | url = "http://" .. host .. prefix, |
@@ -263,6 +266,7 @@ ignore = { | |||
263 | headers = 1 | 266 | headers = 1 |
264 | } | 267 | } |
265 | check_request(request, expect, ignore) | 268 | check_request(request, expect, ignore) |
269 | ]] | ||
266 | 270 | ||
267 | ------------------------------------------------------------------------ | 271 | ------------------------------------------------------------------------ |
268 | io.write("testing automatic auth failure: ") | 272 | io.write("testing automatic auth failure: ") |