mirror of
				https://github.com/lunarmodules/luasocket.git
				synced 2025-10-31 10:25:55 +01:00 
			
		
		
		
	socket.http.request(): simultaneous support for http and https URL schemes, with caller-adjustable scheme-to-transport mappings (default "socket.http" and "ssl.https")
This commit is contained in:
		
							
								
								
									
										54
									
								
								src/http.lua
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/http.lua
									
									
									
									
									
								
							| @@ -26,15 +26,20 @@ _M.TIMEOUT = 60 | |||||||
| -- user agent field sent in request | -- user agent field sent in request | ||||||
| _M.USERAGENT = socket._VERSION | _M.USERAGENT = socket._VERSION | ||||||
|  |  | ||||||
| -- supported schemes | -- supported schemes and their particulars | ||||||
| local SCHEMES = { | local SCHEMES = { | ||||||
|     http = { port = 80 } |     http = { | ||||||
|     , https = { port = 443 }} |         port = 80 | ||||||
|  |         , create = function(t) | ||||||
|  |             return socket.tcp end } | ||||||
|  |     , https = { | ||||||
|  |         port = 443 | ||||||
|  |         , create = function(t) | ||||||
|  |             return require("ssl.https").tcp(t) end }} | ||||||
|  |  | ||||||
| -- default scheme and port for document retrieval | -- default scheme and port for document retrieval | ||||||
| local SCHEME = 'http' | local SCHEME = 'http' | ||||||
| local PORT = SCHEMES[SCHEME].port | local PORT = SCHEMES[SCHEME].port | ||||||
|  |  | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| -- Reads MIME headers from a connection, unfolding where needed | -- Reads MIME headers from a connection, unfolding where needed | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| @@ -115,13 +120,13 @@ local metat = { __index = {} } | |||||||
|  |  | ||||||
| function _M.open(host, port, create) | function _M.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((create or socket.tcp)()) |     local c = socket.try(create()) | ||||||
|     local h = base.setmetatable({ c = c }, metat) |     local h = base.setmetatable({ c = c }, metat) | ||||||
|     -- create finalized try |     -- create finalized try | ||||||
|     h.try = socket.newtry(function() h:close() end) |     h.try = socket.newtry(function() h:close() end) | ||||||
|     -- set timeout before connecting |     -- set timeout before connecting | ||||||
|     h.try(c:settimeout(_M.TIMEOUT)) |     h.try(c:settimeout(_M.TIMEOUT)) | ||||||
|     h.try(c:connect(host, port or PORT)) |     h.try(c:connect(host, port)) | ||||||
|     -- here everything worked |     -- here everything worked | ||||||
|     return h |     return h | ||||||
| end | end | ||||||
| @@ -221,14 +226,13 @@ end | |||||||
|  |  | ||||||
| local function adjustheaders(reqt) | local function adjustheaders(reqt) | ||||||
|     -- default headers |     -- default headers | ||||||
|     local headhost = reqt.host |     local host = reqt.host | ||||||
|     local headport = tostring(reqt.port) |     local port = tostring(reqt.port) | ||||||
|     local schemeport = tostring(SCHEMES[reqt.scheme].port) |     if port ~= tostring(SCHEMES[reqt.scheme].port) then | ||||||
|     if headport ~= schemeport then |         host = host .. ':' .. port end | ||||||
|         headhost = headhost .. ':' .. headport end |  | ||||||
|     local lower = { |     local lower = { | ||||||
|         ["user-agent"] = _M.USERAGENT, |         ["user-agent"] = _M.USERAGENT, | ||||||
|         ["host"] = headhost, |         ["host"] = host, | ||||||
|         ["connection"] = "close, TE", |         ["connection"] = "close, TE", | ||||||
|         ["te"] = "trailers" |         ["te"] = "trailers" | ||||||
|     } |     } | ||||||
| @@ -267,8 +271,13 @@ local function adjustrequest(reqt) | |||||||
|     local nreqt = reqt.url and url.parse(reqt.url, default) or {} |     local nreqt = reqt.url and url.parse(reqt.url, default) or {} | ||||||
|     -- explicit components override url |     -- explicit components override url | ||||||
|     for i,v in base.pairs(reqt) do nreqt[i] = v end |     for i,v in base.pairs(reqt) do nreqt[i] = v end | ||||||
|     if nreqt.port == "" then nreqt.port = PORT end |     -- default to scheme particulars | ||||||
|     if not (nreqt.host and nreqt.host ~= "") then |     local schemedefs, host, port, method | ||||||
|  |         = SCHEMES[nreqt.scheme], nreqt.host, nreqt.port, nreqt.method | ||||||
|  |     if not nreqt.create then nreqt.create = schemedefs.create(nreqt) end | ||||||
|  |     if not (port and port ~= '') then nreqt.port = schemedefs.port end | ||||||
|  |     if not (method and method ~= '') then nreqt.method = 'GET' end | ||||||
|  |     if not (host and host ~= "") then | ||||||
|         socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'") |         socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'") | ||||||
|     end |     end | ||||||
|     -- compute uri if user hasn't overriden |     -- compute uri if user hasn't overriden | ||||||
| @@ -285,8 +294,10 @@ local function shouldredirect(reqt, code, headers) | |||||||
|     if not location then return false end |     if not location then return false end | ||||||
|     location = string.gsub(location, "%s", "") |     location = string.gsub(location, "%s", "") | ||||||
|     if location == "" then return false end |     if location == "" then return false end | ||||||
|     local scheme = string.match(location, "^([%w][%w%+%-%.]*)%:") |     local scheme = url.parse(location).scheme | ||||||
|     if scheme and not SCHEMES[scheme] then return false end |     if scheme and (not SCHEMES[scheme]) then return false end | ||||||
|  |     -- avoid https downgrades | ||||||
|  |     if ('https' == reqt.scheme) and ('https' ~= scheme) then return false end | ||||||
|     return (reqt.redirect ~= false) and |     return (reqt.redirect ~= false) and | ||||||
|            (code == 301 or code == 302 or code == 303 or code == 307) and |            (code == 301 or code == 302 or code == 303 or code == 307) and | ||||||
|            (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") |            (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD") | ||||||
| @@ -306,10 +317,16 @@ end | |||||||
| local trequest, tredirect | local trequest, tredirect | ||||||
|  |  | ||||||
| --[[local]] function tredirect(reqt, location) | --[[local]] function tredirect(reqt, location) | ||||||
|     local result, code, headers, status = trequest { |  | ||||||
|     -- the RFC says the redirect URL has to be absolute, but some |     -- the RFC says the redirect URL has to be absolute, but some | ||||||
|     -- servers do not respect that |     -- servers do not respect that | ||||||
|         url = url.absolute(reqt.url, location), |     local newurl = url.absolute(reqt.url, location) | ||||||
|  |     -- if switching schemes, reset port and create function | ||||||
|  |     if url.parse(newurl).scheme ~= reqt.scheme then | ||||||
|  |         reqt.port = nil | ||||||
|  |         reqt.create = nil end | ||||||
|  |     -- make new request | ||||||
|  |     local result, code, headers, status = trequest { | ||||||
|  |         url = newurl, | ||||||
|         source = reqt.source, |         source = reqt.source, | ||||||
|         sink = reqt.sink, |         sink = reqt.sink, | ||||||
|         headers = reqt.headers, |         headers = reqt.headers, | ||||||
| @@ -397,4 +414,5 @@ _M.request = socket.protect(function(reqt, body) | |||||||
|     else return trequest(reqt) end |     else return trequest(reqt) end | ||||||
| end) | end) | ||||||
|  |  | ||||||
|  | _M.schemes = SCHEMES | ||||||
| return _M | return _M | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user