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

Feature: export Requests to cURL commands #534

Open
1 task done
sahaj-b opened this issue Feb 20, 2025 · 3 comments
Open
1 task done

Feature: export Requests to cURL commands #534

sahaj-b opened this issue Feb 20, 2025 · 3 comments
Labels
enhancement New feature or request

Comments

@sahaj-b
Copy link

sahaj-b commented Feb 20, 2025

Issues

  • I have checked existing issues and there are no existing ones with the same request.

Feature description

It would be great to have an option to export requests from a .http file to a cURL command format, similar to the functionality provided by the intelij Idea HTTP client.

As many clients like Postman supports importing curl commands, this can allow converting .http files as collections for other clients with scripts, thus can be shared

Would be cool if we can import curl commands as .http files too

@sahaj-b sahaj-b added the enhancement New feature or request label Feb 20, 2025
@boltlessengineer
Copy link
Contributor

Exporting http to curl command format is already builtin as experimental :Rest curl yank and :Rest curl comment commands.
For importing curl commands as http format, #415 might address that issue (I haven't work on it for a while, but I'll get back to it soon)

@sahaj-b
Copy link
Author

sahaj-b commented Feb 22, 2025

Made this script for converting the whole file into curl commands, utilizing rest-nvim.client.curl.cli command builder

Script
local function getEnvVars()
  local dotenv = require("rest-nvim.parser.dotenv")
  local env_file = vim.b._rest_nvim_env_file
  local envVars = {}
  if env_file then
    local ok, vars = dotenv.parse(env_file)
    if ok then
      envVars = vars
    else
      vim.schedule(function()
        vim.notify("Failed to load environment file: " .. env_file, vim.log.levels.WARN)
      end)
    end
  end
  return envVars
end

local function applySubstitutions(lines, useEnvVars)
  if useEnvVars then
    local env = getEnvVars()
    if env then
      for i, line in ipairs(lines) do
        for k, v in pairs(env) do
          line = line:gsub("{{" .. k .. "}}", v)
        end
        lines[i] = line
      end
    end
  else
    for i, line in ipairs(lines) do
      -- escape brackets so the request parser doesn't remove them
      line = line:gsub("{{", "\\{\\{"):gsub("}}", "\\}\\}")
      lines[i] = line
    end
  end
  return lines
end

local function extractCurlCommands(useEnvVars, format)
  local parser = require("rest-nvim.parser")
  local builder = require("rest-nvim.client.curl.cli").builder

  local originalBuf = vim.api.nvim_get_current_buf()
  local originalLines = vim.api.nvim_buf_get_lines(originalBuf, 0, -1, false)

  vim.cmd("vnew")
  local scratchBuf = vim.api.nvim_get_current_buf()

  local modifiedLines = applySubstitutions(originalLines, useEnvVars)
  vim.api.nvim_buf_set_lines(scratchBuf, 0, -1, false, modifiedLines)

  local nodes = parser.get_all_request_nodes()
  print("Extracting " .. #nodes .. " requests to curl commands")
  local output = {}

  for _, node in ipairs(nodes) do
    local request = parser.parse(node, 0)
    request.cookies = {}

    if request.body and request.body.__TYPE == "json" and (not request.headers or not request.headers["content-type"]) then
      request.headers = request.headers or {}
      request.headers["content-type"] = { "application/json" }
    end

    table.insert(output, "# " .. request.name)
    local curlCmd = builder.build_command(request)
    curlCmd = curlCmd:gsub("%-sL", "-L")
    if not useEnvVars then
      -- revert the escaping for the final output.
      curlCmd = curlCmd:gsub("\\{\\{", "{{"):gsub("\\}\\}", "}}")
    end

    if format then
      for _, line in ipairs(vim.split(curlCmd, "\n", true)) do
        table.insert(output, line)
      end
    else
      curlCmd = curlCmd:gsub("\n", " ")
      table.insert(output, curlCmd)
    end
    table.insert(output, "")
  end

  -- replace scratchpad content with the curl commands
  vim.api.nvim_buf_set_lines(scratchBuf, 0, -1, false, output)
  vim.bo.filetype = "sh"
end

vim.api.nvim_create_user_command("ExtractCommands", function(opts)
  local unformatted = (opts.args == "compact")
  extractCurlCommands(true, not unformatted)
end, { nargs = "?" })

vim.api.nvim_create_user_command("ExtractCommandsVar", function(opts)
  local unformatted = (opts.args == "compact")
  extractCurlCommands(false, not unformatted)
end, { nargs = "?" })
Example usage:

:ExtractCommands -> extracts all curl commands (formatted json) with variables replaced
:ExtractCommandsVar compact-> extracts all curl commands (without formatting) without variable substitution

I couldn't get rest-nvim.parser to automatically replace environment variables, I think it's because I don't pass the context argument to the parser, and I don't know how to get the current context

The output can be used to convert to, for example, postman collections with multiple-curl-to-postman

@sahaj-b
Copy link
Author

sahaj-b commented Feb 22, 2025

Workaround for importing curl format to http: see the bash script curlToHttp.sh mentioned here #144 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants