dotfiles/vim/bundle/webapi-vim/autoload/webapi/http.vim

252 lines
7.5 KiB
VimL

" http
" Last Change: 2010-09-10
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
" License: This file is placed in the public domain.
" Reference:
let s:save_cpo = &cpo
set cpo&vim
let s:system = function(get(g:, 'webapi#system_function', 'system'))
function! s:nr2byte(nr)
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)
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)
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)
let utf = iconv(a:c, &encoding, "utf-8")
if utf == ""
let utf = a:c
endif
let s = ""
for i in range(strlen(utf))
let s .= printf("%%%02X", char2nr(utf[i]))
endfor
return s
endfunction
function! webapi#http#decodeURI(str)
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! webapi#http#escape(str)
return substitute(a:str, '[^a-zA-Z0-9_.~/-]', '\=s:urlencode_char(submatch(0))', 'g')
endfunction
function! webapi#http#encodeURI(items)
let ret = ''
if type(a:items) == 4
for key in sort(keys(a:items))
if strlen(ret) | let ret .= "&" | endif
let ret .= key . "=" . webapi#http#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))', 'g')
endif
return ret
endfunction
function! webapi#http#encodeURIComponent(items)
let ret = ''
if type(a:items) == 4
for key in sort(keys(a:items))
if strlen(ret) | let ret .= "&" | endif
let ret .= key . "=" . webapi#http#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! webapi#http#get(url, ...)
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 = webapi#http#encodeURI(getdata)
if strlen(getdatastr)
let url .= "?" . getdatastr
endif
if executable('curl')
let command = printf('curl %s -s -k -i', follow ? '-L' : '')
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
let res = s:system(command)
elseif executable('wget')
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
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
let res = s:system(command)
else
throw "require `curl` or `wget` command"
endif
if follow != 0
while res =~ '^HTTP/1.\d 3' || res =~ '^HTTP/1\.\d 200 Connection established' || res =~ '^HTTP/1\.\d 100 Continue'
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
return {
\ "header" : split(res[:pos-1], '\r\?\n'),
\ "content" : content
\}
endfunction
function! webapi#http#post(url, ...)
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 = webapi#http#encodeURI(postdata)
else
let postdatastr = postdata
endif
let file = tempname()
if executable('curl')
let command = printf('curl %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
while res =~ '^HTTP/1.\d 3' || res =~ '^HTTP/1\.\d 200 Connection established' || res =~ '^HTTP/1\.\d 100 Continue'
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
return {
\ "header" : split(res[:pos-1], '\r\?\n'),
\ "content" : content
\}
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et: