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  }