| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 |
- package common
- import (
- "bytes"
- "fmt"
- "io"
- "net/http"
- "github.com/gin-gonic/gin"
- )
- func CloseResponseBodyGracefully(httpResponse *http.Response) {
- if httpResponse == nil || httpResponse.Body == nil {
- return
- }
- err := httpResponse.Body.Close()
- if err != nil {
- SysError("failed to close response body: " + err.Error())
- }
- }
- func IOCopyBytesGracefully(c *gin.Context, src *http.Response, data []byte) {
- if c.Writer == nil {
- return
- }
- body := io.NopCloser(bytes.NewBuffer(data))
- // We shouldn't set the header before we parse the response body, because the parse part may fail.
- // And then we will have to send an error response, but in this case, the header has already been set.
- // So the httpClient will be confused by the response.
- // For example, Postman will report error, and we cannot check the response at all.
- if src != nil {
- for k, v := range src.Header {
- // avoid setting Content-Length
- if k == "Content-Length" {
- continue
- }
- c.Writer.Header().Set(k, v[0])
- }
- }
- // set Content-Length header manually BEFORE calling WriteHeader
- c.Writer.Header().Set("Content-Length", fmt.Sprintf("%d", len(data)))
- // Write header with status code (this sends the headers)
- if src != nil {
- c.Writer.WriteHeader(src.StatusCode)
- } else {
- c.Writer.WriteHeader(http.StatusOK)
- }
- _, err := io.Copy(c.Writer, body)
- if err != nil {
- LogError(c, fmt.Sprintf("failed to copy response body: %s", err.Error()))
- }
- }
|