Using core.so instead of csocket.so and cmime.so.

This commit is contained in:
Diego Nehab 2005-06-17 04:04:55 +00:00
parent 65c35845c5
commit 4d455c6206
9 changed files with 89 additions and 69 deletions

3
TODO
View File

@ -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!!!

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 "''"

View File

@ -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

View File

@ -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: ")