0

I have an extremely simple web server to toggle a relay. It will work sometimes, and other times, a connection is made, but times out. If I reload the page and try again. It will start working again. Any ideas?
Here is the code:

srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    conn:on("receive",function(conn,data)
        conn:send("HTTP/1.1 200 OK\r\n\r\n")

        path = string.find(data, "chk=on")
        print(path)
        if path == nil then
            print("off")
            gpio.write(1, gpio.LOW)
        end
        if path ~= nil then
            print("on")
            gpio.write(1, gpio.HIGH)
        end

        conn:send("<h1>Relay Control</h1>")
        conn:send("<form action='/' method='post'>")
        conn:send("<input type='checkbox' value='on' name='chk'>")
        conn:send("<input type='submit' value='Submit'>")
        conn:send("</form>")

        path = nil
        data = nil

    end)
    conn:on("sent",function(conn) conn:close() end)
end)
mpromonet
  • 11,326
  • 43
  • 62
  • 91
Kevin192291
  • 1,925
  • 4
  • 26
  • 43

2 Answers2

4

Your web browser is actually sending two requests.

The first contains your 'chk=on' to turn on the relay or nothing to turn your relay off.

The second header request is "GET /favicon.ico HTTP/1.1".
Your script is parsing both headers, since 'chk=on' is never found in the second header, the relay is switched off.

Your TCP server parses these as individual requests.

Example:

GET /chk=on HTTP/1.1 Host: 192.168.11.6 Connection: keep-alive Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,pt;q=0.6

GET /favicon.ico HTTP/1.1 Host: 192.168.11.6 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 Accept: / Referer: http://192.168.11.6/on Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8,pt;q=0.6

Try:
headertest = string.find(data, "favicon.ico")
if(headertest) dont parse.

And, not all browsers ask for a favicon.....

Bruce
  • 56
  • 4
1

The thing of it is, you may not necessarily get the whole request passed to the receive function in one call, it could get called multiple times for a single request. Closing the connection before receiving all of the request sends a RST to the client browser.

The best I have been able to do so far is look for a valid verb at the beginning of the data, and assume a.) that it will never need more than 2 calls to complete, and; b.) if there is no valid verb, it must be the second call.

It's a difficult scenario to code for, to be sure.

Mark McGinty
  • 756
  • 7
  • 13