mirror of
https://github.com/neovim/neovim.git
synced 2026-04-19 14:00:49 +00:00
feat(vim.net): custom request() headers #38837
Problem Cannot specify headers in vim.net.request() call. Solution Support opts.headers in vim.net.request opts.
This commit is contained in:
@@ -4220,6 +4220,11 @@ vim.net.request({url}, {opts}, {on_response}) *vim.net.request()*
|
||||
outbuf = 0,
|
||||
})
|
||||
job:close()
|
||||
|
||||
-- Add custom headers in the request
|
||||
vim.net.request('https://neovim.io/charter/', {
|
||||
headers = { Authorization = 'Bearer XYZ' },
|
||||
})
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
@@ -4232,6 +4237,11 @@ vim.net.request({url}, {opts}, {on_response}) *vim.net.request()*
|
||||
body to.
|
||||
• {outbuf}? (`integer`) Buffer to save the response
|
||||
body to.
|
||||
• {headers}? (`table<string, string>`) Table of custom
|
||||
headers to send with the request. Supports basic
|
||||
key/value header formats and empty headers as
|
||||
supported by curl. Does not support @filename style,
|
||||
internal header deletion (e.g: 'Header:').
|
||||
• {on_response} (`fun(err: string?, response: vim.net.request.Response?)?`)
|
||||
Callback invoked on request completion. The `body`
|
||||
field in the response parameter contains the raw
|
||||
|
||||
@@ -63,6 +63,9 @@ API
|
||||
• |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|, |vim.lsp.buf.definition()|,
|
||||
and |vim.lsp.buf.implementation()| now follows 'switchbuf'.
|
||||
|
||||
• |vim.net.request()| opts field now accepts a headers table, with custom
|
||||
header support.
|
||||
|
||||
BUILD
|
||||
|
||||
• todo
|
||||
|
||||
@@ -14,6 +14,11 @@ local M = {}
|
||||
---
|
||||
---Buffer to save the response body to.
|
||||
---@field outbuf? integer
|
||||
---
|
||||
---Table of custom headers to send with the request.
|
||||
---Supports basic key/value header formats and empty headers as supported by curl.
|
||||
---Does not support @filename style, internal header deletion (e.g: 'Header:').
|
||||
---@field headers? table<string, string>
|
||||
|
||||
---@class vim.net.request.Response
|
||||
---
|
||||
@@ -47,6 +52,11 @@ local M = {}
|
||||
--- outbuf = 0,
|
||||
--- })
|
||||
--- job:close()
|
||||
---
|
||||
--- -- Add custom headers in the request
|
||||
--- vim.net.request('https://neovim.io/charter/', {
|
||||
--- headers = { Authorization = 'Bearer XYZ' },
|
||||
--- })
|
||||
--- ```
|
||||
---
|
||||
--- @param url string The URL for the request.
|
||||
@@ -76,6 +86,25 @@ function M.request(url, opts, on_response)
|
||||
vim.list_extend(args, { '--output', opts.outpath })
|
||||
end
|
||||
|
||||
if opts.headers then
|
||||
vim.validate('opts.headers', opts.headers, 'table', true)
|
||||
for key, value in pairs(opts.headers) do
|
||||
if type(key) ~= 'string' or type(value) ~= 'string' then
|
||||
error('headers keys and values must be strings')
|
||||
end
|
||||
|
||||
if key:match(':$') or key:match(';$') or key:match('^@') then
|
||||
error('header keys must not start with @ or end with : and ;')
|
||||
end
|
||||
|
||||
if value == '' then
|
||||
vim.list_extend(args, { '-H', key .. ';' })
|
||||
else
|
||||
vim.list_extend(args, { '-H', key .. ': ' .. value })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(args, url)
|
||||
|
||||
local job = vim.system(args, {}, function(res)
|
||||
|
||||
@@ -11,6 +11,15 @@ local function assert_404_error(err)
|
||||
)
|
||||
end
|
||||
|
||||
local function assert_wrong_headers(expected_err, header)
|
||||
local err = t.pcall_err(exec_lua, [[
|
||||
return vim.net.request('https://example.com', {
|
||||
headers = ]] .. header .. [[,
|
||||
}, function() end)
|
||||
]])
|
||||
t.matches(expected_err, err)
|
||||
end
|
||||
|
||||
describe('vim.net.request', function()
|
||||
before_each(function()
|
||||
n:clear()
|
||||
@@ -163,4 +172,55 @@ describe('vim.net.request', function()
|
||||
t.eq(false, rv.modified)
|
||||
t.eq(true, rv.zipfile)
|
||||
end)
|
||||
|
||||
it('accepts custom headers', function()
|
||||
t.skip(skip_integ, 'NVIM_TEST_INTEG not set: skipping network integration test')
|
||||
|
||||
local headers = exec_lua([[
|
||||
local done = false
|
||||
local result
|
||||
|
||||
vim.net.request("https://httpbingo.org/headers", {
|
||||
headers = {
|
||||
Authorization = "Bearer test-token",
|
||||
['X-Custom-Header'] = "custom-value",
|
||||
['Empty'] = '',
|
||||
},
|
||||
}, function(err, res)
|
||||
if err then
|
||||
result = { error = err }
|
||||
else
|
||||
result = vim.json.decode(res.body).headers
|
||||
end
|
||||
done = true
|
||||
end)
|
||||
|
||||
vim.wait(2000, function() return done end)
|
||||
return result
|
||||
]])
|
||||
|
||||
assert.is_table(headers)
|
||||
-- httpbingo.org/request returns each header as a list in the returned value
|
||||
t.eq(headers.Authorization[1], 'Bearer test-token', 'Expected Authorization header')
|
||||
t.eq(headers['X-Custom-Header'][1], 'custom-value', 'Expected X-Custom-Header')
|
||||
t.eq(headers['Empty'][1], '', 'Expected Empty header')
|
||||
end)
|
||||
|
||||
it('validation', function()
|
||||
assert_wrong_headers('opts.headers: expected table, got number', '123')
|
||||
assert_wrong_headers('headers keys and values must be strings', "{ [123] = 'value' }")
|
||||
assert_wrong_headers('headers keys and values must be strings', '{ Header = 123 }')
|
||||
assert_wrong_headers(
|
||||
'header keys must not start with @ or end with : and ;',
|
||||
"{ ['Header:'] = 'value' }"
|
||||
)
|
||||
assert_wrong_headers(
|
||||
'header keys must not start with @ or end with : and ;',
|
||||
"{ ['Header;'] = 'value' }"
|
||||
)
|
||||
assert_wrong_headers(
|
||||
'header keys must not start with @ or end with : and ;',
|
||||
"{ ['@filename'] = '' }"
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user