mirror of
				https://github.com/KevinMidboe/planetposen-mail.git
				synced 2025-10-29 17:50:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			135 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package client contains a HTTP client.
 | |
| package client
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"net/http"
 | |
| 	"net/url"
 | |
| 	"time"
 | |
| 
 | |
| 	opentracing "github.com/opentracing/opentracing-go"
 | |
| )
 | |
| 
 | |
| // Parameters provides the parameters used when creating a new HTTP client.
 | |
| type Parameters struct {
 | |
| 	Timeout *time.Duration
 | |
| }
 | |
| 
 | |
| // NewHTTPClient instantiates a new HTTPClient based on provided parameters.
 | |
| func NewHTTPClient(parameters Parameters) HTTPClient {
 | |
| 	if parameters.Timeout == nil {
 | |
| 		timeout := 1 * time.Second
 | |
| 		parameters.Timeout = &timeout
 | |
| 	}
 | |
| 
 | |
| 	client := &http.Client{
 | |
| 		Timeout: *parameters.Timeout,
 | |
| 	}
 | |
| 
 | |
| 	return HTTPClient{client}
 | |
| }
 | |
| 
 | |
| // HTTPRequestData contains the request data.
 | |
| type HTTPRequestData struct {
 | |
| 	Method      string
 | |
| 	URL         string
 | |
| 	Headers     map[string]string
 | |
| 	PostPayload []byte
 | |
| 	GetPayload  *url.Values
 | |
| }
 | |
| 
 | |
| // HTTPClient contains the HTTP client.
 | |
| type HTTPClient struct {
 | |
| 	*http.Client
 | |
| }
 | |
| 
 | |
| // HTTPStatusCodeError is an error that occurs when receiving an unexpected status code (>= 400).
 | |
| type HTTPStatusCodeError struct {
 | |
| 	URL        string
 | |
| 	StatusCode int
 | |
| 	Message    string
 | |
| }
 | |
| 
 | |
| // Error return an error string.
 | |
| func (e HTTPStatusCodeError) Error() string {
 | |
| 	return fmt.Sprintf("Error response from %s, got status: %d", e.URL, e.StatusCode)
 | |
| }
 | |
| 
 | |
| // RequestBytes does the actual HTTP request.
 | |
| // Returns a slice of bytes or an error.
 | |
| func (client *HTTPClient) RequestBytes(ctx context.Context, reqData HTTPRequestData) ([]byte, error) {
 | |
| 	span, ctx := opentracing.StartSpanFromContext(ctx, "RequestBytes")
 | |
| 	defer span.Finish()
 | |
| 
 | |
| 	r, err := client.request(ctx, reqData)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	defer r.Body.Close()
 | |
| 
 | |
| 	if r.StatusCode >= 400 {
 | |
| 		resp, _ := ioutil.ReadAll(r.Body)
 | |
| 		message := string(resp)
 | |
| 		span.SetTag("error", true)
 | |
| 		span.LogKV("message", fmt.Errorf("error making request to %s, got error: %s", reqData.URL, message))
 | |
| 		return nil, HTTPStatusCodeError{
 | |
| 			URL:        reqData.URL,
 | |
| 			StatusCode: r.StatusCode,
 | |
| 			Message:    message,
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return ioutil.ReadAll(r.Body)
 | |
| }
 | |
| 
 | |
| func (client *HTTPClient) request(ctx context.Context, reqData HTTPRequestData) (*http.Response, error) {
 | |
| 	var req *http.Request
 | |
| 	var err error
 | |
| 
 | |
| 	if reqData.Method == http.MethodPost {
 | |
| 		req, err = http.NewRequest(reqData.Method, reqData.URL, bytes.NewBuffer(reqData.PostPayload))
 | |
| 	} else {
 | |
| 		req, err = http.NewRequest(reqData.Method, reqData.URL, nil)
 | |
| 	}
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	if reqData.GetPayload != nil {
 | |
| 		req.URL.RawQuery = reqData.GetPayload.Encode()
 | |
| 	}
 | |
| 
 | |
| 	span := opentracing.SpanFromContext(ctx)
 | |
| 
 | |
| 	if span != nil {
 | |
| 		opentracing.GlobalTracer().Inject(
 | |
| 			span.Context(),
 | |
| 			opentracing.HTTPHeaders,
 | |
| 			opentracing.HTTPHeadersCarrier(req.Header),
 | |
| 		)
 | |
| 	}
 | |
| 
 | |
| 	for k, v := range reqData.Headers {
 | |
| 		req.Header.Set(k, v)
 | |
| 	}
 | |
| 
 | |
| 	req.Header.Set("User-Agent", "planetposen-mail")
 | |
| 
 | |
| 	resp, err := client.Do(req)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		if reqData.Method == http.MethodPost {
 | |
| 			return resp, fmt.Errorf("Error making request: %v. Body: %s", err, reqData.PostPayload)
 | |
| 		}
 | |
| 
 | |
| 		return resp, fmt.Errorf("Error making request: %v. Query: %v", err, req.URL.RawQuery)
 | |
| 	}
 | |
| 
 | |
| 	return resp, nil
 | |
| } |