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

Commit

Permalink
Merge pull request #37 from nyanpassu/bugfix/forward-chunked
Browse files Browse the repository at this point in the history
Fix bugs when transfer chunked result
  • Loading branch information
jschwinger233 authored Sep 2, 2021
2 parents 5b37b64 + a565edd commit 0c10d66
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
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

0 comments on commit 0c10d66

Please sign in to comment.