http - Golang 写入 http 响应会中断输入读取?

标签 http go gzip

我正在尝试用 Go 编写一个小型网络应用程序,用户可以在其中以多部分形式上传 gzip 文件。该应用程序解压缩并解析文件并将一些输出写入响应。但是,当我开始写入响应时,我一直遇到输入流看起来已损坏的错误。不写入响应解决了这个问题,就像从非 gzip 压缩的输入流中读取一样。这是一个示例 http 处理程序:

func(w http.ResponseWriter, req *http.Request) {

//Get an input stream from the multipart reader
//and read it using a scanner
multiReader, _ := req.MultipartReader()
part, _ := multiReader.NextPart()
gzipReader, _ := gzip.NewReader(part)
scanner := bufio.NewScanner(gzipReader)

//Strings read from the input stream go to this channel     
inputChan := make(chan string, 1000)

//Signal completion on this channel 
donechan := make(chan bool, 1)

//This goroutine just reads text from the input scanner
//and sends it into the channel 
go func() {
    for scanner.Scan() {
        inputChan <- scanner.Text()
    }       
    close(inputChan)
}()

//Read lines from input channel. They all either start with #
//or have ten tab-separated columns
go func() {
    for line := range inputChan {
        toks := strings.Split(line, "\t")
        if len(toks) != 10 && line[0] != '#' {
            panic("Dang.")
        }
    }
    donechan <- true 
}()

//periodically write some random text to the response
go func() {
    for {
        time.Sleep(10*time.Millisecond)     
        w.Write([]byte("write\n some \n output\n"))
    }
}()

//wait until we're done to return
<-donechan
}

奇怪的是,这段代码每次都会崩溃,因为它总是遇到一行少于 10 个标记的行,尽管每次都在不同的位置。注释掉写入响应的行解决了这个问题,从非 gzip 压缩的输入流中读取也是如此。我错过了一些明显的东西吗?如果从 gzip 文件而不是纯文本格式的文件读取,为什么写入响应会中断?为什么它会破裂?

最佳答案

HTTP 协议(protocol)不是全双工的:它是基于请求-响应的。您应该只在阅读完输入后才发送输出。

在您的代码中,您在 channel 上使用了带有 rangefor。这将尝试读取 channel 直到它关闭,但您永远不会关闭inputChan

如果您从不关闭 inputChan,则永远不会到达以下行:

donechan <- true 

因此从 donechan block 接收:

<-donechan

当到达 EOF 时,您必须关闭 inputChan:

go func() {
    for scanner.Scan() {
        inputChan <- scanner.Text()
    }       
    close(inputChan) // THIS IS NEEDED
}()

关于http - Golang 写入 http 响应会中断输入读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28336313/

相关文章:

javascript - 在 JS 中读取 pcap.gz 文件

r - 如何使用 fread 在 R 中读取 gz 文件?

http - 使用 Golang Gorilla 包设置回调

java - 在 Spring Integration 中将 HTTP 请求 header 设置为 LinkedList

angular - angular http请求同时发送两次

http - 转到 HTTP 请求 POST header ,等待响应,然后发布分块的正文内容

tcp - 允许 golang 通过 Windows 防火墙进行测试

java - 如何在 Grizzly 嵌入式 Jersey 应用程序上获取 HTTP 请求方法?

Golang crypto/tls 内存泄漏

python 和twisted proxy,如何即时进行gunzip?