Skip to content
This repository has been archived by the owner on Jul 5, 2022. It is now read-only.

Fix bugs when transfer chunked result #37

Merged
merged 1 commit into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ func (ph HTTPProxyHandler) proxy(response http.ResponseWriter, request *http.Req
return
}
if resp.StatusCode != http.StatusSwitchingProtocols {
if request.Method == http.MethodGet && utils.IsChunkedEncoding(resp) {
log.Debug("[dispatch] Forward chunked response")
utils.ForwardChunked(response, resp)
return
}
log.Debug("[dispatch] Forward http response")
if err := utils.Forward(resp, response); err != nil {
log.Errorf("[dispatch] forward docker socket response failed %v", err)
Expand Down
60 changes: 60 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,66 @@ func Initialize(bufSize int) {
debug = log.GetLevel() == log.DebugLevel
}

// IsChunkedEncoding .
func IsChunkedEncoding(src *http.Response) bool {
for _, value := range src.TransferEncoding {
if lower := strings.ToLower(strings.Trim(value, " ")); lower == "chunked" {
return true
}
}
return false
}

// ForwardChunked .
func ForwardChunked(response http.ResponseWriter, resp *http.Response) {
log.Info("[ForwardChunked] Will forward chunked response")
initResponseHeader(response, resp.StatusCode, resp.Header)

buffer := make([]byte, 256)
for {
cnt, err := resp.Body.Read(buffer)
readed := buffer[:cnt]

log.Infof("%d bytes readed", cnt)

if _, err := response.Write(readed); err != nil {
log.WithError(err).Error("[ForwardChunked] server response write error")
return
}
if flusher, ok := response.(http.Flusher); ok {
flusher.Flush()
} else {
log.Warn("[ForwardChunked] server response is not http flusher")
}

if err == io.EOF {
log.Info("[ForwardChunked] client response end")
return
}

if err != nil {
log.WithError(err).Error("[ForwardChunked] copy io error")
return
}
}
}

func initResponseHeader(response http.ResponseWriter, statusCode int, header http.Header) {
PrintHeaders("ServerResponse", header)
responseHeader := response.Header()
for key, values := range header {
for _, value := range values {
responseHeader.Add(key, value)
}
}
response.WriteHeader(statusCode)
if flusher, ok := response.(http.Flusher); ok {
flusher.Flush()
} else {
log.Error("[WriteToServerResponse] Can't make flush to http.flusher")
}
}

// Forward .
func Forward(src *http.Response, dst http.ResponseWriter) error {
copyHeader(src, dst)
Expand Down