spacevim/autoload/SpaceVim/api/web/http.vim
JIe 2bb7059579
Some checks failed
Detach Plugins / check (FlyGrep.vim) (push) Has been cancelled
Detach Plugins / check (GitHub.vim) (push) Has been cancelled
Detach Plugins / check (JavaUnit.vim) (push) Has been cancelled
Detach Plugins / check (SourceCounter.vim) (push) Has been cancelled
Detach Plugins / check (cpicker.nvim) (push) Has been cancelled
Detach Plugins / check (dein-ui.vim) (push) Has been cancelled
Detach Plugins / check (git.vim) (push) Has been cancelled
Detach Plugins / check (iedit.vim) (push) Has been cancelled
Detach Plugins / check (scrollbar.vim) (push) Has been cancelled
Detach Plugins / check (vim-chat) (push) Has been cancelled
Detach Plugins / check (vim-cheat) (push) Has been cancelled
Detach Plugins / check (vim-todo) (push) Has been cancelled
Detach Plugins / check (xmake.vim) (push) Has been cancelled
test / Linux (nvim, nightly) (push) Has been cancelled
test / Linux (nvim, v0.3.8) (push) Has been cancelled
test / Linux (nvim, v0.4.0) (push) Has been cancelled
test / Linux (nvim, v0.4.2) (push) Has been cancelled
test / Linux (nvim, v0.4.3) (push) Has been cancelled
test / Linux (nvim, v0.4.4) (push) Has been cancelled
test / Linux (nvim, v0.5.0) (push) Has been cancelled
test / Linux (nvim, v0.5.1) (push) Has been cancelled
test / Linux (nvim, v0.6.0) (push) Has been cancelled
test / Linux (nvim, v0.6.1) (push) Has been cancelled
test / Linux (nvim, v0.7.0) (push) Has been cancelled
test / Linux (nvim, v0.7.2) (push) Has been cancelled
test / Linux (nvim, v0.8.0) (push) Has been cancelled
test / Linux (nvim, v0.8.1) (push) Has been cancelled
test / Linux (nvim, v0.8.2) (push) Has been cancelled
test / Linux (nvim, v0.8.3) (push) Has been cancelled
test / Linux (nvim, v0.9.0) (push) Has been cancelled
test / Linux (nvim, v0.9.1) (push) Has been cancelled
test / Linux (true, vim, v7.4.052) (push) Has been cancelled
test / Linux (true, vim, v7.4.1689) (push) Has been cancelled
test / Linux (true, vim, v7.4.629) (push) Has been cancelled
test / Linux (true, vim, v8.0.0027) (push) Has been cancelled
test / Linux (true, vim, v8.0.0183) (push) Has been cancelled
test / Linux (vim, nightly) (push) Has been cancelled
test / Linux (vim, v8.0.0184) (push) Has been cancelled
test / Linux (vim, v8.0.1453) (push) Has been cancelled
test / Linux (vim, v8.1.2269) (push) Has been cancelled
test / Linux (vim, v8.2.2434) (push) Has been cancelled
test / Linux (vim, v8.2.3995) (push) Has been cancelled
test / Windows (nvim, nightly) (push) Has been cancelled
test / Windows (nvim, v0.3.8) (push) Has been cancelled
test / Windows (nvim, v0.4.2) (push) Has been cancelled
test / Windows (nvim, v0.4.3) (push) Has been cancelled
test / Windows (nvim, v0.4.4) (push) Has been cancelled
test / Windows (nvim, v0.5.0) (push) Has been cancelled
test / Windows (nvim, v0.5.1) (push) Has been cancelled
test / Windows (nvim, v0.6.0) (push) Has been cancelled
test / Windows (nvim, v0.6.1) (push) Has been cancelled
test / Windows (nvim, v0.7.0) (push) Has been cancelled
test / Windows (nvim, v0.7.2) (push) Has been cancelled
test / Windows (nvim, v0.8.0) (push) Has been cancelled
test / Windows (nvim, v0.8.1) (push) Has been cancelled
test / Windows (nvim, v0.8.2) (push) Has been cancelled
test / Windows (nvim, v0.8.3) (push) Has been cancelled
test / Windows (nvim, v0.9.0) (push) Has been cancelled
test / Windows (nvim, v0.9.1) (push) Has been cancelled
test / Windows (vim, nightly) (push) Has been cancelled
test / Windows (vim, v7.4.1185) (push) Has been cancelled
test / Windows (vim, v7.4.1689) (push) Has been cancelled
test / Windows (vim, v8.0.0027) (push) Has been cancelled
test / Windows (vim, v8.0.1453) (push) Has been cancelled
test / Windows (vim, v8.1.2269) (push) Has been cancelled
test / Windows (vim, v8.2.2434) (push) Has been cancelled
test / Windows (vim, v8.2.3995) (push) Has been cancelled
docker / docker (push) Has been cancelled
mirror / check (coding) (push) Has been cancelled
mirror / check (gitee) (push) Has been cancelled
mirror / check (gitlab) (push) Has been cancelled
init
2024-08-21 14:17:26 +08:00

