mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-26 04:28:20 +01:00
Using core.so instead of csocket.so and cmime.so.
This commit is contained in:
parent
65c35845c5
commit
4d455c6206
3
TODO
3
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
|
talk about the non-blocking connect in the manual
|
||||||
test it on Windows!!!
|
test it on Windows!!!
|
||||||
|
|
||||||
|
98
src/http.lua
98
src/http.lua
@ -27,10 +27,41 @@ PORT = 80
|
|||||||
-- user agent field sent in request
|
-- user agent field sent in request
|
||||||
USERAGENT = socket._VERSION
|
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
|
-- Extra sources and sinks
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
socket.sourcet["http-chunked"] = function(sock)
|
socket.sourcet["http-chunked"] = function(sock, headers)
|
||||||
return base.setmetatable({
|
return base.setmetatable({
|
||||||
getfd = function() return sock:getfd() end,
|
getfd = function() return sock:getfd() end,
|
||||||
dirty = function() return sock:dirty() 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)
|
local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
|
||||||
if not size then return nil, "invalid chunk size" end
|
if not size then return nil, "invalid chunk size" end
|
||||||
-- was it the last chunk?
|
-- was it the last chunk?
|
||||||
if size <= 0 then
|
if size > 0 then
|
||||||
-- skip trailer headers, if any
|
-- if not, get chunk and skip terminating CRLF
|
||||||
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
|
|
||||||
local chunk, err, part = sock:receive(size)
|
local chunk, err, part = sock:receive(size)
|
||||||
if chunk then sock:receive() end
|
if chunk then sock:receive() end
|
||||||
return chunk, err
|
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
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
@ -78,8 +106,8 @@ end
|
|||||||
local metat = { __index = {} }
|
local metat = { __index = {} }
|
||||||
|
|
||||||
-- default connect function, respecting the timeout
|
-- default connect function, respecting the timeout
|
||||||
local function connect(host, port)
|
local function connect(host, port, create)
|
||||||
local c, e = socket.tcp()
|
local c, e = (create or socket.tcp)()
|
||||||
if not c then return nil, e end
|
if not c then return nil, e end
|
||||||
c:settimeout(TIMEOUT)
|
c:settimeout(TIMEOUT)
|
||||||
local r, e = c:connect(host, port or PORT)
|
local r, e = c:connect(host, port or PORT)
|
||||||
@ -90,9 +118,9 @@ local function connect(host, port)
|
|||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
function open(host, port, user)
|
function open(host, port, create)
|
||||||
-- create socket with user connect function, or with default
|
-- 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
|
-- create our http request object, pointing to the socket
|
||||||
local h = base.setmetatable({ c = c }, metat)
|
local h = base.setmetatable({ c = c }, metat)
|
||||||
-- make sure the object close gets called on exception
|
-- make sure the object close gets called on exception
|
||||||
@ -130,37 +158,16 @@ function metat.__index:receivestatusline()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:receiveheaders()
|
function metat.__index:receiveheaders()
|
||||||
local line, name, value
|
return self.try(receiveheaders(self.c))
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function metat.__index:receivebody(headers, sink, step)
|
function metat.__index:receivebody(headers, sink, step)
|
||||||
sink = sink or ltn12.sink.null()
|
sink = sink or ltn12.sink.null()
|
||||||
step = step or ltn12.pump.step
|
step = step or ltn12.pump.step
|
||||||
local length = base.tonumber(headers["content-length"])
|
local length = base.tonumber(headers["content-length"])
|
||||||
local TE = headers["transfer-encoding"]
|
local t = headers["transfer-encoding"] -- shortcut
|
||||||
local mode = "default" -- connection close
|
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
|
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
|
||||||
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
||||||
sink, step))
|
sink, step))
|
||||||
@ -198,16 +205,21 @@ local function adjustproxy(reqt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function adjustheaders(headers, host)
|
local function adjustheaders(headers, host)
|
||||||
local lower = {}
|
-- default headers
|
||||||
-- override with user values
|
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
|
for i,v in pairs(headers or lower) do
|
||||||
lower[string.lower(i)] = v
|
lower[string.lower(i)] = v
|
||||||
end
|
end
|
||||||
lower["user-agent"] = lower["user-agent"] or USERAGENT
|
|
||||||
lower["host"] = lower["host"] or host
|
|
||||||
return lower
|
return lower
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- default url parts
|
||||||
local default = {
|
local default = {
|
||||||
host = "",
|
host = "",
|
||||||
port = PORT,
|
port = PORT,
|
||||||
@ -280,7 +292,7 @@ end
|
|||||||
|
|
||||||
function trequest(reqt)
|
function trequest(reqt)
|
||||||
reqt = adjustrequest(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:sendrequestline(reqt.method, reqt.uri)
|
||||||
h:sendheaders(reqt.headers)
|
h:sendheaders(reqt.headers)
|
||||||
if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end
|
if reqt.source then h:sendbody(reqt.headers, reqt.source, reqt.step) end
|
||||||
|
@ -108,7 +108,7 @@ static int base_open(lua_State *L) {
|
|||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Initializes all library modules.
|
* Initializes all library modules.
|
||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
LUASOCKET_API int luaopen_csocket(lua_State *L) {
|
LUASOCKET_API int luaopen_socketcore(lua_State *L) {
|
||||||
int i;
|
int i;
|
||||||
base_open(L);
|
base_open(L);
|
||||||
for (i = 0; mod[i].name; i++) mod[i].func(L);
|
for (i = 0; mod[i].name; i++) mod[i].func(L);
|
||||||
|
@ -27,6 +27,6 @@
|
|||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Initializes the library.
|
* Initializes the library.
|
||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
LUASOCKET_API int luaopen_csocket(lua_State *L);
|
LUASOCKET_API int luaopen_socketcore(lua_State *L);
|
||||||
|
|
||||||
#endif /* LUASOCKET_H */
|
#endif /* LUASOCKET_H */
|
||||||
|
@ -78,7 +78,7 @@ static UC b64unbase[256];
|
|||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Initializes module
|
* Initializes module
|
||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
MIME_API int luaopen_cmime(lua_State *L)
|
MIME_API int luaopen_mimecore(lua_State *L)
|
||||||
{
|
{
|
||||||
luaL_openlib(L, "mime", func, 0);
|
luaL_openlib(L, "mime", func, 0);
|
||||||
/* initialize lookup tables */
|
/* initialize lookup tables */
|
||||||
|
@ -19,6 +19,6 @@
|
|||||||
#define MIME_API extern
|
#define MIME_API extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MIME_API int luaopen_cmime(lua_State *L);
|
MIME_API int luaopen_mimecore(lua_State *L);
|
||||||
|
|
||||||
#endif /* MIME_H */
|
#endif /* MIME_H */
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
local base = _G
|
local base = _G
|
||||||
local ltn12 = require("ltn12")
|
local ltn12 = require("ltn12")
|
||||||
local mime = require("cmime")
|
local mime = require("mime.core")
|
||||||
|
local io = require("io")
|
||||||
|
local string = require("string")
|
||||||
module("mime")
|
module("mime")
|
||||||
|
|
||||||
-- encode, decode and wrap algorithm tables
|
-- encode, decode and wrap algorithm tables
|
||||||
@ -49,8 +51,6 @@ decodet['quoted-printable'] = function()
|
|||||||
return ltn12.filter.cycle(unqp, "")
|
return ltn12.filter.cycle(unqp, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
local io, string = io, string
|
|
||||||
|
|
||||||
local function format(chunk)
|
local function format(chunk)
|
||||||
if chunk then
|
if chunk then
|
||||||
if chunk == "" then return "''"
|
if chunk == "" then return "''"
|
||||||
|
@ -10,13 +10,13 @@
|
|||||||
local base = _G
|
local base = _G
|
||||||
local string = require("string")
|
local string = require("string")
|
||||||
local math = require("math")
|
local math = require("math")
|
||||||
local socket = require("csocket")
|
local socket = require("socket.core")
|
||||||
module("socket")
|
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()
|
local sock, err = socket.tcp()
|
||||||
if not sock then return nil, err end
|
if not sock then return nil, err end
|
||||||
if laddress then
|
if laddress then
|
||||||
@ -28,7 +28,7 @@ function socket.connect(address, port, laddress, lport)
|
|||||||
return sock
|
return sock
|
||||||
end
|
end
|
||||||
|
|
||||||
function socket.bind(host, port, backlog)
|
function bind(host, port, backlog)
|
||||||
local sock, err = socket.tcp()
|
local sock, err = socket.tcp()
|
||||||
if not sock then return nil, err end
|
if not sock then return nil, err end
|
||||||
sock:setoption("reuseaddr", true)
|
sock:setoption("reuseaddr", true)
|
||||||
@ -39,9 +39,9 @@ function socket.bind(host, port, backlog)
|
|||||||
return sock
|
return sock
|
||||||
end
|
end
|
||||||
|
|
||||||
socket.try = socket.newtry()
|
try = newtry()
|
||||||
|
|
||||||
function socket.choose(table)
|
function choose(table)
|
||||||
return function(name, opt1, opt2)
|
return function(name, opt1, opt2)
|
||||||
if base.type(name) ~= "string" then
|
if base.type(name) ~= "string" then
|
||||||
name, opt1, opt2 = "default", name, opt1
|
name, opt1, opt2 = "default", name, opt1
|
||||||
@ -56,12 +56,12 @@ end
|
|||||||
-- Socket sources and sinks, conforming to LTN12
|
-- Socket sources and sinks, conforming to LTN12
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
-- create namespaces inside LuaSocket namespace
|
-- create namespaces inside LuaSocket namespace
|
||||||
socket.sourcet = {}
|
sourcet = {}
|
||||||
socket.sinkt = {}
|
sinkt = {}
|
||||||
|
|
||||||
socket.BLOCKSIZE = 2048
|
BLOCKSIZE = 2048
|
||||||
|
|
||||||
socket.sinkt["close-when-done"] = function(sock)
|
sinkt["close-when-done"] = function(sock)
|
||||||
return base.setmetatable({
|
return base.setmetatable({
|
||||||
getfd = function() return sock:getfd() end,
|
getfd = function() return sock:getfd() end,
|
||||||
dirty = function() return sock:dirty() end
|
dirty = function() return sock:dirty() end
|
||||||
@ -75,7 +75,7 @@ socket.sinkt["close-when-done"] = function(sock)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
socket.sinkt["keep-open"] = function(sock)
|
sinkt["keep-open"] = function(sock)
|
||||||
return base.setmetatable({
|
return base.setmetatable({
|
||||||
getfd = function() return sock:getfd() end,
|
getfd = function() return sock:getfd() end,
|
||||||
dirty = function() return sock:dirty() end
|
dirty = function() return sock:dirty() end
|
||||||
@ -87,11 +87,11 @@ socket.sinkt["keep-open"] = function(sock)
|
|||||||
})
|
})
|
||||||
end
|
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({
|
return base.setmetatable({
|
||||||
getfd = function() return sock:getfd() end,
|
getfd = function() return sock:getfd() end,
|
||||||
dirty = function() return sock:dirty() end
|
dirty = function() return sock:dirty() end
|
||||||
@ -107,7 +107,7 @@ socket.sourcet["by-length"] = function(sock, length)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
socket.sourcet["until-closed"] = function(sock)
|
sourcet["until-closed"] = function(sock)
|
||||||
local done
|
local done
|
||||||
return base.setmetatable({
|
return base.setmetatable({
|
||||||
getfd = function() return sock:getfd() end,
|
getfd = function() return sock:getfd() end,
|
||||||
@ -127,8 +127,9 @@ socket.sourcet["until-closed"] = function(sock)
|
|||||||
end
|
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
|
||||||
|
@ -22,7 +22,7 @@ http.TIMEOUT = 10
|
|||||||
|
|
||||||
local t = socket.gettime()
|
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"
|
proxy = proxy or "http://localhost:3128"
|
||||||
prefix = prefix or "/luasocket-test"
|
prefix = prefix or "/luasocket-test"
|
||||||
cgiprefix = cgiprefix or "/luasocket-test-cgi"
|
cgiprefix = cgiprefix or "/luasocket-test-cgi"
|
||||||
@ -146,6 +146,7 @@ ignore = {
|
|||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
--[[
|
||||||
io.write("testing proxy with post method: ")
|
io.write("testing proxy with post method: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. cgiprefix .. "/cat",
|
url = "http://" .. host .. cgiprefix .. "/cat",
|
||||||
@ -163,6 +164,7 @@ ignore = {
|
|||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
]]
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing simple post function: ")
|
io.write("testing simple post function: ")
|
||||||
@ -249,6 +251,7 @@ ignore = {
|
|||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
--[[
|
||||||
io.write("testing proxy with redirection: ")
|
io.write("testing proxy with redirection: ")
|
||||||
request = {
|
request = {
|
||||||
url = "http://" .. host .. prefix,
|
url = "http://" .. host .. prefix,
|
||||||
@ -263,6 +266,7 @@ ignore = {
|
|||||||
headers = 1
|
headers = 1
|
||||||
}
|
}
|
||||||
check_request(request, expect, ignore)
|
check_request(request, expect, ignore)
|
||||||
|
]]
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
io.write("testing automatic auth failure: ")
|
io.write("testing automatic auth failure: ")
|
||||||
|
Loading…
Reference in New Issue
Block a user