http: send headers and request data

pull/1742/head
Delyan Angelov 2019-08-25 01:48:06 +03:00 committed by Alexander Medvednikov
parent 57880aed18
commit a62e6b127a
4 changed files with 29 additions and 18 deletions

View File

@ -38,7 +38,7 @@ fn init_module() {
//C.OPENSSL_config(0) //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.SSLv23_method()
ssl_method := C.TLSv1_2_method() ssl_method := C.TLSv1_2_method()
if isnil(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) cert := C.SSL_get_peer_certificate(ssl)
res = C.SSL_get_verify_result(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) C.BIO_puts(web, s.str)
mut sb := strings.new_builder(100) mut sb := strings.new_builder(100)
for { for {

View File

@ -16,14 +16,14 @@ import net.urllib
fn init_module() {} 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() C.vschannel_init()
// TODO: joe-c // TODO: joe-c
// dynamically increase in vschannel.c if needed // dynamically increase in vschannel.c if needed
mut buff := malloc(44000) mut buff := malloc(44000)
addr := host_name addr := host_name
req := build_request_headers('', method, host_name, path) sdata := req.build_request_headers(method, host_name, path)
length := int(C.request(port, addr.str, req.str, buff)) length := int(C.request(port, addr.str, sdata.str, buff))
C.vschannel_cleanup() C.vschannel_cleanup()
return parse_response(string(buff, length)) return parse_response(string(buff, length))

View File

@ -25,6 +25,7 @@ pub:
ws_func voidptr ws_func voidptr
user_ptr voidptr user_ptr voidptr
verbose bool verbose bool
user_agent string
} }
struct Response { struct Response {
@ -66,6 +67,7 @@ pub fn new_request(typ, _url, _data string) ?Request {
ws_func: 0 ws_func: 0
user_ptr: 0 user_ptr: 0
headers: map[string]string headers: map[string]string
user_agent: 'v'
} }
} }
@ -109,7 +111,7 @@ pub fn (req &Request) do() ?Response {
mut no_redirects := 0 mut no_redirects := 0
for { for {
if no_redirects == max_redirects { return error('http.request.do: maximum number of redirects reached ($max_redirects)') } 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 resp = qresp
if ! (resp.status_code in [301, 302, 303, 307, 308]) { break } if ! (resp.status_code in [301, 302, 303, 307, 308]) { break }
// follow any redirects // follow any redirects
@ -121,7 +123,7 @@ pub fn (req &Request) do() ?Response {
return resp return resp
} }
fn method_and_url_to_response(method string, url net_dot_urllib.URL) ?Response { fn (req &Request) method_and_url_to_response(method string, url net_dot_urllib.URL) ?Response {
host_name := url.hostname() host_name := url.hostname()
scheme := url.scheme scheme := url.scheme
mut p := url.path.trim_left('/') mut p := url.path.trim_left('/')
@ -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 ') //println('fetch $method, $scheme, $host_name, $nport, $path ')
if scheme == 'https' { if scheme == 'https' {
//println('ssl_do( $nport, $method, $host_name, $path )') //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' { } else if scheme == 'http' {
//println('http_do( $nport, $method, $host_name, $path )') //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') 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 { fn (req &Request) build_request_headers(method, host_name, path string) string {
ua := if user_agent == '' { 'v' } else { user_agent } 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' + return '$method $path HTTP/1.1\r\n' +
'Host: $host_name\r\n' + 'Host: $host_name\r\n' +
'User-Agent: $ua\r\n' + 'User-Agent: $ua\r\n' +
'Connection: close\r\n\r\n' uheaders.join('') +
'Connection: close\r\n\r\n' +
req.data
} }
pub fn unescape_url(s string) string { pub fn unescape_url(s string) string {

View File

@ -3,11 +3,11 @@ module http
import net import net
import strings 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 bufsize := 512
rbuffer := [512]byte rbuffer := [512]byte
mut sb := strings.new_builder(100) 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 := net.dial( host_name, port) or { return error(err) }
client.send( s.str, s.len ) client.send( s.str, s.len )