490 lines
15 KiB
VimL

"=============================================================================
" http.vim --- SpaceVim http API
" Copyright (c) 2016-2023 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
let s:self = {}
let s:system = function(get(g:, 'webapi#system_function', 'system'))
function! s:nr2byte(nr) abort
if a:nr < 0x80
return nr2char(a:nr)
elseif a:nr < 0x800
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
elseif a:nr < 0x10000
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
elseif a:nr < 0x200000
return nr2char(a:nr/262144%16+240).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
elseif a:nr < 0x4000000
return nr2char(a:nr/16777216%16+248).nr2char(a:nr/262144%16+128).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
else
return nr2char(a:nr/1073741824%16+252).nr2char(a:nr/16777216%16+128).nr2char(a:nr/262144%16+128).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
endif
endfunction
function! s:nr2enc_char(charcode) abort
if &encoding ==# 'utf-8'
return nr2char(a:charcode)
endif
let char = s:nr2byte(a:charcode)
if strlen(char) > 1
let char = strtrans(iconv(char, 'utf-8', &encoding))
endif
return char
endfunction
function! s:nr2hex(nr) abort
let n = a:nr
let r = ''
while n
let r = '0123456789ABCDEF'[n % 16] . r
let n = n / 16
endwhile
return r
endfunction
function! s:urlencode_char(c, ...) abort
let is_binary = get(a:000, 1)
let c = a:c
if !is_binary
let c = iconv(a:c, &encoding, 'utf-8')
if c ==# ''
let c = a:c
endif
endif
let s = ''
for i in range(strlen(c))
let s .= printf('%%%02X', char2nr(c[i]))
endfor
return s
endfunction
function! s:self.decodeURI(str) abort
let ret = a:str
let ret = substitute(ret, '+', ' ', 'g')
let ret = substitute(ret, '%\(\x\x\)', '\=printf("%c", str2nr(submatch(1), 16))', 'g')
return ret
endfunction
function! s:self.escape(str) abort
return substitute(a:str, '[^a-zA-Z0-9_.~/-]', '\=s:urlencode_char(submatch(0))', 'g')
endfunction
function! s:self.encodeURI(items, ...) abort
let is_binary = get(a:000, 1)
let ret = ''
if type(a:items) == 4
for key in sort(keys(a:items))
if strlen(ret) | let ret .= '&' | endif
let ret .= key . '=' . s:self.encodeURI(a:items[key])
endfor
elseif type(a:items) == 3
for item in sort(a:items)
if strlen(ret) | let ret .= '&' | endif
let ret .= item
endfor
else
let ret = substitute(a:items, '[^a-zA-Z0-9_.~-]', '\=s:urlencode_char(submatch(0), is_binary)', 'g')
endif
return ret
endfunction
function! s:self.encodeURIComponent(items) abort
let ret = ''
if type(a:items) == 4
for key in sort(keys(a:items))
if strlen(ret) | let ret .= '&' | endif
let ret .= key . '=' . s:self.encodeURIComponent(a:items[key])
endfor
elseif type(a:items) == 3
for item in sort(a:items)
if strlen(ret) | let ret .= '&' | endif
let ret .= item
endfor
else
let items = iconv(a:items, &enc, 'utf-8')
let len = strlen(items)
let i = 0
while i < len
let ch = items[i]
if ch =~# '[0-9A-Za-z-._~!''()*]'
let ret .= ch
elseif ch ==# ' '
let ret .= '+'
else
let ret .= '%' . substitute('0' . s:nr2hex(char2nr(ch)), '^.*\(..\)$', '\1', '')
endif
let i = i + 1
endwhile
endif
return ret
endfunction
function! s:self.get(url, ...) abort
let getdata = a:0 > 0 ? a:000[0] : {}
let headdata = a:0 > 1 ? a:000[1] : {}
let follow = a:0 > 2 ? a:000[2] : 1
let url = a:url
let getdatastr = self.encodeURI(getdata)
if strlen(getdatastr)
let url .= '?' . getdatastr
endif
if executable('curl')
let command = printf('curl -q %s -s -k -i', follow ? '-L' : '')
" let quote = &shellxquote ==# '"' ? "'" : '"'
" @fixme this line failed on windows
let quote = '"'
for key in keys(headdata)
if has('win32')
let command .= ' -H ' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' -H ' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' ' . quote . url . quote
let res = s:system(command)
elseif executable('wget')
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
" let quote = &shellxquote ==# '"' ? "'" : '"'
let quote = '"'
for key in keys(headdata)
if has('win32')
let command .= ' --header=' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' --header=' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' ' . quote . url . quote
let res = s:system(command)
else
throw 'require `curl` or `wget` command'
endif
if follow != 0
let mx = 'HTTP/\%(1\.[01]\|2\%(\.0\)\?\)'
while res =~# '^' . mx . ' 3' || res =~# '^' . mx . ' [0-9]\{3} .\+\n\r\?\n' . mx . ' .\+'
let pos = stridx(res, "\r\n\r\n")
if pos != -1
let res = strpart(res, pos+4)
else
let pos = stridx(res, "\n\n")
let res = strpart(res, pos+2)
endif
endwhile
endif
let pos = stridx(res, "\r\n\r\n")
if pos != -1
let content = strpart(res, pos+4)
else
let pos = stridx(res, "\n\n")
let content = strpart(res, pos+2)
endif
let header = split(res[:pos-1], '\r\?\n')
let matched = matchlist(get(header, 0), '^HTTP/\%(1\.[01]\|2\%(\.0\)\?\)\s\+\(\d\+\)\s*\(.*\)')
if !empty(matched)
let [status, message] = matched[1 : 2]
call remove(header, 0)
else
if v:shell_error || len(matched)
let [status, message] = ['500', "Couldn't connect to host"]
else
let [status, message] = ['200', 'OK']
endif
endif
return {
\ 'status' : status,
\ 'message' : message,
\ 'header' : header,
\ 'content' : content
\}
endfunction
function! s:self.post(url, ...) abort
let postdata = a:0 > 0 ? a:000[0] : {}
let headdata = a:0 > 1 ? a:000[1] : {}
let method = a:0 > 2 ? a:000[2] : 'POST'
let follow = a:0 > 3 ? a:000[3] : 1
let url = a:url
if type(postdata) == 4
let postdatastr = self.encodeURI(postdata)
else
let postdatastr = postdata
endif
let file = tempname()
if executable('curl')
let command = printf('curl -q %s -s -k -i -X %s', (follow ? '-L' : ''), len(method) ? method : 'POST')
let quote = &shellxquote ==# '"' ? "'" : '"'
for key in keys(headdata)
if has('win32')
let command .= ' -H ' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' -H ' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' ' . quote . url . quote
call writefile(split(postdatastr, "\n"), file, 'b')
let res = s:system(command . ' --data-binary @' . quote.file.quote)
elseif executable('wget')
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
let headdata['X-HTTP-Method-Override'] = method
let quote = &shellxquote ==# '"' ? "'" : '"'
for key in keys(headdata)
if has('win32')
let command .= ' --header=' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' --header=' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' '.quote.url.quote
call writefile(split(postdatastr, "\n"), file, 'b')
let res = s:system(command . ' --post-data @' . quote.file.quote)
else
throw 'require `curl` or `wget` command'
endif
call delete(file)
if follow != 0
let mx = 'HTTP/\%(1\.[01]\|2\%(\.0\)\?\)'
while res =~# '^' . mx . ' 3' || res =~# '^' . mx . ' [0-9]\{3} .\+\n\r\?\n' . mx . ' .\+'
let pos = stridx(res, "\r\n\r\n")
if pos != -1
let res = strpart(res, pos+4)
else
let pos = stridx(res, "\n\n")
let res = strpart(res, pos+2)
endif
endwhile
endif
let pos = stridx(res, "\r\n\r\n")
if pos != -1
let content = strpart(res, pos+4)
else
let pos = stridx(res, "\n\n")
let content = strpart(res, pos+2)
endif
let header = split(res[:pos-1], '\r\?\n')
let matched = matchlist(get(header, 0), '^HTTP/\%(1\.[01]\|2\%(\.0\)\?\)\s\+\(\d\+\)\s*\(.*\)')
if !empty(matched)
let [status, message] = matched[1 : 2]
call remove(header, 0)
else
if v:shell_error || len(matched)
let [status, message] = ['500', "Couldn't connect to host"]
else
let [status, message] = ['200', 'OK']
endif
endif
return {
\ 'status' : status,
\ 'message' : message,
\ 'header' : header,
\ 'content' : content
\}
endfunction
function! s:self.send(req) abort
let postdata = get(a:req, 'data', '')
let method = get(a:req, 'method', postdata ==# '' ? 'GET': 'POST')
let headdata = get(a:req, 'header', {})
let follow = get(a:req, 'follow', 1)
let url = get(a:req, 'url', '')
if type(postdata) == 4
let postdatastr = self.encodeURI(postdata)
else
let postdatastr = postdata
endif
if empty(postdatastr)
let file = ''
else
let file = tempname()
endif
if executable('curl')
let command = printf('curl -q %s -s -k -i -X %s', (follow ? '-L' : ''), len(method) ? method : 'POST')
let quote = &shellxquote ==# '"' ? "'" : '"'
for key in keys(headdata)
if has('win32')
let command .= ' -H ' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' -H ' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' ' . quote . url . quote
if file ==# ''
let res = s:system(command)
else
call writefile(split(postdatastr, "\n"), file, 'b')
let res = s:system(command . ' --data-binary @' . quote.file.quote)
call delete(file)
endif
elseif executable('wget')
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
let headdata['X-HTTP-Method-Override'] = method
let quote = &shellxquote ==# '"' ? "'" : '"'
for key in keys(headdata)
if has('win32')
let command .= ' --header=' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' --header=' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' '.quote.url.quote
if file ==# ''
let res = s:system(command)
else
call writefile(split(postdatastr, "\n"), file, 'b')
let res = s:system(command . ' --post-data @' . quote.file.quote)
call delete(file)
endif
else
throw 'require `curl` or `wget` command'
endif
if follow != 0
let mx = 'HTTP/\%(1\.[01]\|2\%(\.0\)\?\)'
while res =~# '^' . mx . ' 3' || res =~# '^' . mx . ' [0-9]\{3} .\+\n\r\?\n' . mx . ' .\+'
let pos = stridx(res, "\r\n\r\n")
if pos != -1
let res = strpart(res, pos+4)
else
let pos = stridx(res, "\n\n")
let res = strpart(res, pos+2)
endif
endwhile
endif
let pos = stridx(res, "\r\n\r\n")
if pos != -1
let content = strpart(res, pos+4)
else
let pos = stridx(res, "\n\n")
let content = strpart(res, pos+2)
endif
let header = split(res[:pos-1], '\r\?\n')
let matched = matchlist(get(header, 0), '^HTTP/\%(1\.[01]\|2\%(\.0\)\?\)\s\+\(\d\+\)\s*\(.*\)')
if !empty(matched)
let [status, message] = matched[1 : 2]
call remove(header, 0)
else
if v:shell_error || len(matched)
let [status, message] = ['500', "Couldn't connect to host"]
else
let [status, message] = ['200', 'OK']
endif
endif
return {
\ 'status' : status,
\ 'message' : message,
\ 'header' : header,
\ 'content' : content
\}
endfunction
function! s:self.stream(req) abort
let postdata = get(a:req, 'data', '')
let method = get(a:req, 'method', postdata ==# '' ? 'GET': 'POST')
let headdata = get(a:req, 'header', {})
let follow = get(a:req, 'follow', 1)
let url = get(a:req, 'url', '')
let mode = get(a:req, 'mode', 'nl')
if type(postdata) == 4
let postdatastr = self.encodeURI(postdata)
else
let postdatastr = postdata
endif
if empty(postdatastr)
let file = ''
else
let file = tempname()
endif
if executable('curl')
let command = printf('curl -q %s -s -k -X %s', (follow ? '-L' : ''), len(method) ? method : 'POST')
let quote = &shellxquote ==# '"' ? "'" : '"'
for key in keys(headdata)
if has('win32')
let command .= ' -H ' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' -H ' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' '.quote . url . quote
if file ==# ''
let job = job_start(command)
else
call writefile(split(postdatastr, "\n"), file, 'b')
let job = job_start(command . ' --data-binary @' . quote.file.quote)
call delete(file)
endif
elseif executable('wget')
let command = printf('wget -O- -q %s', follow ? '-L' : '')
let headdata['X-HTTP-Method-Override'] = method
let quote = &shellxquote ==# '"' ? "'" : '"'
for key in keys(headdata)
if has('win32')
let command .= ' --header=' . quote . key . ': ' . substitute(headdata[key], '"', '"""', 'g') . quote
else
let command .= ' --header=' . quote . key . ': ' . headdata[key] . quote
endif
endfor
let command .= ' '.quote.url.quote
if file ==# ''
let job = job_start(command)
else
call writefile(split(postdatastr, "\n"), file, 'b')
let job = job_start(command . ' --post-data @' . quote.file.quote)
call delete(file)
endif
else
throw 'require `curl` or `wget` command'
endif
call job_setoptions(job,
\{
\ 'exit_cb': function('webapi#http#exit_cb', [a:req]),
\ 'stoponexit': 'kill',
\})
let a:req['job'] = job
let channel = job_getchannel(job)
call ch_setoptions(channel,
\{
\ 'out_cb': function('webapi#http#out_cb', [a:req]),
\ 'mode': mode,
\})
let a:req['channel'] = channel
let a:req['file'] = file
endfunction
" @vimlint(EVL103, 1, a:job)
function! s:self.exit_cb(req, job, code) abort
let file = get(a:req, 'file')
if file !=# ''
call delete(file)
endif
let fexit_cb = get(a:req, 'exit_cb', v:none)
if fexit_cb != v:none
call call(fexit_cb, [a:code])
endif
endfunction
" @vimlint(EVL103, 0, a:job)
" @vimlint(EVL103, 1, a:ch)
function! s:self.out_cb(req, ch, data) abort
let fout_cb = get(a:req, 'out_cb', v:none)
if fout_cb != v:none
call Fout_cb(a:data)
call call(fout_cb, [a:data])
endif
endfunction
" @vimlint(EVL103, 0, a:ch)
function! SpaceVim#api#web#http#get() abort
return deepcopy(s:self)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et: