Skip to content

Luasec HTTPS Module

Nikhil R edited this page Aug 27, 2017 · 3 revisions

The HTTPS module (https.lua) is the result of integrating the HTTP functions from Luasocket into the Luasec module itself. The parameters are same as the Luasocket HTTP module with support for extra parameters.

Paramaters allowed the https.request function

The request function has two forms. The simple form downloads a URL using the GET or POST method and is based on strings. The generic form performs any HTTP method and is LTN12 based.

If the first argument of the request function is a string, it should be an url. In that case, if a body is provided as a string, the function will perform a POST method in the url. Otherwise, it performs a GET in the url.

If the first argument is instead a table, the most important fields are the url and the simple LTN12 sink that will receive the downloaded content. Any part of the url can be overridden by including the appropriate field in the request table. If authentication information is provided, the function uses the Basic Authentication Scheme to retrieve the document. If sink is nil, the function discards the downloaded data.

The optional parameters are the following:

  • method: The HTTP request method. Defaults to GET.

  • headers: Any additional HTTP headers to send with the request.

  • source: simple LTN12 source to provide the request body. If there is a body, you need to provide an appropriate "content-length" request header field, or the function will attempt to send the body as "chunked" (something few servers support). Defaults to the empty source.

  • step: LTN12 pump step function used to move data. Defaults to the LTN12 pump.step function.

  • proxy: The URL of a proxy server to use. Defaults to no proxy. A CONNECT tunnel is created between the proxy and the luasec client.

  • redirect: Set to false to prevent the function from automatically following 301 or 302 server redirect messages.It defaults to true.

  • unsaferedirect: Defaults to false to prevent redirects(downgrades) from HTTPS -> HTTP.

  • create: An optional function to be used instead of socket.tcp when the communications socket is created.

In case of failure, the function returns nil followed by an error message. If successful, the simple form returns the response body as a string, followed by the response status code, the response headers and the response status line. The generic function returns the same information, except the first return value is just the number 1 (the body goes to the sink).

Even when the server fails to provide the contents of the requested URL (URL not found, for example), it usually returns a message body (a web page informing the URL was not found or some other useless page). To make sure the operation was successful, check the returned status code. For a list of the possible values and their meanings, refer to RFC 2616.

Examples

First require the libraries into the namespace and make a table for holding the final result.

local https = require("ssl.https")
local ltn12 = require('ltn12')
local result_table = {}

This is the second form of the function where we pass a request table and a sink. We are querying https://google.com while setting redirect to true.

local reqt = {
  url = 'https://google.com',
  redirect = true,
  target = {},
}

reqt.sink = ltn12.sink.table(result_table)

Then pass the request table to the https.request function.

local result, code, headers, status = https.request(reqt)

Now result_table would contain the data transferred from the connection and headers table would have all the HTTP headers in the response.

print(code, status)
-- 200 OK

If we want to route the HTTPS session through a proxy we modify the request table like this. On the background it actually creates a CONNECT tunnel between the client and the proxy. On the proxies end, it just starts forwarding packets to and fro between the destination server and luasec.

local reqt = {
  url = 'https://google.com',
  redirect = true,
  target = {},
  proxy = "http://<proxy ip address>:<proxy port>",
}
reqt.sink = ltn12.sink.table(result_table)
local result, code, headers, status = https.request(reqt)

If we want to allow unsafe redirects from HTTP->HTTPS downgrade we have to set the unsaferedirects parameter to true. In this case once luasec gets to know about the redirect, it checks for the unsaferedirect paramter and if it is set to true opens a new tunnel with the proxy with the final destination as the HTTP site. The sample request would look like this:

local reqt = {
  url = 'https://goo.gl/tBfqNu',
  redirect = true,
  target = {},
  proxy = "http://<proxy ip address>:<proxy port>",
  unsaferedirect = true,
}
reqt.sink = ltn12.sink.table(result_table)
local result, code, headers, status = https.request(reqt)

It can also redirect from HTTP-> HTTPS which is allowed by default. This also works when the proxy is enabled.

local reqt = {
  url = 'http://goo.gl/UBCUc5',
  redirect = true,
  target = {},
  proxy = "http://<proxy ip address>:<proxy port>",
  unsaferedirect = true,
}
reqt.sink = ltn12.sink.table(result_table)
local result, code, headers, status = https.request(reqt)\

Here is a complete example with the proxy parameter set. It prints out the entire HTML received for different cases.

local https = require("ssl.https")
local ltn12 = require('ltn12')
local result_table = {}

local function doreq(url)
	local reqt = {
	  url = url,
	  redirect = true,
	  target = {},
	  proxy = "http://172.28.128.1:4444",
          -- unsaferedirect = true, -- uncomment this line when testing the security case
	}
	reqt.sink = ltn12.sink.table(result_table)

	local result, code, headers, status = https.request(reqt)
	print("Fetching:",url,"==>",code, status)
	if result then for k,v in pairs(headers) do print("",k,v) end end
	if result then for k,v in pairs(result_table) do print("",k,v) end end
	print(result)
	return result, code, headers, status
end
-- local result, code, headers, status = doreq("http://example.com")--simple http 
-- local result, code, headers, status = doreq("http://goo.gl/tBfqNu") -- http --> http redirect

-- local result, code, headers, status = doreq("https://example.com") --simple https
local result, code, headers, status = doreq("https://google.com")  -- https --> https redirect

-- local result, code, headers, status = doreq("http://goo.gl/UBCUc5")  -- http --> https redirect
-- local result, code, headers, status = doreq("https://goo.gl/tBfqNu")  -- https --> http security test case 

Clone this wiki locally