github.com/openshift-online/ocm-sdk-go@v0.1.473/request.go (about) 1 /* 2 Copyright (c) 2018 Red Hat, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // This file contains the implementation of the request type. 18 19 package sdk 20 21 import ( 22 "bytes" 23 "context" 24 "io" 25 "net/http" 26 "net/url" 27 28 "github.com/openshift-online/ocm-sdk-go/internal" 29 ) 30 31 // Request contains the information and logic needed to perform an HTTP request. 32 type Request struct { 33 transport http.RoundTripper 34 method string 35 path string 36 query url.Values 37 header http.Header 38 body []byte 39 } 40 41 // GetMethod returns the request method (GET/POST/PATCH/PUT/DELETE). 42 func (r *Request) GetMethod() string { 43 return r.method 44 } 45 46 // Path defines the request path, for example `/api/clusters_mgmt/v1/clusters`. This is mandatory; an 47 // error will be returned immediately when calling the Send method if this isn't provided. 48 func (r *Request) Path(value string) *Request { 49 r.path = value 50 return r 51 } 52 53 // GetPath returns the request path. 54 func (r *Request) GetPath() string { 55 return r.path 56 } 57 58 // Parameter adds a query parameter. 59 func (r *Request) Parameter(name string, value interface{}) *Request { 60 internal.AddValue(&r.query, name, value) 61 return r 62 } 63 64 // Header adds a request header. 65 func (r *Request) Header(name string, value interface{}) *Request { 66 internal.AddHeader(&r.header, name, value) 67 return r 68 } 69 70 // Bytes sets the request body from an slice of bytes. 71 func (r *Request) Bytes(value []byte) *Request { 72 if value != nil { 73 r.body = make([]byte, len(value)) 74 copy(r.body, value) 75 } else { 76 r.body = nil 77 } 78 return r 79 } 80 81 // String sets the request body from an string. 82 func (r *Request) String(value string) *Request { 83 r.body = []byte(value) 84 return r 85 } 86 87 // Send sends this request to the server and returns the corresponding response, or an error if 88 // something fails. Note that any HTTP status code returned by the server is considered a valid 89 // response, and will not be translated into an error. It is up to the caller to check the status 90 // code and handle it. 91 // 92 // This operation is potentially lengthy, as it requires network communication. Consider using a 93 // context and the SendContext method. 94 func (r *Request) Send() (result *Response, err error) { 95 return r.SendContext(context.Background()) 96 } 97 98 // SendContext sends this request to the server and returns the corresponding response, or an error 99 // if something fails. Note that any HTTP status code returned by the server is considered a valid 100 // response, and will not be translated into an error. It is up to the caller to check the status 101 // code and handle it. 102 func (r *Request) SendContext(ctx context.Context) (result *Response, err error) { 103 query := internal.CopyQuery(r.query) 104 header := internal.CopyHeader(r.header) 105 uri := &url.URL{ 106 Path: r.path, 107 RawQuery: query.Encode(), 108 } 109 var body io.ReadCloser 110 if r.body != nil { 111 body = io.NopCloser(bytes.NewBuffer(r.body)) 112 } 113 request := &http.Request{ 114 Method: r.method, 115 URL: uri, 116 Header: header, 117 Body: body, 118 } 119 if ctx != nil { 120 request = request.WithContext(ctx) 121 } 122 response, err := r.transport.RoundTrip(request) 123 if err != nil { 124 return 125 } 126 defer response.Body.Close() 127 result = new(Response) 128 result.status = response.StatusCode 129 result.header = response.Header 130 result.body, err = io.ReadAll(response.Body) 131 if err != nil { 132 return 133 } 134 return 135 }