1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

move all vlib modules to vlib/

This commit is contained in:
Alexander Medvednikov
2019-06-29 11:54:29 +02:00
parent bdcbcb075b
commit 4594d78bd6
62 changed files with 6 additions and 5 deletions

56
vlib/http/download_mac.v Normal file
View File

@ -0,0 +1,56 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module http
import os
type downloadfn fn (written int)
type download_finished_fn fn ()
struct DownloadStruct {
mut:
stream voidptr
written int
cb downloadfn
}
fn download_cb(ptr voidptr, size, nmemb size_t, userp voidptr) int {
mut data := &DownloadStruct(userp)
written := C.fwrite(ptr, size, nmemb, data.stream)
data.written += written
#data->cb(data->written); // TODO
return written
}
fn download_file_with_progress(url, out string, cb, cb_finished download_finished_fn) {
curl := C.curl_easy_init()
if isnil(curl) {
return
}
cout := out.cstr()
fp := C.fopen(cout, 'wb')
C.curl_easy_setopt(curl, CURLOPT_URL, url.cstr())
C.curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_cb)
data := &DownloadStruct {
stream:fp
cb: cb
}
C.curl_easy_setopt(curl, CURLOPT_WRITEDATA, data)
mut d := 0.0
C.curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)
C.curl_easy_perform(curl)
C.curl_easy_cleanup(curl)
C.fclose(fp)
#cb_finished(); // TODO
}
fn download_file(url, out string) {
download_file_with_progress(url, out, empty, empty)
}
fn empty() {
}

22
vlib/http/download_win.v Normal file
View File

@ -0,0 +1,22 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module http
fn download_file_with_progress(url, out string, cb, cb_finished voidptr) {
}
fn download_file(url, out string) {
# HRESULT res = URLDownloadToFile(NULL, url.str, out.str, 0, NULL);
# if(res == S_OK) {
println('Download Ok')
# } else if(res == E_OUTOFMEMORY) {
println('Buffer length invalid, or insufficient memory')
# } else if(res == INET_E_DOWNLOAD_FAILURE) {
println('URL is invalid')
# } else {
# printf("Download error: %d\n", res);
# }
}

94
vlib/http/http.v Normal file
View File

@ -0,0 +1,94 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module http
struct Request {
pub:
// headers []string
headers map_string
method string
// cookies map[string]string
h string
cmd string
typ string // GET POST
data string
url string
ws_func voidptr
user_ptr voidptr
verbose bool
}
struct Response {
pub:
body string
headers map_string
status_code int
}
// embed 'http'
pub fn get(url string) string {
if url == '' {
println('http: empty get url')
return ''
}
mut req := new_request('GET', url, '')
resp := req.do()
return resp.body
}
pub fn post(url, data string) string {
req := new_request('POST', url, data)
resp := req.do()
return resp.body
}
pub fn new_request(typ, _url, _data string) *Request {
mut url := _url
mut data := _data
// req.headers['User-Agent'] = 'V $VERSION'
if typ == 'GET' && !url.contains('?') && data != '' {
println('zeroing data, to url')
url = '$url?$data'
data = ''
}
// req.headers = new_map(0, sizeof(string))// []string{}
return &Request {
typ: typ
url: _url
data: _data
ws_func: 0
user_ptr: 0
headers: new_map(0, sizeof(string))
}
}
/*
fn (req &Request) do() Response {
mut resp := Response{}
return resp
}
*/
fn (req mut Request) free() {
req.headers.free()
}
fn (resp mut Response) free() {
resp.headers.free()
}
pub fn (req mut Request) add_header(key, val string) {
// println('start add header')
// println('add header "$key" "$val"')
// println(key)
// println(val)
// h := '$key: $val'
// println('SET H')
// req.headers << h
req.headers[key] = val
// mut h := req.h
// h += ' -H "${key}: ${val}" '
// req.h = h
}

207
vlib/http/http_mac.v Normal file
View File

