1package gophercloud 2 3import ( 4 "io" 5 "net/http" 6 "strings" 7) 8 9// ServiceClient stores details required to interact with a specific service API implemented by a provider. 10// Generally, you'll acquire these by calling the appropriate `New` method on a ProviderClient. 11type ServiceClient struct { 12 // ProviderClient is a reference to the provider that implements this service. 13 *ProviderClient 14 15 // Endpoint is the base URL of the service's API, acquired from a service catalog. 16 // It MUST end with a /. 17 Endpoint string 18 19 // ResourceBase is the base URL shared by the resources within a service's API. It should include 20 // the API version and, like Endpoint, MUST end with a / if set. If not set, the Endpoint is used 21 // as-is, instead. 22 ResourceBase string 23 24 // This is the service client type (e.g. compute, sharev2). 25 // NOTE: FOR INTERNAL USE ONLY. DO NOT SET. GOPHERCLOUD WILL SET THIS. 26 // It is only exported because it gets set in a different package. 27 Type string 28 29 // The microversion of the service to use. Set this to use a particular microversion. 30 Microversion string 31 32 // MoreHeaders allows users (or Gophercloud) to set service-wide headers on requests. Put another way, 33 // values set in this field will be set on all the HTTP requests the service client sends. 34 MoreHeaders map[string]string 35} 36 37// ResourceBaseURL returns the base URL of any resources used by this service. It MUST end with a /. 38func (client *ServiceClient) ResourceBaseURL() string { 39 if client.ResourceBase != "" { 40 return client.ResourceBase 41 } 42 return client.Endpoint 43} 44 45// ServiceURL constructs a URL for a resource belonging to this provider. 46func (client *ServiceClient) ServiceURL(parts ...string) string { 47 return client.ResourceBaseURL() + strings.Join(parts, "/") 48} 49 50func (client *ServiceClient) initReqOpts(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) { 51 if v, ok := (JSONBody).(io.Reader); ok { 52 opts.RawBody = v 53 } else if JSONBody != nil { 54 opts.JSONBody = JSONBody 55 } 56 57 if JSONResponse != nil { 58 opts.JSONResponse = JSONResponse 59 } 60 61 if opts.MoreHeaders == nil { 62 opts.MoreHeaders = make(map[string]string) 63 } 64 65 if client.Microversion != "" { 66 client.setMicroversionHeader(opts) 67 } 68} 69 70// Get calls `Request` with the "GET" HTTP verb. 71func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { 72 if opts == nil { 73 opts = new(RequestOpts) 74 } 75 client.initReqOpts(url, nil, JSONResponse, opts) 76 return client.Request("GET", url, opts) 77} 78 79// Post calls `Request` with the "POST" HTTP verb. 80func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { 81 if opts == nil { 82 opts = new(RequestOpts) 83 } 84 client.initReqOpts(url, JSONBody, JSONResponse, opts) 85 return client.Request("POST", url, opts) 86} 87 88// Put calls `Request` with the "PUT" HTTP verb. 89func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { 90 if opts == nil { 91 opts = new(RequestOpts) 92 } 93 client.initReqOpts(url, JSONBody, JSONResponse, opts) 94 return client.Request("PUT", url, opts) 95} 96 97// Patch calls `Request` with the "PATCH" HTTP verb. 98func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) { 99 if opts == nil { 100 opts = new(RequestOpts) 101 } 102 client.initReqOpts(url, JSONBody, JSONResponse, opts) 103 return client.Request("PATCH", url, opts) 104} 105 106// Delete calls `Request` with the "DELETE" HTTP verb. 107func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) { 108 if opts == nil { 109 opts = new(RequestOpts) 110 } 111 client.initReqOpts(url, nil, nil, opts) 112 return client.Request("DELETE", url, opts) 113} 114 115// Head calls `Request` with the "HEAD" HTTP verb. 116func (client *ServiceClient) Head(url string, opts *RequestOpts) (*http.Response, error) { 117 if opts == nil { 118 opts = new(RequestOpts) 119 } 120 client.initReqOpts(url, nil, nil, opts) 121 return client.Request("HEAD", url, opts) 122} 123 124func (client *ServiceClient) setMicroversionHeader(opts *RequestOpts) { 125 switch client.Type { 126 case "compute": 127 opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion 128 case "sharev2": 129 opts.MoreHeaders["X-OpenStack-Manila-API-Version"] = client.Microversion 130 case "volume": 131 opts.MoreHeaders["X-OpenStack-Volume-API-Version"] = client.Microversion 132 case "baremetal": 133 opts.MoreHeaders["X-OpenStack-Ironic-API-Version"] = client.Microversion 134 case "baremetal-introspection": 135 opts.MoreHeaders["X-OpenStack-Ironic-Inspector-API-Version"] = client.Microversion 136 } 137 138 if client.Type != "" { 139 opts.MoreHeaders["OpenStack-API-Version"] = client.Type + " " + client.Microversion 140 } 141} 142 143// Request carries out the HTTP operation for the service client 144func (client *ServiceClient) Request(method, url string, options *RequestOpts) (*http.Response, error) { 145 if len(client.MoreHeaders) > 0 { 146 if options == nil { 147 options = new(RequestOpts) 148 } 149 for k, v := range client.MoreHeaders { 150 options.MoreHeaders[k] = v 151 } 152 } 153 return client.ProviderClient.Request(method, url, options) 154} 155