[ST Edge] v43 Http Socket Timeout

There are a few problems with that example, I will make a note to get it updated.

The api in question is using the table variant, which will require a sink property is provided to put the body data into. Also you are correct, status is going to resolve to the http status info from the first line of the http response (i.e.HTTP/1.1 200 OK) so status == 200 is always going to be falsy

I took a look at this and it is pretty nice. It is actually similar to what I was starting to build with my HttpClient module above. I’m going to explore this a bit more.

@robert.masen Can luncheon be used with https? Just want to make sure before rewriting that portion of the driver. Are there examples of using luncheon with https? I was looking in the repo for the tcp setup required on the request socket if making https requests.

It should work just fine with a wrapped socket from cosock. something like

local socket = require "cosock.socket"
local ssl = require "cosock.ssl"

local tcp = socket.tcp()
local ip = "192.168.1.1"
local port = 8888
tcp:connect(ip, port)
 
-- TLS/SSL initialization
local params = {
  mode = "client",
  protocol = "any",
  verify = "none",
  options = {"all", "no_sslv3"}
}
local wrapped = ssl.wrap(conn, params)
wrappeddohandshake()
--TLS/SSL initialization

--At this point wrapped will work exactly like tcp would have
--except all traffic will be encrypted

see the luasec wiki for more options

If you were to insert the section between the two TLS/SSL initialization comments, the luncheon example work exactly the same.

@robert.masen First off, thank you very much for working to address this.

I have this using luncheon which appears close. It is sending the request, but The code is hanging up on the response, never print the Response in this code:

    local socket = require "cosock.socket"
    local ssl = require "cosock.ssl"
    local lunch = require 'luncheon'

    local sock = socket.tcp()
    local ip = self.ip
    local port = self.port
    sock:connect(ip, port)

    -- TLS/SSL initialization
    local params = {
        mode = "client",
        protocol = "any",
        verify = "none",
        options = { "all", "no_sslv3" }
    }
    sock = ssl.wrap(sock, params)
    sock:dohandshake()
    --TLS/SSL initialization

    local req = assert(lunch.Request.new(args.method, args.route, sock))

    if args.body then
        local encoded = self:encode('application/json', args.body)
        req = req:append_body(encoded):set_content_type('application/json')
    end

    if self.token then
        req = req:add_header('hue-application-key', self.token)
    end

    print('Sending...')
    for line in req:iter() do
        print(string.gsub(line, '\r?\n$', ''))
        sock:send(line)
    end
    print('Sent')

    local res = assert(lunch.Response.tcp_source(sock))

    print('Response')
    print(res.status)
    print(res:get_body())

    sock:close()

Is tcp_source the correct method to use here? Can the socket be reused for further requests?

Actually, trying this errors out, so it looks like the issue may be on the send call

for line in req:iter() do
    print(string.gsub(line, '\r?\n$', ''))
    assert(sock:send(line))
end
[string "st/dispatcher.lua"]:229: Error encountered while processing event for <Device: XXXXXXX>:
    arg1: init
[string "test.lua"]:180: closed

@robert.masen Thank you for all of the help. I ended up getting it going on v43 using a modified version of ssl/https.lua that is being bundled in the driver. I plan to use luncheon down the road as it matures. It has a very nice interface.

This is most likely because the server you are communicating with is replying with a chunk encoding which isn’t currently supported directly in Luncheon. Hopefully it will get added soon.

It is possible to reuse sockets with luncheon but you would have to manage the connection semantics with the server manually.

@robert.masen what’s the advantage of the above over

local http = require "cosock.socket.http"
local https = require "cosock.ssl.https"

Is there a preferred way ?

No, these should be equivalent. the point of cosock.asyncify is to allow for the consumption of luasocket based libraries so I would say typically you wouldn’t consume luasocket via asyncify but there isn’t anything wrong with that approach.

1 Like

@RBoy If you dig into the asyncify code, it replaces the modules internally when you use it. So when you ssl.https it internally swaps it out to the cosock version and does the same with dependencies. I use it to import libraries I have written that also need to run without the use of cosock internally (used on desktop)

1 Like

Just to be clear, cosock is available to use on a desktop if you wanted (luarocks install cosock), you just need to make sure you have your top level module call cosock.run() to get cosock to drive your coroutines.

1 Like