go:disable http chunk mode-尊龙官方平台

go:disable http chunk mode

el/2024/3/25 16:39:45

go:disable http chunk mode


1.结论

应用层显式设置 content-length,可以 disable chunk mode。

	http.handlefunc("/", func(writer http.responsewriter, request *http.request) {writer.header().set("content-length", "2049")writer.write(bytes.repeat([]byte("."), 2049))})

2.跑起来

go demo:

package mainimport ("bytes""net/http"
)func main() {http.handlefunc("/", func(writer http.responsewriter, request *http.request) {writer.write(bytes.repeat([]byte("."), 2049))})http.listenandserve(":9080", nil)
}

运行:

$ go run main.go 
^csignal: interrupt

测试:

$ curl -v http://127.0.0.1:9080/
...
> 
< http/1.1 200 ok
< date: wed, 28 apr 2021 10:39:50 gmt
< content-type: text/plain; charset=utf-8
< transfer-encoding: chunked
< 
...(2049b)

即,当go服务端写入2049b时,将使用chunk模式传输(transfer-encoding: chunked)。


3.查源码

go版本:

$ go version
go version go1.13.6 linux/amd64

源码定义:

// net/http/server.go
// this should be >= 512 bytes for detectcontenttype,
// but otherwise it's somewhat arbitrary.
const bufferbeforechunkingsize = 2048// net/http/server.go
// read next request from connection.
func (c *conn) readrequest(ctx context.context) (w *response, err error) {...w = &response{conn:          c,cancelctx:     cancelctx,req:           req,reqbody:       req.body,handlerheader: make(header),contentlength: -1,...}...w.cw.res = ww.w = newbufiowritersize(&w.cw, bufferbeforechunkingsize)return w, nil
}

在创建http.response时指定buffer的大小:

// a response represents the server side of an http response.
type response struct {...w  *bufio.writer // buffers output in chunks to chunkwritercw chunkwriter...
}

4.disable http chunk mode

源码注释:【重点】

// if the handler didn't declare a content-length up front, we either
// go into chunking mode or, if the handler finishes running before
// the chunking buffer size, we compute a content-length and send that
// in the header instead.

如果你已经显式声明设置content-length,则不会进入chunk mode,否则,受到chunk buffer size限制:

1.超过chunk buffer size,use chunk mode;
2.未超chunk buffer size,go底层计算content-length并填入http应答header;

因此,如果应用层已知http应答总长度,直接设置content-length即可disable chunk:

package mainimport ("bytes""net/http"
)func main() {http.handlefunc("/", func(writer http.responsewriter, request *http.request) {writer.header().set("content-length", "2049")writer.write(bytes.repeat([]byte("."), 2049))})http.listenandserve(":9080", nil)
}

此时,应用层写入2049b,超过chunk buffer size(2048),但是使用content-length而非chunk。

$ curl -v http://127.0.0.1:9080/
... 
< http/1.1 200 ok
< content-length: 2049
< date: wed, 28 apr 2021 11:00:00 gmt
< content-type: text/plain; charset=utf-8
< 
...(2049b)

5.不建议的方式

修改源码 src/net/http/server.go 中 bufferbeforechunkingsize 值,例如:

// this should be >= 512 bytes for detectcontenttype,
// but otherwise it's somewhat arbitrary.
const bufferbeforechunkingsize = 1024(原2048

此时,应用层未设置content-length并写入1025b,重新编译运行,也将进入chunk mode:

func main() {http.handlefunc("/", func(writer http.responsewriter, request *http.request) {writer.write(bytes.repeat([]byte("."), 1025))})http.listenandserve(":9080", nil)
}
$ go build main.go
$ ./main
$ curl -v http://127.0.0.1:9080/
...
> 
< http/1.1 200 ok
< date: wed, 28 apr 2021 11:12:53 gmt
< content-type: text/plain; charset=utf-8
< transfer-encoding: chunked
< 
...(1025b)

由于没有api设置 bufferbeforechunkingsize 值,因此,只能通过源码方式修改。

这种方法不利于后续运维,因此不建议。


http://www.ngui.cc/el/5127032.html

相关文章

go:http transfer-encoding chunked 实时读写

go:http transfer-encoding chunked 实时读写 服务端: package mainimport ("fmt""net/http""time" )func main() {http.handlefunc("/", func(writer http.responsewriter, request *http.request) {flusher,…

go:http request cancelled 服务端感知

go:http request cancelled 服务端感知 1.背景 今天查问题的时候,偶然发现github上一个有意思的问题,记录下来。 原问题:https://github.com/golang/go/issues/23262 2.问题 首先,我们思考一个问题: 当…

go:read一个已经被canceled的http.request的应答

go:read一个已经被canceled的http.request的应答 1.复现 最近发现项目在处理chunk类型的http应答时,出现读数据异常报错,代码示例如下: server package mainimport ("bytes""net/http" )func main() {http…

docker:安装vim

docker:安装vim 安装命令:apt install vim -y 异常错误:unable to locate package vim # apt install vim reading package lists... done building dependency tree reading state information... done e: unable to locate package…

go:zap log rotate(日志轮转)

go:zap log rotate(日志轮转) demo: package mainimport ("go.uber.org/zap""go.uber.org/zap/zapcore""gopkg.in/natefinch/lumberjack.v2" )func main() {// 日志级别loglevel : "debug&qu…

go:zap 自义定时间戳格式

go:zap 自义定时间戳格式 1.背景 使得zap输出的日志时间戳形如:2021-05-25 22:36:23.107(毫秒) 2.demo: package mainimport ("go.uber.org/zap""go.uber.org/zap/zapcore""gopkg.in/natef…

go run command-line-arguments

go run command-line-arguments 1.复现 目录结构: $ tree test1280 test1280 |-- go.mod |-- hello.go -- main.go代码内容: /*go.mod*/ module test1280go 1.16/*hello.go*/ package mainimport "fmt"func hello() {fmt.println("hel…

go:unresolved reference xx(1)

go:unresolved reference xx(1) 1.环境 goland版本:goland 2020.3.5 go版本:1.16.4 ebdesktop-k45ia6v mingw64 ~/desktop/test1280 $ go version go version go1.16.4 windows/amd64goland中选择的sdk版本:1.16.4 goland已经en…

go:unresolved reference xx(2)

go:unresolved reference xx(2) 1.环境 goland版本:2021.1.2 go版本:1.16.4 ebdesktop-k45ia6v mingw64 ~ $ go version go version go1.16.4 windows/amd642.背景 我们通常执行go get指令完成第三方依赖库的安装。 go get指令具体做了哪…

goland:cannot resolve symbol

goland:cannot resolve symbol 1.环境 goland版本:2021.1.2 go版本:1.16.4 ebdesktop-k45ia6v mingw64 ~/desktop/test1280 $ go version go version go1.16.4 windows/amd642.报错 包import处报错:cannot resolve symbol 项目…
网站地图