service_client.go 4.9 KB

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