From 4d455c6206747ca65b14d65f75d34e16450d352b Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Fri, 17 Jun 2005 04:04:55 +0000 Subject: [PATCH] Using core.so instead of csocket.so and cmime.so. --- TODO | 3 ++ src/http.lua | 98 ++++++++++++++++++++++++++--------------------- src/luasocket.c | 2 +- src/luasocket.h | 2 +- src/mime.c | 2 +- src/mime.h | 2 +- src/mime.lua | 6 +-- src/socket.lua | 37 +++++++++--------- test/httptest.lua | 6 ++- 9 files changed, 89 insertions(+), 69 deletions(-) diff --git a/TODO b/TODO index 8749ea8..5772ae1 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,6 @@ +clean timeout argument to open functions in SMTP, HTTP and FTP +add create field to FTP and SMTP +talk about new create field in HTTP, FTP and SMTP talk about the non-blocking connect in the manual test it on Windows!!! diff --git a/src/http.lua b/src/http.lua index 1a7b101..91c52da 100644 --- a/src/http.lua +++ b/src/http.lua @@ -27,10 +27,41 @@ PORT = 80 -- user agent field sent in request USERAGENT = socket._VERSION +----------------------------------------------------------------------------- +-- Reads MIME headers from a connection, unfolding where needed +----------------------------------------------------------------------------- +local function receiveheaders(sock, headers) + local line, name, value, err + headers = headers or {} + -- get first line + line, err = sock:receive() + if err then return nil, err end + -- headers go until a blank line is found + while line ~= "" do + -- get field-name and value + name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) + if not (name and value) then return nil, "malformed reponse headers" end + name = string.lower(name) + -- get next line (value might be folded) + line, err = sock:receive() + if err then return nil, err end + -- unfold any folded values + while string.find(line, "^%s") do + value = value .. line + line = sock:receive() + if err then return nil, err end + end + -- save pair in table + if headers[name] then headers[name] = headers[name] .. ", " .. value + else headers[name] = value end + end + return headers +end + ----------------------------------------------------------------------------- -- Extra sources and sinks ----------------------------------------------------------------------------- -socket.sourcet["http-chunked"] = function(sock) +socket.sourcet["http-chunked"] = function(sock, headers) return base.setmetatable({ getfd = function() return sock:getfd() end, dirty = function() return sock:dirty() end @@ -42,18 +73,15 @@ socket.sourcet["http-chunked"] = function(sock) local size = base.tonumber(string.gsub(line, ";.*", ""), 16) if not size then return nil, "invalid chunk size" end -- was it the last chunk? - if size <= 0 then - -- skip trailer headers, if any - local line, err = sock:receive() - while not err and line ~= "" do - line, err = sock:receive() - end - return nil, err - else - -- get chunk and skip terminating CRLF + if size > 0 then + -- if not, get chunk and skip terminating CRLF local chunk, err, part = sock:receive(size) if chunk then sock:receive() end return chunk, err + else + -- if it was, read trailers into headers table + headers, err = receiveheaders(sock, headers) + if not headers then return nil, err end end end }) @@ -78,8 +106,8 @@ end local metat = { __index = {} } -- default connect function, respecting the timeout -local function connect(host, port) - local c, e = socket.tcp() +local function connect(host, port, create) + local c, e = (create or socket.tcp)() if not c then return nil, e end c:settimeout(TIMEOUT) local r, e = c:connect(host, port or PORT) @@ -90,9 +118,9 @@ local function connect(host, port) return c end -function open(host, port, user) +function open(host, port, create) -- create socket with user connect function, or with default - local c = socket.try((user or connect)(host, port)) + local c = socket.try(connect(host, port, create)) -- create our http request object, pointing to the socket local h = base.setmetatable({ c = c }, metat) -- make sure the object close gets called on exception @@ -130,37 +158,16 @@ function metat.__index:receivestatusline() end function metat.__index:receiveheaders() - local line, name, value - local headers = {} - -- get first line - line = self.try(self.c:receive()) - -- headers go until a blank line is found - while line ~= "" do - -- get field-name and value - name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) - self.try(name and value, "malformed reponse headers") - name = string.lower(name) - -- get next line (value might be folded) - line = self.try(self.c:receive()) - -- unfold any folded values - while string.find(line, "^%s") do - value = value .. line - line = self.try(self.c:receive()) - end - -- save pair in table - if headers[name] then headers[name] = headers[name] .. ", " .. value - else headers[name] = value end - end - return headers + return self.try(receiveheaders(self.c)) end function metat.__index:receivebody(headers, sink, step) sink = sink or ltn12.sink.null() step = step or ltn12.pump.step local length = base.tonumber(headers["content-length"]) - local TE = headers["transfer-encoding"] + local t = headers["transfer-encoding"] -- shortcut local mode = "default" -- connection close - if TE and TE ~= "identity" then mode = "http-chunked" + if t and t ~= "identity" then mode = "http-chunked" elseif base.tonumber(headers["content-length"]) then mode = "by-length" end return self.try(ltn12.pump.all(socket.source(mode, self.c, length), sink, step)) @@ -198,16 +205,21 @@ local function adjustproxy(reqt) end local function adjustheaders(headers, host) - local lower = {} - -- override with user values + -- default headers + local lower = { + ["user-agent"] = USERAGENT, + ["host"] = host, + ["connection"] = "close, TE", + ["te"] = "trailers" + } + -- override with user headers for i,v in pairs(headers or lower) do lower[string.lower(i)] = v end - lower["user-agent"] = lower["user-agent"] or USERAGENT - lower["host"] = lower["host"] or host return lower end +-- default url parts local default = { host = "", port = PORT, @@ -280,7 +292,7 @@ end function trequest(reqt) reqt = adjustrequest(reqt) - local h = open(reqt.host, reqt.port, reqt.connect) + local h = open(reqt.host, reqt.port, reqt.create) h:sendrequestline(reqt.method, reqt.uri) h:sendheaders(reqt.headers) 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) { /*-------------------------------------------------------------------------*\ * Initializes all library modules. \*-------------------------------------------------------------------------*/ -LUASOCKET_API int luaopen_csocket(lua_State *L) { +LUASOCKET_API int luaopen_socketcore(lua_State *L) { int i; base_open(L); 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 @@ /*-------------------------------------------------------------------------*\ * Initializes the library. \*-------------------------------------------------------------------------*/ -LUASOCKET_API int luaopen_csocket(lua_State *L); +LUASOCKET_API int luaopen_socketcore(lua_State *L); #endif /* LUASOCKET_H */ diff --git a/src/mime.c b/src/mime.c index 67f9f5b..70e0db9 100644 --- a/src/mime.c +++ b/src/mime.c @@ -78,7 +78,7 @@ static UC b64unbase[256]; /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -MIME_API int luaopen_cmime(lua_State *L) +MIME_API int luaopen_mimecore(lua_State *L) { luaL_openlib(L, "mime", func, 0); /* initialize lookup tables */ diff --git a/src/mime.h b/src/mime.h index d596861..34031a1 100644 --- a/src/mime.h +++ b/src/mime.h @@ -19,6 +19,6 @@ #define MIME_API extern #endif -MIME_API int luaopen_cmime(lua_State *L); +MIME_API int luaopen_mimecore(lua_State *L); #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 @@ ----------------------------------------------------------------------------- local base = _G local ltn12 = require("ltn12") -local mime = require("cmime") +local mime = require("mime.core") +local io = require("io") +local string = require("string") module("mime") -- encode, decode and wrap algorithm tables @@ -49,8 +51,6 @@ decodet['quoted-printable'] = function() return ltn12.filter.cycle(unqp, "") end -local io, string = io, string - local function format(chunk) if chunk then 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 @@ local base = _G local string = require("string") local math = require("math") -local socket = require("csocket") +local socket = require("socket.core") module("socket") ----------------------------------------------------------------------------- --- Auxiliar functions +-- Exported auxiliar functions ----------------------------------------------------------------------------- -function socket.connect(address, port, laddress, lport) +function connect(address, port, laddress, lport) local sock, err = socket.tcp() if not sock then return nil, err end if laddress then @@ -28,7 +28,7 @@ function socket.connect(address, port, laddress, lport) return sock end -function socket.bind(host, port, backlog) +function bind(host, port, backlog) local sock, err = socket.tcp() if not sock then return nil, err end sock:setoption("reuseaddr", true) @@ -39,9 +39,9 @@ function socket.bind(host, port, backlog) return sock end -socket.try = socket.newtry() +try = newtry() -function socket.choose(table) +function choose(table) return function(name, opt1, opt2) if base.type(name) ~= "string" then name, opt1, opt2 = "default", name, opt1 @@ -56,12 +56,12 @@ end -- Socket sources and sinks, conforming to LTN12 ----------------------------------------------------------------------------- -- create namespaces inside LuaSocket namespace -socket.sourcet = {} -socket.sinkt = {} +sourcet = {} +sinkt = {} -socket.BLOCKSIZE = 2048 +BLOCKSIZE = 2048 -socket.sinkt["close-when-done"] = function(sock) +sinkt["close-when-done"] = function(sock) return base.setmetatable({ getfd = function() return sock:getfd() end, dirty = function() return sock:dirty() end @@ -75,7 +75,7 @@ socket.sinkt["close-when-done"] = function(sock) }) end -socket.sinkt["keep-open"] = function(sock) +sinkt["keep-open"] = function(sock) return base.setmetatable({ getfd = function() return sock:getfd() end, dirty = function() return sock:dirty() end @@ -87,11 +87,11 @@ socket.sinkt["keep-open"] = function(sock) }) end -socket.sinkt["default"] = socket.sinkt["keep-open"] +sinkt["default"] = sinkt["keep-open"] -socket.sink = socket.choose(socket.sinkt) +sink = choose(sinkt) -socket.sourcet["by-length"] = function(sock, length) +sourcet["by-length"] = function(sock, length) return base.setmetatable({ getfd = function() return sock:getfd() end, dirty = function() return sock:dirty() end @@ -107,7 +107,7 @@ socket.sourcet["by-length"] = function(sock, length) }) end -socket.sourcet["until-closed"] = function(sock) +sourcet["until-closed"] = function(sock) local done return base.setmetatable({ getfd = function() return sock:getfd() end, @@ -127,8 +127,9 @@ socket.sourcet["until-closed"] = function(sock) end -socket.sourcet["default"] = socket.sourcet["until-closed"] +sourcet["default"] = sourcet["until-closed"] -socket.source = socket.choose(socket.sourcet) +source = choose(sourcet) ---getmetatable(_M).__index = nil +-- clear globals from namespace +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 local t = socket.gettime() -host = host or "diego.student.princeton.edu" +host = host or "localhost" -- "diego.student.princeton.edu" proxy = proxy or "http://localhost:3128" prefix = prefix or "/luasocket-test" cgiprefix = cgiprefix or "/luasocket-test-cgi" @@ -146,6 +146,7 @@ ignore = { check_request(request, expect, ignore) ------------------------------------------------------------------------ +--[[ io.write("testing proxy with post method: ") request = { url = "http://" .. host .. cgiprefix .. "/cat", @@ -163,6 +164,7 @@ ignore = { headers = 1 } check_request(request, expect, ignore) +]] ------------------------------------------------------------------------ io.write("testing simple post function: ") @@ -249,6 +251,7 @@ ignore = { check_request(request, expect, ignore) ------------------------------------------------------------------------ +--[[ io.write("testing proxy with redirection: ") request = { url = "http://" .. host .. prefix, @@ -263,6 +266,7 @@ ignore = { headers = 1 } check_request(request, expect, ignore) +]] ------------------------------------------------------------------------ io.write("testing automatic auth failure: ")