From 7607b00952d942282b6ace11a1c181e59ebae8f4 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 7 Aug 2019 04:57:47 +0300 Subject: [PATCH] http: chunked decoding support --- vlib/http/chunked/dechunk.v | 63 +++++++++++++++++++++++++++++++++++++ vlib/http/http.v | 6 +++- vlib/http/openssl_backend.v | 3 ++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 vlib/http/chunked/dechunk.v diff --git a/vlib/http/chunked/dechunk.v b/vlib/http/chunked/dechunk.v new file mode 100644 index 0000000000..461b2dca6d --- /dev/null +++ b/vlib/http/chunked/dechunk.v @@ -0,0 +1,63 @@ +module chunked + +import strings + +// See: https://en.wikipedia.org/wiki/Chunked_transfer_encoding +/////////////////////////////////////////////////////////////// +// The chunk size is transferred as a hexadecimal number +// followed by \r\n as a line separator, +// followed by a chunk of data of the given size. +// The end is marked with a chunk with size 0. + +struct ChunkScanner { +mut: + pos int + text string +} + +fn (s mut ChunkScanner) read_chunk_size() int { + mut n := 0 + for { + if s.pos >= s.text.len { break } + c := s.text[s.pos] + if !c.is_hex_digit() { break } + n = n << 4 + n += int(unhex(c)) + s.pos++ + } + return n +} + +fn unhex(c byte) byte { + if `0` <= c && c <= `9` { return c - `0` } + else if `a` <= c && c <= `f` { return c - `a` + 10 } + else if `A` <= c && c <= `F` { return c - `A` + 10 } + return 0 +} + +fn (s mut ChunkScanner) skip_crlf() { + s.pos += 2 +} + +fn (s mut ChunkScanner) read_chunk(chunksize int) string { + startpos := s.pos + s.pos += chunksize + return s.text.substr(startpos, s.pos) +} + +pub fn decode(text string) string { + mut sb := strings.new_builder(100) + mut cscanner := ChunkScanner { + pos: 0 + text: text + } + for { + csize := cscanner.read_chunk_size() + if 0 == csize { break } + cscanner.skip_crlf() + sb.write( cscanner.read_chunk(csize) ) + cscanner.skip_crlf() + } + cscanner.skip_crlf() + return sb.str() +} diff --git a/vlib/http/http.v b/vlib/http/http.v index 27243af3d8..b1d81c5b58 100644 --- a/vlib/http/http.v +++ b/vlib/http/http.v @@ -5,6 +5,7 @@ module http import net.urllib +import http.chunked struct Request { pub: @@ -141,7 +142,10 @@ pub fn (req &Request) do() Response { key := h.left(pos) val := h.right(pos + 2) headers[key] = val.trim_space() - } + } + if headers['Transfer-Encoding'] == 'chunked' { + text = chunked.decode( text ) + } return Response { status_code: status_code headers: headers diff --git a/vlib/http/openssl_backend.v b/vlib/http/openssl_backend.v index 94ba48cbe8..2dc234857c 100644 --- a/vlib/http/openssl_backend.v +++ b/vlib/http/openssl_backend.v @@ -19,6 +19,9 @@ fn init_module() { $if mac { C.SSL_library_init() } + $if linux { + C.SSL_library_init() + } //C.SSL_load_error_strings() //C.OPENSSL_config(0) }