rest-nvim / rest.nvim

A fast Neovim http client written in Lua
GNU General Public License v3.0
1.61k stars 142 forks source link

Add pre-script configuration. #287

Closed hsanson closed 8 months ago

hsanson commented 9 months ago

Adds a new configuration option that allows to set a lua script that is executed before each request. This script receives the request opts (body, headers, url, etc.) and the environment variables.

This allows to dynamically modify the opts (body, headers, url, etc.) before executing the request. For example compute some signature based on the request body and some key to set the Authorization header etc.

NTBBloodbath commented 9 months ago

Hi, thanks for the PR. It looks like something interesting, could you give me some real world usage examples or use cases to fully understand why this would be good to have?

hsanson commented 9 months ago

@NTBBloodbath I have to deal with many REST APIs that use HMAC signatures to authorize requests. These signatures must be set in the Authorization header of the requests and computed using an encryption key (set via env variables), and the request content-type, date, URI path, and body. See api_auth ruby gem for details on how to compute this signature.

Using the pre-script I can compute the signature and set the appropriate Authorization header allowing me to use rest.nvim to work with these REST APIs.

hsanson commented 9 months ago

I achieve the same in Insomnia using plugins and in Postman using postman pre-scripts but I prefer staying inside neovim, therefore this PR. I am pretty sure there are many use-cases for this feature other than custom authorization schemes.

NTBBloodbath commented 8 months ago

Hey, sorry for the delay in accepting the changes.

I recently got a new kitten and I've been looking after him and making sure my other cat adjusts to him, a bit of hard work but they seem to get along well now haha, thank you very much for your time in explaining the use case and submitting the changes, I hope this will be very useful to other users too :)

Note: I have in mind to also implement post-request hooks so I think this initial implementation of a pre-script can be improved and refactored later so that it serves as a pre-request hook allowing several pre-scripts at the same time if necessary so this may change in a future release

NTBBloodbath commented 8 months ago

Note: this feature has been superseded by the pre-request hooks in the next release, which have had a great improvement in rest.nvim v2. The first table is before running the request and the hooks, and the second table is after running the hooks before running the request.

image

Here is a sample of the used code (can be defined anywhere):

vim.api.nvim_create_autocmd("User", {
  pattern = "RestStartRequest",
  callback = function()
    -- This is a temporal global variable that is set when running pre-request hooks
    _G._rest_nvim_req_data.headers["Content-Type"] = "application/json"
  end,
})

Note that it does not pass variables to the callback function as running the request will automatically load the environment variables from your .env file into the vim.env (e.g. vim.env.SECRET_KEY) metatable which also contains all the environment variables from your shell session.

hsanson commented 8 months ago

@NTBBloodbath I am trying to update my configuration to work with new v2 of the plugin but I am having troubles getting it to work. The problem is that the data received in the global _G._rest_nvim_req_data variable is not what is sent to CURL command. Below an example:

{
  body = {
    __TYPE = "json",
    id = "1072e7f1-398c-40ef-a3ec-5987a6f59286",
    job = "leader",
    name = "{{USERNAME}}"
  },
  end_ = 9,
  headers = {
    Authorization = "Bearer",
    ["Content-Type"] = "application/json"
  },
  request = {
    method = "POST",
    url = "{{HOST}}"
  },
  script = "",
  start = 0
}
  1. The url is not replaced with the actual URL and is left instead as {{HOST}}
  2. The body is an object instead of the text sent via curl to the server.
  3. I have not tested but can assume that headers the use env variables will also not be replaced with the actual values.

In order to support HMAC authentication (see Api-Auth) I need access to the request raw data as it is to be sent to curl.

  1. Replace all env variables in headers, url, body, etc before setting them in the _G._rest_nvim_req_data variable.
  2. Set body to the exact text being sent to curl command or add a body_raw field that contains it.