英文:
Stray characters in output when using Docker's Go SDK
问题
我正在尝试将通过Go的docker-sdk
运行Docker镜像后获得的io.ReadCloser
(接口)转换为[]byte
以供进一步使用。
当我使用stdcopy.StdCopy
从io.ReadCloser
读取到stdout
时,它可以完美地打印数据。
以下代码stdcopy.StdCopy(os.Stderr, os.Stdout, out)
打印的内容如下:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
Content-Type: text/html
<html>
<head><title>HTML response</title></head>
<body><h1>Hello, Goodbye</h1></body>
</html>
<!-- end snippet -->
因为我需要将整个内容作为响应发送,所以我需要将内容转换为[]byte
或string
。但是,一旦我将io.ReadCloser
转换为[]byte
或string
,使用除了stdcopy.StdCopy
之外的任何方法,它会在某些行添加特殊字符。
我使用以下代码从out
读取到buf
,使用*bytes.Buffer.ReadFrom
:
buf := new(bytes.Buffer)
buf.ReadFrom(out)
fmt.Println(buf.String())
打印的结果如下:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
Content-Type: text/html
<html>
*<head><title>HTML response</title></head>
%<body><h1>Hello, Goodbye</h1></body>
</html>
<!-- end snippet -->
你可以看到额外的字符,如*
和%
被添加了进去。我也尝试过使用ioutil.ReadAll
函数,但没有成功。如果有任何建议,将不胜感激。
英文:
I am trying to convert the io.ReadCloser
(interface) that I am getting after running the Docker image via Go docker-sdk
to []byte
for further use.
When I read from the io.ReadCloser
using stdcopy.StdCopy
to stdout
, it prints the data perfectly.
The code stdcopy.StdCopy(os.Stderr, os.Stdout, out)
prints:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
Content-Type: text/html
<html>
<head><title>HTML response</title></head>
<body><h1>Hello, Goodbye</h1></body>
</html>
<!-- end snippet -->
Because I need to send this entire content as a Response I need to convert the content to []byte
or string
. But, once I convert the io.ReadCloser
to []byte
or string
using any method but stdcopy.StdCopy
, it adds a special character to some lines.
The snippet I used to read from out
to buf
using *bytes.Buffer.ReadFrom
:
buf := new(bytes.Buffer)
buf.ReadFrom(out)
fmt.Println(buf.String())
Prints:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
Content-Type: text/html
<html>
*<head><title>HTML response</title></head>
%<body><h1>Hello, Goodbye</h1></body>
</html>
<!-- end snippet -->
As you can see extra characters like *
and %
are being added. I have also tried ioutil.ReadAll
function as well, no luck. Any suggestion would be much appreciated.
答案1
得分: 3
这些是带有一些行前缀的杂乱字节,如*
,%
等。
这些杂乱字节似乎是一种自定义流复用协议,允许将STDOUT
和STDERR
发送到同一连接。
使用stdcopy.StdCopy()
可以解释这些自定义头,并通过删除每个数据块的协议头来避免这些杂乱字符。
参考:https://github.com/moby/moby/blob/master/pkg/stdcopy/stdcopy.go#L42
// Write将缓冲区发送到底层写入器。
// 它在缓冲区之前插入前缀头,
// 这样stdcopy.StdCopy就知道在哪里复用输出。
// 它使stdWriter实现io.Writer。
因此,stdcopy.StdCopy
是您在使用Docker时的好帮手,也是io.Copy
和相关函数的替代品。
以下是一个示例,以帮助您理解:
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
var resp string = `
Content-Type: text/html
<html>
<head><title>HTML response</title></head>
<body><h1>Hello, Goodbye</h1></body>
</html>`
func main() {
src := strings.NewReader(resp)
dst := &bytes.Buffer{}
_, _ = io.Copy(dst, src)
fmt.Println(dst.String())
// 输出:
//
// Content-Type: text/html
// <html>
// <head><title>HTML response</title></head>
// <body><h1>Hello, Goodbye</h1></body>
// </html>
}
func io.Copy(dst io.Writer, src io.Reader)
的签名
由于dst
(*bytes.Buffer
)具有Write
方法,因此它实现了io.Writer
接口,因此可以正常工作。
现在在使用stdcopy.StdCopy()
时使用相同的思路,因为签名是相同的。https://pkg.go.dev/github.com/docker/docker/pkg/stdcopy#StdCopy
英文:
Those are stray bytes like *
, %
, etc. prefixed with some of the lines.
The stray bytes appear to be a custom stream multiplexing protocol, allowing STDOUT
and STDERR
to be sent down the same connection.
Using stdcopy.StdCopy()
interprets these custom headers and those stray characters are avoided by removing the protocol header for each piece of data.
Refer: https://github.com/moby/moby/blob/master/pkg/stdcopy/stdcopy.go#L42
// Write sends the buffer to the underneath writer.
// It inserts the prefix header before the buffer,
// so stdcopy.StdCopy knows where to multiplex the output.
// It makes stdWriter to implement io.Writer.
So, stdcopy.StdCopy
is your friend and an alternative for io.Copy
and friends when working with Docker.
A sample example to give you an idea:
package main
import (
"bytes"
"fmt"
"io"
"strings"
)
var resp string = `
Content-Type: text/html
<html>
<head><title>HTML response</title></head>
<body><h1>Hello, Goodbye</h1></body>
</html>`
func main() {
src := strings.NewReader(resp)
dst := &bytes.Buffer{}
_, _ = io.Copy(dst, src)
fmt.Println(dst.String())
// Output:
//
// Content-Type: text/html
// <html>
// <head><title>HTML response</title></head>
// <body><h1>Hello, Goodbye</h1></body>
// </html>
}
Signature for: func io.Copy(dst io.Writer, src io.Reader)
As dst
(*bytes.Buffer)
has a Write
method and hence it implements the io.Writer
interface and it works.
Now use the same idea when using stdcopy.StdCopy()
as the signature is the same. https://pkg.go.dev/github.com/docker/docker/pkg/stdcopy#StdCopy
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论