@ -0,0 +1,207 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module http
#include <curl/curl.h>
#flag darwin -lcurl
#flag windows -lcurl
#flag linux -lcurl
fn C.curl_easy_init() *C.CURL
fn foo() {}
type wsfn fn (s string, ptr voidptr)
struct MemoryStruct {
size size_t
ws_func wsfn
user_ptr voidptr // for wsfn
strings []string
}
import const (
CURLOPT_WRITEFUNCTION
CURLOPT_SSL_VERIFYPEER
CURLOPT_HEADERFUNCTION
CURLOPT_WRITEDATA
CURLOPT_HEADERDATA
CURLOPT_FOLLOWLOCATION
CURLOPT_URL
CURLOPT_VERBOSE
CURLOPT_HTTP_VERSION
CURL_HTTP_VERSION_1_1
CURLOPT_HTTPHEADER
CURLOPT_POSTFIELDS
CURLOPT_CUSTOMREQUEST
CURLOPT_TCP_KEEPALIVE
CURLINFO_CONTENT_LENGTH_DOWNLOAD
CURLE_OK
)
fn C.curl_easy_strerror(curl voidptr) byteptr
fn C.curl_easy_perform(curl voidptr) C.CURLcode
fn write_fn(contents byteptr, size, nmemb int, _mem *MemoryStruct) int {
mut mem := _mem
// # printf("size =%d nmemb=%d contents=%s\n", size, nmemb, contents);
realsize := size * nmemb// TODO size_t ?
// if !isnil(mem.ws_func) {
# if (mem->ws_func)
{
C.printf('\n\nhttp_mac.m: GOT WS FUNC. size=%d\n', realsize)
// Skip negative and 0 junk chars in the WS string
mut start := 0
for i := 0; i < realsize; i++ {
// printf("char=%d %c\n", s[i], s[i]);
if contents[i] == 0 && start == 0 {
start = i
break
}
}
contents += start + 1
// printf("GOOD CONTEnTS=%s\n", contents);
s := string(contents)
// mem.ws_func('kek', 0)
# mem->ws_func(s, mem->user_ptr);
}
mut c := string(contents)
c = c.trim_space()
// Need to clone because libcurl reuses this memory
mem.strings << c.clone()
return realsize
}
struct C.curl_slist { }
fn (req &Request) do() Response {
//println('req.do() mac/linux url="$req.url" data="$req.data"')
// println('req.do() url="$req.url"')
/*
mut resp := Response {
headers: map[string]string{}
}
*/
mut headers := map[string]string{}
// no data at this point
chunk := MemoryStruct {
ws_func: req.ws_func
user_ptr: req.user_ptr
}
// header chunk
hchunk := MemoryStruct {
ws_func: 0
user_ptr: 0
}
// init curl
curl := C.curl_easy_init()
if isnil(curl) {
println('curl init failed')
return Response{}
}
// options
// url2 := req.url.clone()
C.curl_easy_setopt(curl, CURLOPT_URL, req.url.cstr())// ..clone())
// C.curl_easy_setopt(curl, CURLOPT_URL, 'http://example.com')
// return resp
// curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
$if windows {
C.curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0)
}
C.curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn)
C.curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_fn)
C.curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk)
C.curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hchunk)
C.curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1)
if req.typ == 'POST' {
C.curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req.data.cstr())
C.curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, 'POST')
// req.headers << 'Content-Type: application/x-www-form-urlencoded'
}
// Add request headers
mut hlist := &C.curl_slist{!}
// for i, h := range req.headers {
for entry in req.headers.entries {
key := entry.key
val := req.headers[key]
h := '$key: $val'
hlist = C.curl_slist_append(hlist, h.cstr())
}
// curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, // (long)CURL_HTTP_VERSION_2TLS);<3B>`C<>ʀ9<CA80>
C.curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)
if req.verbose {
C.curl_easy_setopt(curl, CURLOPT_VERBOSE, 1)
}
C.curl_easy_setopt(curl, CURLOPT_HTTPHEADER, hlist)
C.curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1)
C.curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1)
//println('bef easy()')
res := C.curl_easy_perform(curl)
//println('after easy()')
# if (res != CURLE_OK )
{
err := C.curl_easy_strerror(res)
println('curl_easy_perform() failed: $err')
}
body := chunk.strings.join('')// string(chunk.memory)
// chunk.strings.free()
// resp.headers = hchunk.strings
if hchunk.strings.len == 0 {
return Response{}
}
first_header := hchunk.strings.first()
mut status_code := 0
if first_header.contains('HTTP/') {
val := first_header.find_between(' ', ' ')
status_code = val.int()
}
// Build resp headers map
// println('building resp headers hchunk.strings.len')
for h in hchunk.strings {
// break
// println(h)
vals := h.split(':')
pos := h.index(':')
if pos == -1 {
continue
}
if h.contains('Content-Type') {
continue
}
key := h.left(pos)
val := h.right(pos + 1)
// println('"$key" *** "$val"')
// val2 := val.trim_space()
// println('val2="$val2"')
headers[key] = val// val.trim_space()
}
// println('done')
// j.println(resp.status_code)
// println('body=')
// j.println(resp.body)
// j.println('headers=')
// j.println(hchunk.strings)
C.curl_easy_cleanup(curl)
//println('end of req.do() url="$req.url"')
return Response {
body: body
}
}
fn unescape(s string) string {
return string(byteptr(C.curl_unescape(s.cstr(), s.len)))
}
fn escape(s string) string {
return string(byteptr(C.curl_escape(s.cstr(), s.len)))
}
// ////////////////
fn (req &Request) do2() Response {
mut resp := Response{}
return resp
}

