gitlab.com/ignitionrobotics/web/ign-go@v1.0.0-rc4/net/http.go (about) 1 package net 2 3 import ( 4 "bytes" 5 "context" 6 "errors" 7 "io/ioutil" 8 "net/http" 9 "net/url" 10 "strings" 11 "time" 12 ) 13 14 // httpCaller is a Caller implementation using HTTP as transport layer. 15 type httpCaller struct { 16 // client is the HTTP client used to create requests and receive responses from a certain web server. 17 client *http.Client 18 19 // baseURL is the base URL where all the requests should be routed to. 20 baseURL *url.URL 21 22 // endpoints contains a set of HTTP endpoints that this caller can communicate with. 23 endpoints map[string]EndpointHTTP 24 } 25 26 // Call establishes a connection with a certain endpoint sending the given slice of bytes as input, 27 // it returns the response's body as a slice of bytes. 28 func (h *httpCaller) Call(ctx context.Context, endpoint string, in []byte) ([]byte, error) { 29 e := h.resolveEndpoint(endpoint) 30 31 u, err := h.baseURL.Parse(e.Path) 32 if err != nil { 33 return nil, err 34 } 35 36 buff := bytes.NewBuffer(in) 37 req, err := http.NewRequestWithContext(ctx, e.Method, u.String(), buff) 38 if err != nil { 39 return nil, err 40 } 41 42 res, err := h.client.Do(req) 43 if err != nil { 44 return nil, err 45 } 46 47 var out []byte 48 out, err = ioutil.ReadAll(res.Body) 49 if err != nil { 50 return nil, err 51 } 52 53 if res.StatusCode < 200 || res.StatusCode > 299 { 54 return nil, errors.New(strings.TrimRight(string(out), "\r\n")) 55 } 56 57 return out, nil 58 } 59 60 // resolveEndpoint resolves if the given endpoint is a valid endpoint 61 func (h *httpCaller) resolveEndpoint(endpoint string) EndpointHTTP { 62 e, ok := h.endpoints[endpoint] 63 if !ok { 64 return defaultEndpointHTTP 65 } 66 return e 67 } 68 69 // defaultEndpointHTTP is a default endpoint returned when no HTTP endpoint has been found. 70 var defaultEndpointHTTP = EndpointHTTP{ 71 Method: http.MethodGet, 72 Path: "/", 73 } 74 75 // EndpointHTTP represents an HTTP endpoint. 76 type EndpointHTTP struct { 77 // Method is the HTTP verb supported by this endpoint. 78 Method string 79 // Path is the relative path where this endpoint is located. 80 // Example: /example/test 81 Path string 82 } 83 84 // NewCallerHTTP initializes a new HTTP Caller. 85 func NewCallerHTTP(baseURL *url.URL, endpoints map[string]EndpointHTTP, timeout time.Duration) Caller { 86 return &httpCaller{ 87 baseURL: baseURL, 88 endpoints: endpoints, 89 client: &http.Client{Timeout: timeout}, 90 } 91 }