From a62e6b127a12efe82913a173334e7ceb3cde9628 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 25 Aug 2019 01:48:06 +0300 Subject: [PATCH] http: send headers and request data --- vlib/http/backend_nix.v | 4 ++-- vlib/http/backend_win.v | 6 +++--- vlib/http/http.v | 33 ++++++++++++++++++++++----------- vlib/http/http_client.v | 4 ++-- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/vlib/http/backend_nix.v b/vlib/http/backend_nix.v index 4424632b4b..7d4e2ac760 100644 --- a/vlib/http/backend_nix.v +++ b/vlib/http/backend_nix.v @@ -38,7 +38,7 @@ fn init_module() { //C.OPENSSL_config(0) } -fn ssl_do(port int, method, host_name, path string) Response { +fn (req &Request) ssl_do(port int, method, host_name, path string) Response { //ssl_method := C.SSLv23_method() ssl_method := C.TLSv1_2_method() if isnil(method) { @@ -73,7 +73,7 @@ fn ssl_do(port int, method, host_name, path string) Response { cert := C.SSL_get_peer_certificate(ssl) res = C.SSL_get_verify_result(ssl) /////// - s := build_request_headers('', method, host_name, path) + s := req.build_request_headers(method, host_name, path) C.BIO_puts(web, s.str) mut sb := strings.new_builder(100) for { diff --git a/vlib/http/backend_win.v b/vlib/http/backend_win.v index 0ec9f6fb9e..2d123b9a46 100644 --- a/vlib/http/backend_win.v +++ b/vlib/http/backend_win.v @@ -16,14 +16,14 @@ import net.urllib fn init_module() {} -fn ssl_do(port int, method, host_name, path string) Response { +fn (req &Request) ssl_do(port int, method, host_name, path string) Response { C.vschannel_init() // TODO: joe-c // dynamically increase in vschannel.c if needed mut buff := malloc(44000) addr := host_name - req := build_request_headers('', method, host_name, path) - length := int(C.request(port, addr.str, req.str, buff)) + sdata := req.build_request_headers(method, host_name, path) + length := int(C.request(port, addr.str, sdata.str, buff)) C.vschannel_cleanup() return parse_response(string(buff, length)) diff --git a/vlib/http/http.v b/vlib/http/http.v index 1c22c409c5..9a3274bdbc 100644 --- a/vlib/http/http.v +++ b/vlib/http/http.v @@ -25,6 +25,7 @@ pub: ws_func voidptr user_ptr voidptr verbose bool + user_agent string } struct Response { @@ -66,6 +67,7 @@ pub fn new_request(typ, _url, _data string) ?Request { ws_func: 0 user_ptr: 0 headers: map[string]string + user_agent: 'v' } } @@ -109,7 +111,7 @@ pub fn (req &Request) do() ?Response { mut no_redirects := 0 for { if no_redirects == max_redirects { return error('http.request.do: maximum number of redirects reached ($max_redirects)') } - qresp := method_and_url_to_response( req.typ, rurl ) or { return error(err) } + qresp := req.method_and_url_to_response( req.typ, rurl ) or { return error(err) } resp = qresp if ! (resp.status_code in [301, 302, 303, 307, 308]) { break } // follow any redirects @@ -121,9 +123,9 @@ pub fn (req &Request) do() ?Response { return resp } -fn method_and_url_to_response(method string, url net_dot_urllib.URL) ?Response { - host_name := url.hostname() - scheme := url.scheme +fn (req &Request) method_and_url_to_response(method string, url net_dot_urllib.URL) ?Response { + host_name := url.hostname() + scheme := url.scheme mut p := url.path.trim_left('/') mut path := if url.query().size > 0 { '/$p?${url.query().encode()}' } else { '/$p' } mut nport := url.port().int() @@ -134,10 +136,10 @@ fn method_and_url_to_response(method string, url net_dot_urllib.URL) ?Response { //println('fetch $method, $scheme, $host_name, $nport, $path ') if scheme == 'https' { //println('ssl_do( $nport, $method, $host_name, $path )') - return ssl_do( nport, method, host_name, path ) + return req.ssl_do( nport, method, host_name, path ) } else if scheme == 'http' { //println('http_do( $nport, $method, $host_name, $path )') - return http_do( nport, method, host_name, path ) + return req.http_do(nport, method, host_name, path ) } return error('http.request.do: unsupported scheme: $scheme') } @@ -190,12 +192,21 @@ fn parse_response(resp string) Response { } } -fn build_request_headers(user_agent, method, host_name, path string) string { - ua := if user_agent == '' { 'v' } else { user_agent } +fn (req &Request) build_request_headers(method, host_name, path string) string { + ua := req.user_agent + mut uheaders := []string + for key, val in req.headers { + uheaders << '${key}: ${val}\r\n' + } + if req.data.len > 0 { + uheaders << 'Content-Length: ${req.data.len}\r\n' + } return '$method $path HTTP/1.1\r\n' + - 'Host: $host_name\r\n' + - 'User-Agent: $ua\r\n' + - 'Connection: close\r\n\r\n' + 'Host: $host_name\r\n' + + 'User-Agent: $ua\r\n' + + uheaders.join('') + + 'Connection: close\r\n\r\n' + + req.data } pub fn unescape_url(s string) string { diff --git a/vlib/http/http_client.v b/vlib/http/http_client.v index 9e3d9106b4..1d04a7013f 100644 --- a/vlib/http/http_client.v +++ b/vlib/http/http_client.v @@ -3,11 +3,11 @@ module http import net import strings -fn http_do(port int, method, host_name, path string) ?Response { +fn (req &Request) http_do(port int, method, host_name, path string) ?Response { bufsize := 512 rbuffer := [512]byte mut sb := strings.new_builder(100) - s := build_request_headers('', method, host_name, path) + s := req.build_request_headers(method, host_name, path) client := net.dial( host_name, port) or { return error(err) } client.send( s.str, s.len )