207
vlib/http/http_win.v Normal file
View File

@ -0,0 +1,207 @@
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module http
#flag -lwininet
#flag -lurlmon
// #include <WinInet.h>
#include "urlmon.h"
#include <shlwapi.h>
// #LPWSTR winstring(string s);
// # bool ok = InternetReadFile(request, buf, BUF_MAX, &nr_read);
import const (
INTERNET_OPEN_TYPE_PRECONFIG
INTERNET_DEFAULT_HTTP_PORT
INTERNET_DEFAULT_HTTPS_PORT
INTERNET_SERVICE_HTTP
)
fn (req &Request) do() Response {
mut s := ''
emptyresp := Response{}
mut url := req.url
println('\n\nhttp.do() WIN URL="$url" TYP=$req.typ data="$req.data" headers.len=req.headers.len"')
println(req.headers)
is_ssl := req.url.starts_with('https://')
println('is ssl=$is_ssl')
mut pos := url.index('/')
url = url.right(pos + 2)
mut host := url
mut path := '/'
pos = url.index('/')
if pos > -1 {
host = url.left(pos)
host = host.clone()
path = url.right(pos)
}
// println('HOST="$host"')
// println('PATH="$path"')
mut headers := ''
mut resp_headers := ''
// for header in req.headers {
for entry in req.headers.entries {
// headers += '$header\r\n'
key := entry.key
val := req.headers[key]
headers += '$key: $val\r\n'
}
if req.typ == 'POST' {
headers += 'Content-Type: application/x-www-form-urlencoded'
}
// headers = headers.trim_space()
// println('!!! OLO REQ HEADERS WIN="$headers"')
data := req.data
// Retrieve default http user agent
// char httpUseragent[512];
// # char httpUseragent []= "";
user_agent := ''
// DWORD szhttpUserAgent = sizeof(httpUseragent);
// ObtainUserAgentString(0, httpUseragent, &szhttpUserAgent);
// # HINTERNET internet = InternetOpenA(httpUseragent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
internet := C.InternetOpenA(user_agent.str, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0)
// # if (!internet)
if isnil(internet) {
println('InternetOpen() failed')
return emptyresp
}
// # INTERNET_PORT port = INTERNET_DEFAULT_HTTP_PORT;
port := int(if is_ssl{INTERNET_DEFAULT_HTTPS_PORT} else { INTERNET_DEFAULT_HTTP_PORT})
// if is_ssl {
// # port = INTERNET_DEFAULT_HTTPS_PORT;
// }
connect := C.InternetConnectA(internet, host.str, port, 0, 0, INTERNET_SERVICE_HTTP, 0, 0)
// # HINTERNET connect = InternetConnectA(internet, host.str, port, NULL, NULL,
// # INTERNET_SERVICE_HTTP, 0, 0);
# if (!connect)
if isnil(connect) {
e := C.GetLastError()
println('[windows] InternetConnect() failed')
C.printf('err=%d\n', e)
return emptyresp
}
flags := 0
// # DWORD flags =
#flags =
# INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
# INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
# INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
# INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_NO_AUTH |
# INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI |
# INTERNET_FLAG_NO_COOKIES | // FUCK YOU MICROSOFT
# INTERNET_FLAG_KEEP_CONNECTION |
# INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD ;
if is_ssl {
#flags = flags | INTERNET_FLAG_SECURE;
}
request := C.HttpOpenRequest(connect, req.typ.str, path.str, 'HTTP/1.1', 0, 0, flags, 0)
// request := C.InternetOpenUrl(connect, req.typ.str, path.str, 'HTTP/1.1', 0, 0, flags, 0)
// # HINTERNET request = HttpOpenRequest(connect, req->typ.str, path.str, "HTTP/1.1",
// # NULL, NULL, flags, NULL);
// # if (!request)
if isnil(request) {
println('HttpOpenRequest() failed')
return emptyresp
}
// println('LEN BEFORE SEND=$headers.len ; $headers')
# bool ret =HttpSendRequest(request, headers.str, -1, data.str, data.len);
# printf("RET=%d\n", ret);
# int e = GetLastError();
# printf("e=%d\n", e);
// Get response headers
// Todo call twice to get len
# LPSTR h_buf = malloc(1024);
# DWORD dwSize = 1024;
// LPVOID lpOutBuffer=malloc(dwSize);
# HttpQueryInfo(request, HTTP_QUERY_RAW_HEADERS_CRLF,
# h_buf,&dwSize,NULL);
# printf(" resp HEADERS %s\n", h_buf);
// Get response body
// # const int BUF_MAX = 1024;
// # TCHAR buf[BUF_MAX + 1];
mut buf := [1025]byte
mut nr_read := 0
BUF_MAX := 1024
// ok := C.InternetReadFile(request, buf, BUF_MAX, &nr_read)
// # DWORD dwRead = 0;
// /println('calling InternetReadFile()')
// # bool ok = InternetReadFile(request, buf, BUF_MAX, &nr_read);
// # if (!ok)
// {
// println('read not ok')
// # int e = GetLastError();
// # printf("%d\n", e);
// }
// # printf("dwread=%d\n", dwRead);
// # while ((InternetReadFile(request, buf, BUF_MAX, &nr_read)) && nr_read > 0)
for
{
println('111')
ok := C.InternetReadFile(request, buf, BUF_MAX, &nr_read)
println('222')
if !ok {
println('InternetReadFile() not ok ')
}
if ok && nr_read == 0 {
println('ok && nr read == 0, breaking')
C.printf('buf broken="%s"\n', buf)
if req.url.contains('websocket') {
println('win sleeping 2')
time.sleep(2)
continue
}
break
}
println('ireadfile()')
buf[nr_read] = 0
C.printf('buf="%s"\n', buf)
s += string(buf)// TODO perf
nr_read = 0
}
C.InternetCloseHandle(request)
C.InternetCloseHandle(connect)
C.InternetCloseHandle(internet)
# resp_headers = tos2(h_buf);
hh := resp_headers.split('\n')
mut resp := Response {
body: s
headers: map[string]string{}
// headers: resp_headers
}
// println('gen hh')
for h in hh {
// println('\n!')
// println(h)
vals := h.split(':')
pos := h.index(':')
if pos == -1 {
continue
}
key := h.left(pos)
val := h.right(pos + 1)
// println('$key => $val')
resp.headers[key] = val.trim_space()
}
println('END OF WIN req.do($req.url)')
return resp
}
fn escape(s string) string {
# DWORD size=1;
# char *escaped = NULL;
# char *empty_string = NULL;
# HRESULT res = UrlEscapeA(s.str, empty_string, &size, URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY);
# if (res == E_POINTER)
{
# escaped = HeapAlloc(GetProcessHeap(), 0, size);
# if (!escaped)
# return s;
# UrlEscapeA(s.str, escaped, &size, URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY);
# return tos2(escaped);
}
return ''
}
fn C.InternetReadFile(voidptr, voidptr, int, intptr) bool