Handled chunked requests when content-length is given.
(ctx context.Context, finalReq *[]byte, clientConn, destConn net.Conn, contentLength int)
| 110 | |
| 111 | // Handled chunked requests when content-length is given. |
| 112 | func (h *HTTP) contentLengthRequest(ctx context.Context, finalReq *[]byte, clientConn, destConn net.Conn, contentLength int) error { |
| 113 | // Use a larger buffer (e.g., 32KB) for better performance than 1KB |
| 114 | buf := make([]byte, 32*1024) |
| 115 | |
| 116 | for contentLength > 0 { |
| 117 | // 1. Check if context is already done before trying to read |
| 118 | if ctx.Err() != nil { |
| 119 | return ctx.Err() |
| 120 | } |
| 121 | |
| 122 | // 2. Refresh the deadline |
| 123 | err := clientConn.SetReadDeadline(time.Now().Add(20 * time.Second)) |
| 124 | if err != nil { |
| 125 | utils.LogError(h.Logger, err, "failed to set the read deadline for the client conn") |
| 126 | return err |
| 127 | } |
| 128 | |
| 129 | // 3. Read directly from connection |
| 130 | // This blocks only until *some* data is available or error occurs. |
| 131 | readBuf := buf |
| 132 | if contentLength < len(buf) { |
| 133 | readBuf = buf[:contentLength] |
| 134 | } |
| 135 | n, err := clientConn.Read(readBuf) |
| 136 | |
| 137 | if n > 0 { |
| 138 | chunk := buf[:n] |
| 139 | |
| 140 | // Append to final request |
| 141 | *finalReq = append(*finalReq, chunk...) |
| 142 | contentLength -= n |
| 143 | |
| 144 | h.Logger.Debug("Read chunk", zap.Int("chunkSize", n), zap.Int("remaining", contentLength)) |
| 145 | |
| 146 | // Write to destination |
| 147 | if destConn != nil { |
| 148 | _, wErr := destConn.Write(chunk) |
| 149 | if wErr != nil { |
| 150 | if ctx.Err() != nil { |
| 151 | return ctx.Err() |
| 152 | } |
| 153 | utils.LogError(h.Logger, wErr, "failed to write request message to the destination server") |
| 154 | return wErr |
| 155 | } |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | if err != nil { |
| 160 | if err == io.EOF { |
| 161 | // Client closed connection cleanly |
| 162 | utils.LogError(h.Logger, nil, "conn closed by the user client") |
| 163 | return err |
| 164 | } |
| 165 | |
| 166 | // Check for Timeout |
| 167 | if netErr, ok := err.(net.Error); ok && netErr.Timeout() { |
| 168 | h.Logger.Info("Stopped getting data from the conn (Timeout)", zap.Error(err)) |
| 169 | break |
no test coverage detected