keplerproject / wsapi

WSAPI is an API that abstracts the web server from Lua web applications.
http://keplerproject.github.io/wsapi
74 stars 33 forks source link

WSAPI doesn't parse truncated requests #22

Open edzius opened 11 years ago

edzius commented 11 years ago

Due to network timings (latency, heavy load) not all requests received in one peace. Those one who are not received in one peace (truncated) interpreted by wsapi as empty string. This is why wsapi must read until whole content length received or connection closed on other side.

Maybe my patch can help, take a look:

diff --git a/lua-modules/wsapi-1.6/src/wsapi/request.lua b/lua-modules/wsapi-1.6/src/wsapi/request.lua
index 15fa602..d4d1bbd 100644
--- a/lua-modules/wsapi-1.6/src/wsapi/request.lua
+++ b/lua-modules/wsapi-1.6/src/wsapi/request.lua
@@ -1,4 +1,5 @@
 local util = require"wsapi.util"
+local sockreader = require"wsapi.sockreader"

 local _M = {}

@@ -118,16 +119,11 @@ local function parse_post_data(wsapi_env, tab, overwrite)
   tab = tab or {}
   local input_type = wsapi_env.CONTENT_TYPE
   if string.find(input_type, "x-www-form-urlencoded", 1, true) then
-    local length = tonumber(wsapi_env.CONTENT_LENGTH) or 0
-    parse_qs(wsapi_env.input:read(length) or "", tab, overwrite)
+    parse_qs(sockreader.read_post_data(wsapi_env) or "", tab, overwrite)
   elseif string.find(input_type, "multipart/form-data", 1, true) then
-    local length = tonumber(wsapi_env.CONTENT_LENGTH) or 0
-    if length > 0 then
-       parse_multipart_data(wsapi_env.input:read(length) or "", input_type, tab, overwrite)
-    end
+    parse_multipart_data(sockreader.read_post_data(wsapi_env) or "", input_type, tab, overwrite)
   else
-    local length = tonumber(wsapi_env.CONTENT_LENGTH) or 0
-    tab.post_data = wsapi_env.input:read(length) or ""
+    tab.post_data = sockreader.read_post_data(wsapi_env) or ""
   end
   return tab
 end
diff --git a/lua-modules/wsapi-1.6/src/wsapi/sockreader.lua b/lua-modules/wsapi-1.6/src/wsapi/sockreader.lua
new file mode 100644
index 0000000..cdb3dc4
--- /dev/null
+++ b/lua-modules/wsapi-1.6/src/wsapi/sockreader.lua
@@ -0,0 +1,35 @@
+--
+-- Helper functions to read all data from socket correctly
+--
+
+local _M = {}
+
+function _M.read_all(input, length)
+
+       local response = ""
+       local count = length
+
+       while true do
+               if count <= 0 then
+                       break
+               end
+
+               local rv, err, part = input:read(count)
+               if err == "closed" then
+                       return nil, err
+               end
+
+               local data = rv or part
+               response = response .. data
+               count = count - #data
+       end
+
+       return response
+end
+
+function _M.read_post_data(wsapi_env)
+       local length = tonumber(wsapi_env.CONTENT_LENGTH) or 0
+       return _M.read_all(wsapi_env.input, length)
+end
+
+return _M

Those post read methods placed in separate file (sockreader.lua) due to i need exposed functions to manually read post payload in smaller chunks.