mirror of
				https://github.com/lunarmodules/luasocket.git
				synced 2025-10-31 02:15:38 +01:00 
			
		
		
		
	Using core.so instead of csocket.so and cmime.so.
This commit is contained in:
		
							
								
								
									
										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 | ||||
| test it on Windows!!! | ||||
|  | ||||
|   | ||||
							
								
								
									
										98
									
								
								src/http.lua
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								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 | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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 "''" | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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: ") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user