Skip to content

WSAPI doesn't parse truncated requests #22

@edzius

Description

@edzius

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions