emaxedon Posted February 27, 2018 Share Posted February 27, 2018 I've created a server in my driver using C4.CreateServer. The OnServerDataIn function is invoked when the director receives data on the port. Right now I'm sending it a HTTP POST request, but don't know how to extract only the body from the "strData". --[[ Invoked by Director when data comes in on an open Server Socket. ]] function OnServerDataIn(nHandle, strData, strClientAddress, strPort) -- TODO: Parse body of POST from strData end Right now when I send it a POST request that looks like: POST / HTTP/1.1 Content-type:text/plain host:example.com content-length:5 test strData always looks like: POST / HTTP/1.1Content-type:text/plainhost:example.comcontent-length:5test Does Control4 strip out the \r\n from the POST request? Link to comment Share on other sites More sharing options...
RyanE Posted February 28, 2018 Share Posted February 28, 2018 No, but printing it might. You can likely see the entire query if you do a hexdump with the data... function OnServerDataIn(nHandle, strData, strClientAddress, strPort) hexdump(strData) end You end up seeing your header, then 0d 0a 0d 0a, then your data: 00000000 50 4F 53 54 20 2F 20 48 54 54 50 2F 31 2E 30 0D POST / HTTP/1.0. 00000010 0A 55 73 65 72 2D 41 67 65 6E 74 3A 20 63 75 72 .User-Agent: cur 00000020 6C 2F 37 2E 33 35 2E 30 0D 0A 48 6F 73 74 3A 20 l/7.35.0..Host: 00000030 31 39 32 2E 31 36 38 2E 32 39 2E 31 30 3A 38 37 192.168.29.10:87 00000040 36 35 0D 0A 41 63 63 65 70 74 3A 20 2A 2F 2A 0D 65..Accept: */*. 00000050 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67 74 68 3A .Content-Length: 00000060 20 34 0D 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 65 4..Content-Type 00000070 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 78 2D : application/x- 00000080 77 77 77 2D 66 6F 72 6D 2D 75 72 6C 65 6E 63 6F www-form-urlenco 00000090 64 65 64 0D 0A 56 69 61 3A 20 31 2E 31 20 70 66 ded..Via: 1.1 pf 000000A0 73 65 6E 73 65 3A 33 31 32 38 20 28 73 71 75 69 sense:3128 (squi 000000B0 64 2F 32 2E 37 2E 53 54 41 42 4C 45 39 29 0D 0A d/2.7.STABLE9).. 000000C0 58 2D 46 6F 72 77 61 72 64 65 64 2D 46 6F 72 3A X-Forwarded-For: 000000D0 20 31 39 32 2E 31 36 38 2E 32 39 2E 31 38 0D 0A 192.168.29.18.. 000000E0 43 61 63 68 65 2D 43 6F 6E 74 72 6F 6C 3A 20 6D Cache-Control: m 000000F0 61 78 2D 61 67 65 3D 32 35 39 32 30 30 0D 0A 43 ax-age=259200..C 00000100 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D onnection: keep- 00000110 61 6C 69 76 65 0D 0A 0D 0A alive.... 00000000 62 6C 61 68 blah If you'll notice, in this case, you're getting *2* calls to OnServerDataIn (notice the address where 'blah' starts is 00000000)... That means you need to buffer all the data you've gotten until you get it all, then the easiest way is to use a pattern match to get the data out. Something like this: function OnServerDataIn(nHandle, strData, strClientAddress, strPort) -- Make a buffer for every handle that comes in... gBuf = gBuf or {} gBuf[nHandle] = gBuf[nHandle] or "" gBuf[nHandle] = gBuf[nHandle] .. strData -- You really should check the header to make sure you have the entire Content-Length, but I am going to just assume -- that my data will all be there within a half a second after the data starts coming... -- This will probably break if you have large data packets... C4:SetTimer(500, function() if (gBuf[nHandle]) then local _, _, data = gBuf[nHandle]:find("\r\n\r\n(.+)") gBuf[nHandle] = nil -- clear buffer, otherwise memory leak... UseMyData(data) end end ) end function UseMyData(postData) -- Here's where you'll use that posted data... print("Post Data: " .. postData) end Good luck with it. RyanE Link to comment Share on other sites More sharing options...
RyanE Posted February 28, 2018 Share Posted February 28, 2018 OK, here's a better implementation that uses Content-Length if it exists: function OnServerDataIn(nHandle, strData, strClientAddress, strPort) gBuf = gBuf or {} -- Make a buffer for every handle that comes in... gBuf[nHandle] = (gBuf[nHandle] or "") .. strData HEADER_WHITESPACE = "\r\n\r\n" CONTENT_LENGTH_HEADER = "Content%-Length: " if (gBuf[nHandle]:find(CONTENT_LENGTH_HEADER)) then local _, _, content_len = gBuf[nHandle]:find(CONTENT_LENGTH_HEADER .. "(%d+)%s") local _, header_end = gBuf[nHandle]:find(HEADER_WHITESPACE) if (string.len(gBuf[nHandle]) >= header_end + content_len) then -- Found full Content... local _, _, data = gBuf[nHandle]:find(HEADER_WHITESPACE .. "(.+)") gBuf[nHandle] = nil -- clear buffer, otherwise memory leak... UseMyData(data) C4:ServerCloseClient(nHandle) end else -- No Content-Length header found, grab data after a couple of seconds... C4:SetTimer(2000, function() -- Check if the buffer still exists... if (gBuf[nHandle]) then local _, _, data = gBuf[nHandle]:find(HEADER_WHITESPACE .. "(.+)") gBuf[nHandle] = nil -- clear buffer, otherwise memory leak... UseMyData(data or "") C4:ServerCloseClient(nHandle) end end ) end end function UseMyData(postData) print("Post Data: " .. postData) end BTW, I'm not checking to see if I have a valid header_end. That's likely a bug that may bite you if you have a lot of headers. I'll leave that as an exercise to the reader to fix. I'm also not sending an HTTP reply. Baaaad Laaama! RyanE Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.