252 lines
7.5 KiB
VimL
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:
|