(request *HttpRequest, ctx context.Context)
| 86 | } |
| 87 | |
| 88 | func (c HttpClient) send(request *HttpRequest, ctx context.Context) (*HttpResponse, error) { |
| 89 | transport := &http.Transport{ |
| 90 | Proxy: http.ProxyFromEnvironment, |
| 91 | TLSClientConfig: &tls.Config{InsecureSkipVerify: c.settings.Insecure}, //nolint:gosec // This is user configurable and disabled by default |
| 92 | ResponseHeaderTimeout: c.settings.Timeout, |
| 93 | } |
| 94 | client := &http.Client{Transport: transport} |
| 95 | |
| 96 | responseChan := make(chan *HttpResponse) |
| 97 | ctx, cancel := context.WithCancelCause(ctx) |
| 98 | go func(client *http.Client, request *HttpRequest) { |
| 99 | req, err := http.NewRequestWithContext(ctx, request.Method, request.URL, request.Body) |
| 100 | if err != nil { |
| 101 | cancel(fmt.Errorf("Error preparing request: %w", err)) |
| 102 | return |
| 103 | } |
| 104 | req.Header = request.Header |
| 105 | for k, v := range c.settings.Header { |
| 106 | req.Header.Set(k, v) |
| 107 | } |
| 108 | req.ContentLength = request.ContentLength |
| 109 | |
| 110 | resp, err := client.Do(req) //nolint:bodyclose // The response body needs to be closed by the caller to support streaming |
| 111 | if err != nil { |
| 112 | cancel(fmt.Errorf("Error sending request: %w", err)) |
| 113 | return |
| 114 | } |
| 115 | |
| 116 | response := NewHttpResponse( |
| 117 | resp.Status, |
| 118 | resp.StatusCode, |
| 119 | resp.Proto, |
| 120 | resp.Header, |
| 121 | resp.Body, |
| 122 | resp.ContentLength) |
| 123 | responseChan <- response |
| 124 | }(client, request) |
| 125 | |
| 126 | select { |
| 127 | case <-ctx.Done(): |
| 128 | return nil, fmt.Errorf("Error sending request: %w", context.Cause(ctx)) |
| 129 | case response := <-responseChan: |
| 130 | return response, nil |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | func (c HttpClient) logRequest(request *HttpRequest, body []byte) { |
| 135 | reader := bytes.NewReader(c.truncate(body, loggingLimit)) |
no test coverage detected