checker: requre & in struct init; http: chunked encoding

pull/4940/head
Alexander Medvednikov 2020-05-18 05:10:56 +02:00
parent 88e6d987d6
commit 4f307c1a78
7 changed files with 98 additions and 13 deletions

View File

@ -1224,6 +1224,21 @@ pub fn (s string) all_after(dot string) string {
pub fn (s string) after(dot string) string { return s.all_after(dot) }
pub fn (s string) after_char(dot byte) string {
mut pos := 0
for i, c in s {
if c == dot {
pos = i
break
}
}
if pos == 0 {
return s
}
return s.right(pos+1)
}
// fn (s []string) substr(a, b int) string {
// return join_strings(s.slice_fast(a, b))
// }

View File

@ -463,6 +463,9 @@ fn test_all_after() {
assert s.all_after('fn ') == 'hello'
assert s.all_after('test') == s
assert s.all_after('') == s
assert s.after('e') == 'llo'
x := s.after('e')
assert x == 'llo'
}
fn test_reverse() {

View File

@ -26,7 +26,7 @@ struct User {
nums []int
last_name string [json:lastName]
is_registered bool [json:IsRegistered]
typ int [json:'type']
typ int [json:'type']
pets string [raw; json:'pet_animals']
}
@ -47,7 +47,7 @@ fn test_parse_user() {
assert u.nums[0] == 1
assert u.nums[1] == 2
assert u.nums[2] == 3
assert u.typ == 1
assert u.typ == 1
assert u.pets == '{"name":"Bob","animal":"Dog"}'
}
@ -73,3 +73,25 @@ fn test_raw_json_field() {
assert color.space == 'YCbCr'
}
struct City {
name string
}
struct Country {
cities []City
name string
}
fn test_struct_in_struct() {
country := json.decode(Country, '{ "name": "UK", "cities": [{"name":"London"}, {"name":"Manchester"}]}') or {
assert false
exit(1)
}
assert country.name == 'UK'
assert country.cities.len == 2
assert country.cities[0].name == 'London'
assert country.cities[1].name == 'Manchester'
println(country.cities)
}

View File

@ -69,7 +69,7 @@ fn C.SSL_set_tlsext_host_name() int
fn C.BIO_puts()
fn C.BIO_read()
fn C.BIO_read() int
fn C.BIO_free_all()
@ -83,6 +83,10 @@ fn init() int {
return 1
}
const (
buf_size = 500 // 1536
)
fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response {
// ssl_method := C.SSLv23_method()
ssl_method := C.TLSv1_2_method()
@ -111,6 +115,7 @@ fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response {
preferred_ciphers := 'HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4'
res = C.SSL_set_cipher_list(ssl, preferred_ciphers.str)
if res != 1 {
println('http: openssl: cipher failed')
}
res = C.SSL_set_tlsext_host_name(ssl, host_name.str)
res = C.BIO_do_connect(web)
@ -121,18 +126,44 @@ fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response {
C.SSL_get_peer_certificate(ssl)
res = C.SSL_get_verify_result(ssl)
// /////
s := req.build_request_headers(method, host_name, path)
C.BIO_puts(web, s.str)
req_headers := req.build_request_headers(method, host_name, path)
C.BIO_puts(web, req_headers.str)
mut headers := strings.new_builder(100)
mut h := ''
mut headers_done := false
mut sb := strings.new_builder(100)
mut buff := [buf_size]byte
mut is_chunk_encoding := false
for {
buff := [1536]byte
len := int(C.BIO_read(web, buff, 1536))
if len > 0 {
sb.write(tos(buff, len))
}
else {
len := C.BIO_read(web, buff, buf_size)
if len <= 0 {
break
}
mut chunk := (tos(buff, len))
if !headers_done && chunk.contains('\r\n\r\n') {
headers_done = true
headers.write(chunk.all_before('\r\n'))
h = headers.str()
//println(h)
sb.write(chunk.after('\r\n'))
// TODO for some reason this can be missing from headers
is_chunk_encoding = true //h.contains('chunked')
//println(sb.str())
continue
}
// TODO clean this up
if is_chunk_encoding && len > 6 && ((buff[3] == 13 && buff[4] == 10) || (buff[2] ==13 && buff[3]==10)
|| (buff[4] == 13 && buff[5] == 10) ) {
chunk = chunk.after_char(10)
}
if chunk.len > 3 && chunk[chunk.len-2] == 13 && chunk[chunk.len-1] == 10 {
chunk = chunk[..chunk.len-2]
}
if headers_done {
sb.write(chunk)
} else {
headers.write(chunk)
}
}
if !isnil(web) {
C.BIO_free_all(web)
@ -140,6 +171,8 @@ fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response {
if !isnil(ctx) {
C.SSL_CTX_free(ctx)
}
return parse_response(sb.str())
body:= sb.str()
println(body)
return parse_response(h +'\r\n\r\n'+ body)
}

View File

@ -45,11 +45,16 @@ pub:
pub fn new_request(method, url_, data string) ?Request {
url := if method == 'GET' { url_ + '?' + data } else { url_ }
// println('new req() method=$method url="$url" dta="$data"')
//println('new req() method=$method url="$url" dta="$data"')
return Request{
method: method.to_upper()
url: url
data: data
/*
headers: {
'Accept-Encoding': 'compress'
}
*/
}
}

View File

@ -355,6 +355,10 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$info_field.name`',
field.pos)
}
if info_field.typ.is_ptr() && !expr_type.is_ptr() && !expr_type.is_number(){
c.error('ref', field.pos)
}
struct_init.fields[i].typ = expr_type
struct_init.fields[i].expected_type = info_field.typ
}

View File

@ -2274,6 +2274,9 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
}
}
if !cloned {
if field.expected_type.is_ptr() && !field.typ.is_ptr() && !field.typ.is_number() {
g.write('/* autoref */&')
}
g.expr_with_cast(field.expr, field.typ, field.expected_type)
}
g.writeln(',')