request.go raw

   1  package scw
   2  
   3  import (
   4  	"bytes"
   5  	"context"
   6  	"encoding/json"
   7  	"io"
   8  	"net/http"
   9  	"net/url"
  10  
  11  	"github.com/scaleway/scaleway-sdk-go/errors"
  12  	"github.com/scaleway/scaleway-sdk-go/internal/auth"
  13  )
  14  
  15  // ScalewayRequest contains all the contents related to performing a request on the Scaleway API.
  16  type ScalewayRequest struct {
  17  	Method  string
  18  	Path    string
  19  	Headers http.Header
  20  	Query   url.Values
  21  	Body    io.Reader
  22  
  23  	// request options
  24  	ctx      context.Context
  25  	auth     auth.Auth
  26  	allPages bool
  27  	zones    []Zone
  28  	regions  []Region
  29  }
  30  
  31  // getURL constructs a URL based on the base url and the client.
  32  func (req *ScalewayRequest) getURL(baseURL string) (*url.URL, error) {
  33  	url, err := url.Parse(baseURL + req.Path)
  34  	if err != nil {
  35  		return nil, errors.New("invalid url %s: %s", baseURL+req.Path, err)
  36  	}
  37  	url.RawQuery = req.Query.Encode()
  38  
  39  	return url, nil
  40  }
  41  
  42  // SetBody json marshal the given body and write the json content type
  43  // to the request. It also catches when body is a file.
  44  func (req *ScalewayRequest) SetBody(body any) error {
  45  	var contentType string
  46  	var content io.Reader
  47  
  48  	switch b := body.(type) {
  49  	case *File:
  50  		contentType = b.ContentType
  51  		content = b.Content
  52  	case io.Reader:
  53  		contentType = "text/plain"
  54  		content = b
  55  	default:
  56  		buf, err := json.Marshal(body)
  57  		if err != nil {
  58  			return err
  59  		}
  60  		contentType = "application/json"
  61  		content = bytes.NewReader(buf)
  62  	}
  63  
  64  	if req.Headers == nil {
  65  		req.Headers = http.Header{}
  66  	}
  67  
  68  	req.Headers.Set("Content-Type", contentType)
  69  	req.Body = content
  70  
  71  	return nil
  72  }
  73  
  74  func (req *ScalewayRequest) apply(opts []RequestOption) {
  75  	for _, opt := range opts {
  76  		opt(req)
  77  	}
  78  }
  79  
  80  func (req *ScalewayRequest) validate() error {
  81  	// nothing so far
  82  	return nil
  83  }
  84  
  85  func (req *ScalewayRequest) clone() *ScalewayRequest {
  86  	clonedReq := &ScalewayRequest{
  87  		Method:   req.Method,
  88  		Path:     req.Path,
  89  		Headers:  req.Headers.Clone(),
  90  		ctx:      req.ctx,
  91  		auth:     req.auth,
  92  		allPages: req.allPages,
  93  		zones:    req.zones,
  94  	}
  95  	if req.Query != nil {
  96  		clonedReq.Query = url.Values(http.Header(req.Query).Clone())
  97  	}
  98  	return clonedReq
  99  }
 100