From 79fd9c1f8741f15cda9cb03200fa37576b047e91 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 15 May 2022 00:23:52 +0200 Subject: [PATCH] fix(docker): read_response now handles chunked data --- src/build/build.v | 1 - src/docker/images.v | 5 +---- src/docker/socket.v | 22 +++++++++++++++++++--- src/util/util.v | 11 +++++++++++ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/build/build.v b/src/build/build.v index dd72c17..98c56f5 100644 --- a/src/build/build.v +++ b/src/build/build.v @@ -56,7 +56,6 @@ pub fn create_build_image(base_image string) ?string { // This loop waits until the container has stopped, so we can remove it after for { - println('wot') data := dd.inspect_container(id)? if !data.state.running { diff --git a/src/docker/images.v b/src/docker/images.v index 974b408..ab735f2 100644 --- a/src/docker/images.v +++ b/src/docker/images.v @@ -27,11 +27,8 @@ pub fn (mut d DockerDaemon) pull_image(image string, tag string) ? { mut buf := []u8{len: 1024} for { - c := body.read(mut buf)? + c := body.read(mut buf) or { break } - if c == 0 { - break - } print(buf[..c].bytestr()) } } diff --git a/src/docker/socket.v b/src/docker/socket.v index b1e3080..dfa7ea7 100644 --- a/src/docker/socket.v +++ b/src/docker/socket.v @@ -38,6 +38,9 @@ pub fn (mut d DockerDaemon) send_request(method string, url urllib.URL) ? { req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\n\n' d.socket.write_string(req)? + + // When starting a new request, the reader needs to be reset. + d.reader = io.new_buffered_reader(reader: d.socket) } // send_request_with_body sends an HTTP request with the given body. @@ -45,6 +48,9 @@ pub fn (mut d DockerDaemon) send_request_with_body(method string, url urllib.URL req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\nContent-Type: $content_type\nContent-Length: $body.len\n\n$body\n\n' d.socket.write_string(req)? + + // When starting a new request, the reader needs to be reset. + d.reader = io.new_buffered_reader(reader: d.socket) } // send_request_with_json is a convenience wrapper around @@ -108,11 +114,21 @@ pub fn (mut d DockerDaemon) read_response_body(length int) ?string { return builder.str() } -// read_response is a convenience function combining read_response_head & -// read_response_body. It can be used when you know for certain the response -// won't be chunked. +// read_response is a convenience function which always consumes the entire +// response & returns it. It should only be used when we're certain that the +// result isn't too large. pub fn (mut d DockerDaemon) read_response() ?(http.Response, string) { head := d.read_response_head()? + + if head.header.get(http.CommonHeader.transfer_encoding) or { '' } == 'chunked' { + mut builder := strings.new_builder(1024) + mut body := d.get_chunked_response_reader() + + util.reader_to_writer(mut body, mut builder) ? + + return head, builder.str() + } + content_length := head.header.get(http.CommonHeader.content_length)?.int() res := d.read_response_body(content_length)? diff --git a/src/util/util.v b/src/util/util.v index f805e6d..7aabc1b 100644 --- a/src/util/util.v +++ b/src/util/util.v @@ -23,6 +23,17 @@ pub fn exit_with_message(code int, msg string) { exit(code) } +// reader_to_writer tries to consume the entire reader & write it to the writer. +pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ? { + mut buf := []u8{len: 10 * 1024} + + for { + c := reader.read(mut buf) or { break } + + writer.write(buf) or { break } + } +} + // reader_to_file writes the contents of a BufferedReader to a file pub fn reader_to_file(mut reader io.BufferedReader, length int, path string) ? { mut file := os.create(path)?