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