Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(form): fix binary multipart-form-data #230

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions docs/docs/usage/sending-form-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,36 @@ name={{name}}&
age={{age}}
```

## Sending multipart form data

You can send multipart form data in Kulala by using the `multipart/form-data` content type.

```http title="multipart.http"
# @file-to-variable LOGO_FILE_VAR ./../../logo.png
POST https://httpbin.org/post HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary{{$timestamp}}

------WebKitFormBoundary{{$timestamp}}
Content-Disposition: form-data; name="logo"; filename="logo.png"
Content-Type: image/jpeg

{{LOGO_FILE_VAR}}

------WebKitFormBoundary{{$timestamp}}
Content-Disposition: form-data; name="x"

0
------WebKitFormBoundary{{$timestamp}}
Content-Disposition: form-data; name="y"

1.4333333333333333
------WebKitFormBoundary{{$timestamp}}
Content-Disposition: form-data; name="w"

514.5666666666667
------WebKitFormBoundary{{$timestamp}}
Content-Disposition: form-data; name="h"

514.5666666666667
------WebKitFormBoundary{{$timestamp}}--
```
10 changes: 8 additions & 2 deletions lua/kulala/parser/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ local function extend_document_variables(document_variables, request)
local kv = vim.split(metadata.value, " ")
local variable_name = kv[1]
local file_path = kv[2]
file_path = FS.get_file_path(file_path)
local file_contents = FS.read_file(file_path)
if file_contents then
document_variables[variable_name] = file_contents
Expand Down Expand Up @@ -574,8 +575,13 @@ function M.parse(start_request_linenr)
res.headers["content-type"] = "application/json"
end
elseif res.headers["content-type"]:find("^multipart/form%-data") then
table.insert(res.cmd, "--data-binary")
table.insert(res.cmd, res.body)
local tmp_file = FS.get_binary_temp_file(res.body)
if tmp_file ~= nil then
table.insert(res.cmd, "--data-binary")
table.insert(res.cmd, "@" .. tmp_file)
else
Logger.error("Failed to create a temporary file for the binary request body")
end
else
table.insert(res.cmd, "--data")
table.insert(res.cmd, res.body)
Expand Down
32 changes: 32 additions & 0 deletions lua/kulala/utils/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ M.join_paths = function(...)
return table.concat({ ... }, M.ps)
end

---Returns true if the path is absolute, false otherwise
M.is_absolute_path = function(path)
if path:match("^/") or path:match("^%a:\\") then
return true
end
return false
end

---Either returns the absolute path if the path is already absolute or
---joins the path with the current buffer directory
M.get_file_path = function(path)
if M.is_absolute_path(path) then
return path
end
local buffer_dir = vim.fn.expand("%:p:h")
if path:sub(1, 2) == "./" or path:sub(1, 2) == ".\\" then
path = path:sub(3)
end
return M.join_paths(buffer_dir, path)
end

-- This is mainly used for determining if the current buffer is a non-http file
-- and therefore maybe we need to parse a fenced code block
M.is_non_http_file = function()
Expand Down Expand Up @@ -232,6 +253,17 @@ M.read_file = function(filename)
return content
end

M.get_binary_temp_file = function(content)
local tmp_file = vim.fn.tempname()
local f = io.open(tmp_file, "wb")
if f == nil then
return nil
end
f:write(content)
f:close()
return tmp_file
end

---Read file lines
---@param filename string
---@return string[]
Expand Down