rest-nvim / rest.nvim

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

Fix encoding query parameters #356

Closed daniilrozanov closed 2 months ago

daniilrozanov commented 2 months ago

Fixing #355.All of this happens when encode_url=true in setup config. Before this change all query in http://aaa.bbb/ccc?<query> gets encoded. Since plugin's treesitter does not support URLs like http://...?value , this behaviour seems pointless to me. Besides everything else it spoils = sign, replacing it to %3d. So, at least on my machine, the most basic test

GET https://reqres.in/api/users?page=6

is indifferent to value of page, so you can change it, response will be the same, and it will be the same as if you delete ?page=6 at all.

Some examples how echo server sees current requests with parameters: Request: GET https://echo.free.beeceptor.com/hi?x=1&y=2&df=привет Reply:

 {
    "method": "GET",
    "protocol": "https",
    "host": "echo.free.beeceptor.com",
    "path": "/hi?x%3d1%26y%3d2%26df%3d%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d1%82",
    "ip": "109.252.213.1",
   "headers": {
      "Host": "echo.free.beeceptor.com",
      "Accept": "*/*",
      "Accept-Encoding": "gzip"
    },
   "parsedQueryParams": {
      "x=1&y=2&df=привет": ""
    }
  }

Request: GET https://echo.free.beeceptor.com/some?a=1 Reply:

{
    "method": "GET",
    "protocol": "https",
    "host": "echo.free.beeceptor.com",
    "path": "/some?a%3d1",
    "ip": "109.252.213.1",
   "headers": {
      "Host": "echo.free.beeceptor.com",
      "Accept": "*/*",
      "Accept-Encoding": "gzip"
    },
   "parsedQueryParams": {
      "a=1": ""
    }
  }

Comparing to curl -G https://echo.free.beeceptor.com/some --data-urlencode "x=1" --data-urlencode "y=2" --data-urlencode "hello=привет", which gives

{
  "method": "GET",
  "protocol": "https",
  "host": "echo.free.beeceptor.com",
  "path": "/some?x=1&y=2&hello=%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d1%82",
  "ip": "109.252.213.1",
  "headers": {
    "Host": "echo.free.beeceptor.com",
    "User-Agent": "curl/8.4.0",
    "Accept": "*/*",
    "Accept-Encoding": "gzip"
  },
  "parsedQueryParams": {
    "x": "1",
    "y": "=",
    "hello": "привет"
  }
}

This fix aims to change this behaviour to more like curl's --data-urlencode works (see manual). This changes behaviour of encoding, so only value in key=value pairs of query will be changed. Currently, this works only with & separator.

This is what I noticed while writing the fix

Firstly, plugin have no tests with more than one query parameter, and no tests to validate if reply corresponds to request.

Secondly, as far as I understood, reading the URL manual, query string is unspecified, so instead of & delimiter it could be ; or any other, so splitting _url:get_query() by & does not cover all possible use cases (despite the fact that the vast majority use the query string as key=value&...). At least, this fix covers following curl's --data-urlencode patterns:

Summary. Because of query string is unspecified, and we don't know the rule how to encode it's parts, should we add some option so user can define encoding behaviour. It may be set in config or locally as request parameter (similar to 'host')?