haveapi-go-client 0.27.3 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,11 +2,12 @@ package <%= package %>
2
2
 
3
3
  import (
4
4
  <% if action.has_path_params? -%>
5
+ "net/url"
5
6
  "strings"
6
7
  <% end -%>
7
8
  )
8
9
 
9
- // <%= action.go_type %> is a type for action <%= action.full_dot_name %>
10
+ // <%= action.go_type %> is a type for action <%= go_comment_text(action.full_dot_name) %>
10
11
  type <%= action.go_type %> struct {
11
12
  // Pointer to client
12
13
  Client *Client
@@ -22,7 +23,7 @@ func New<%= action.go_type %>(client *Client) *<%= action.go_type %> {
22
23
  // <%= action.metadata.global.input.go_type %> is a type for action global meta input parameters
23
24
  type <%= action.metadata.global.input.go_type %> struct {
24
25
  <% action.metadata.global.input.parameters.each do |p| -%>
25
- <%= p.go_name %> <%= p.go_in_type %> `json:"<%= p.name %>"`
26
+ <%= p.go_name %> <%= p.go_in_type %> <%= go_json_tag(p.name) %>
26
27
  <% end -%>
27
28
  // Only selected parameters are sent to the API. Ignored if empty.
28
29
  _selectedParameters map[string]interface{}
@@ -42,7 +43,7 @@ func (in *<%= action.metadata.global.input.go_type %>) Set<%= p.go_name %>(value
42
43
  <% if p.nillable? -%>
43
44
  in.Set<%= p.go_name %>Nil(false)
44
45
  <% end -%>
45
- in._selectedParameters["<%= p.go_name %>"] = nil
46
+ in._selectedParameters[<%= go_string_literal(p.go_name) %>] = nil
46
47
  return in
47
48
  }
48
49
  <% if p.nillable? -%>
@@ -57,10 +58,10 @@ func (in *<%= action.metadata.global.input.go_type %>) Set<%= p.go_name %>Nil(se
57
58
  }
58
59
 
59
60
  if set {
60
- in._nilParameters["<%= p.go_name %>"] = nil
61
- in.SelectParameters("<%= p.go_name %>")
61
+ in._nilParameters[<%= go_string_literal(p.go_name) %>] = nil
62
+ in.SelectParameters(<%= go_string_literal(p.go_name) %>)
62
63
  } else {
63
- delete(in._nilParameters, "<%= p.go_name %>")
64
+ delete(in._nilParameters, <%= go_string_literal(p.go_name) %>)
64
65
  }
65
66
  return in
66
67
  }
@@ -95,7 +96,7 @@ func (in *<%= action.metadata.global.input.go_type %>) AnySelected() bool {
95
96
  // <%= action.input.go_type %> is a type for action input parameters
96
97
  type <%= action.input.go_type %> struct {
97
98
  <% action.input.parameters.each do |p| -%>
98
- <%= p.go_name %> <%= p.go_in_type %> `json:"<%= p.name %>"`
99
+ <%= p.go_name %> <%= p.go_in_type %> <%= go_json_tag(p.name) %>
99
100
  <% end -%>
100
101
  // Only selected parameters are sent to the API. Ignored if empty.
101
102
  _selectedParameters map[string]interface{}
@@ -115,7 +116,7 @@ func (in *<%= action.input.go_type %>) Set<%= p.go_name %>(value <%= p.go_in_typ
115
116
  <% if p.nillable? -%>
116
117
  in.Set<%= p.go_name %>Nil(false)
117
118
  <% end -%>
118
- in._selectedParameters["<%= p.go_name %>"] = nil
119
+ in._selectedParameters[<%= go_string_literal(p.go_name) %>] = nil
119
120
  return in
120
121
  }
121
122
  <% if p.nillable? -%>
@@ -130,10 +131,10 @@ func (in *<%= action.input.go_type %>) Set<%= p.go_name %>Nil(set bool) *<%= act
130
131
  }
131
132
 
132
133
  if set {
133
- in._nilParameters["<%= p.go_name %>"] = nil
134
- in.SelectParameters("<%= p.go_name %>")
134
+ in._nilParameters[<%= go_string_literal(p.go_name) %>] = nil
135
+ in.SelectParameters(<%= go_string_literal(p.go_name) %>)
135
136
  } else {
136
- delete(in._nilParameters, "<%= p.go_name %>")
137
+ delete(in._nilParameters, <%= go_string_literal(p.go_name) %>)
137
138
  }
138
139
  return in
139
140
  }
@@ -183,10 +184,10 @@ func (in *<%= action.input.go_type %>) AnySelected() bool {
183
184
  // <%= action.go_request_type %> is a type for the entire action request
184
185
  type <%= action.go_request_type %> struct {
185
186
  <% if action.has_input? -%>
186
- <%= action.input.go_namespace %> map[string]interface{} `json:"<%= action.input.namespace %>"`
187
+ <%= action.input.go_namespace %> map[string]interface{} <%= go_json_tag(action.input.namespace) %>
187
188
  <% end -%>
188
189
  <% if action.metadata.has_global_input? -%>
189
- Meta map[string]interface{} `json:"<%= action.resource.api_version.metadata_namespace %>"`
190
+ Meta map[string]interface{} <%= go_json_tag(action.resource.api_version.metadata_namespace) %>
190
191
  <% end -%>
191
192
  }
192
193
  <% end -%>
@@ -196,9 +197,9 @@ type <%= action.go_request_type %> struct {
196
197
  type <%= action.output.go_type %> struct {
197
198
  <% action.output.parameters.each do |p| -%>
198
199
  <% if p.respond_to?(:association) -%>
199
- <%= p.go_name %> *<%= p.go_out_type %> `json:"<%= p.name %>"`
200
+ <%= p.go_name %> *<%= p.go_out_type %> <%= go_json_tag(p.name) %>
200
201
  <% else -%>
201
- <%= p.go_name %> <%= p.go_out_type %> `json:"<%= p.name %>"`
202
+ <%= p.go_name %> <%= p.go_out_type %> <%= go_json_tag(p.name) %>
202
203
  <% end -%>
203
204
  <% end -%>
204
205
  }
@@ -208,23 +209,23 @@ type <%= action.output.go_type %> struct {
208
209
  // <%= action.metadata.global.output.go_type %> is a type for global output metadata parameters
209
210
  type <%= action.metadata.global.output.go_type %> struct {
210
211
  <% action.metadata.global.output.parameters.each do |p| -%>
211
- <%= p.go_name %> <%= p.go_out_type %> `json:"<%= p.name %>"`
212
+ <%= p.go_name %> <%= p.go_out_type %> <%= go_json_tag(p.name) %>
212
213
  <% end -%>
213
214
  }
214
215
  <% end -%>
215
216
 
216
217
  // Type for action response, including envelope
217
218
  type <%= action.go_response_type %> struct {
218
- Action *<%= action.go_type %> `json:"-"`
219
+ Action *<%= action.go_type %> <%= go_json_tag('-') %>
219
220
  *Envelope
220
221
  <% if action.has_output? -%>
221
222
  <% if %w(hash object).include?(action.output.layout) -%>
222
223
  // Action output encapsulated within a namespace
223
224
  Response *struct {
224
- <%= action.output.go_namespace %> *<%= action.output.go_type %> `json:"<%= action.output.namespace %>"`
225
+ <%= action.output.go_namespace %> *<%= action.output.go_type %> <%= go_json_tag(action.output.namespace) %>
225
226
  <% if action.blocking? -%>
226
227
  // Global output metadata
227
- Meta *<%= action.metadata.global.output.go_type %> `json:"<%= action.resource.api_version.metadata_namespace %>"`
228
+ Meta *<%= action.metadata.global.output.go_type %> <%= go_json_tag(action.resource.api_version.metadata_namespace) %>
228
229
  <% end -%>
229
230
  }
230
231
 
@@ -233,10 +234,10 @@ type <%= action.go_response_type %> struct {
233
234
  <% elsif %w(hash_list object_list).include?(action.output.layout) -%>
234
235
  // Action output encapsulated within a namespace
235
236
  Response *struct {
236
- <%= action.output.go_namespace %> []*<%= action.output.go_type %> `json:"<%= action.output.namespace %>"`
237
+ <%= action.output.go_namespace %> []*<%= action.output.go_type %> <%= go_json_tag(action.output.namespace) %>
237
238
  <% if action.blocking? -%>
238
239
  // Global output metadata
239
- Meta *<%= action.metadata.global.output.go_type %> `json:"<%= action.resource.api_version.metadata_namespace %>"`
240
+ Meta *<%= action.metadata.global.output.go_type %> <%= go_json_tag(action.resource.api_version.metadata_namespace) %>
240
241
  <% end -%>
241
242
  }
242
243
 
@@ -247,7 +248,7 @@ type <%= action.go_response_type %> struct {
247
248
  // Action output encapsulated within a namespace
248
249
  Response *struct {
249
250
  // Global output metadata
250
- Meta *<%= action.metadata.global.output.go_type %> `json:"<%= action.resource.api_version.metadata_namespace %>"`
251
+ Meta *<%= action.metadata.global.output.go_type %> <%= go_json_tag(action.resource.api_version.metadata_namespace) %>
251
252
  }
252
253
  <% end -%>
253
254
  }
@@ -263,7 +264,7 @@ func (action *<%= action.go_type %>) Call() (*<%= action.go_response_type %>, er
263
264
  func (action *<%= action.go_type %>) Prepare() *<%= action.go_invocation_type%> {
264
265
  return &<%= action.go_invocation_type %>{
265
266
  Action: action,
266
- Path: "<%= action.path %>",
267
+ Path: <%= go_string_literal(action.path) %>,
267
268
  }
268
269
  }
269
270
 
@@ -292,7 +293,7 @@ func (inv *<%= action.go_invocation_type %>) SetPathParamInt(param string, value
292
293
 
293
294
  // SetPathParamString sets string path parameter
294
295
  func (inv *<%= action.go_invocation_type %>) SetPathParamString(param string, value string) *<%= action.go_invocation_type %> {
295
- inv.Path = strings.Replace(inv.Path, "{"+param+"}", value, 1)
296
+ inv.Path = strings.Replace(inv.Path, "{"+param+"}", url.PathEscape(value), 1)
296
297
  return inv
297
298
  }
298
299
  <% end -%>
@@ -371,23 +372,23 @@ func (inv *<%= action.go_invocation_type %>) validate() error {
371
372
  if inv.Input != nil {
372
373
  <% action.input.parameters.each do |p| -%>
373
374
  <% if %w(Float Datetime Resource).include?(p.type) -%>
374
- if inv.IsParameterSelected("<%= p.go_name %>") {
375
- if !inv.IsParameterNil("<%= p.go_name %>") {
375
+ if inv.IsParameterSelected(<%= go_string_literal(p.go_name) %>) {
376
+ if !inv.IsParameterNil(<%= go_string_literal(p.go_name) %>) {
376
377
  <% if p.type == 'Float' -%>
377
- if !isFiniteFloat64(inv.Input.<%= p.go_name %>) {
378
- verr.Add("<%= p.name %>", "not a valid float")
379
- }
378
+ if !isFiniteFloat64(inv.Input.<%= p.go_name %>) {
379
+ verr.Add(<%= go_string_literal(p.name) %>, "not a valid float")
380
+ }
380
381
  <% elsif p.type == 'Datetime' -%>
381
- normalized, ok := normalizeAndCheckDatetimeString(inv.Input.<%= p.go_name %>)
382
- if !ok {
383
- verr.Add("<%= p.name %>", "not a valid datetime")
384
- } else {
385
- inv.Input.<%= p.go_name %> = normalized
386
- }
382
+ normalized, ok := normalizeAndCheckDatetimeString(inv.Input.<%= p.go_name %>)
383
+ if !ok {
384
+ verr.Add(<%= go_string_literal(p.name) %>, "not a valid datetime")
385
+ } else {
386
+ inv.Input.<%= p.go_name %> = normalized
387
+ }
387
388
  <% elsif p.type == 'Resource' -%>
388
- if inv.Input.<%= p.go_name %> < 0 {
389
- verr.Add("<%= p.name %>", "not a valid resource id")
390
- }
389
+ if inv.Input.<%= p.go_name %> < 0 {
390
+ verr.Add(<%= go_string_literal(p.name) %>, "not a valid resource id")
391
+ }
391
392
  <% end -%>
392
393
  }
393
394
  }
@@ -399,23 +400,23 @@ func (inv *<%= action.go_invocation_type %>) validate() error {
399
400
  if inv.MetaInput != nil {
400
401
  <% action.metadata.global.input.parameters.each do |p| -%>
401
402
  <% if %w(Float Datetime Resource).include?(p.type) -%>
402
- if inv.IsMetaParameterSelected("<%= p.go_name %>") {
403
- if !inv.IsMetaParameterNil("<%= p.go_name %>") {
403
+ if inv.IsMetaParameterSelected(<%= go_string_literal(p.go_name) %>) {
404
+ if !inv.IsMetaParameterNil(<%= go_string_literal(p.go_name) %>) {
404
405
  <% if p.type == 'Float' -%>
405
- if !isFiniteFloat64(inv.MetaInput.<%= p.go_name %>) {
406
- verr.Add("<%= p.name %>", "not a valid float")
407
- }
406
+ if !isFiniteFloat64(inv.MetaInput.<%= p.go_name %>) {
407
+ verr.Add(<%= go_string_literal(p.name) %>, "not a valid float")
408
+ }
408
409
  <% elsif p.type == 'Datetime' -%>
409
- normalized, ok := normalizeAndCheckDatetimeString(inv.MetaInput.<%= p.go_name %>)
410
- if !ok {
411
- verr.Add("<%= p.name %>", "not a valid datetime")
412
- } else {
413
- inv.MetaInput.<%= p.go_name %> = normalized
414
- }
410
+ normalized, ok := normalizeAndCheckDatetimeString(inv.MetaInput.<%= p.go_name %>)
411
+ if !ok {
412
+ verr.Add(<%= go_string_literal(p.name) %>, "not a valid datetime")
413
+ } else {
414
+ inv.MetaInput.<%= p.go_name %> = normalized
415
+ }
415
416
  <% elsif p.type == 'Resource' -%>
416
- if inv.MetaInput.<%= p.go_name %> < 0 {
417
- verr.Add("<%= p.name %>", "not a valid resource id")
418
- }
417
+ if inv.MetaInput.<%= p.go_name %> < 0 {
418
+ verr.Add(<%= go_string_literal(p.name) %>, "not a valid resource id")
419
+ }
419
420
  <% end -%>
420
421
  }
421
422
  }
@@ -471,7 +472,7 @@ func (inv *<%= action.go_invocation_type %>) callAsBody() (*<%= action.go_respon
471
472
  input := make(map[string]interface{})
472
473
  <% end -%>
473
474
  resp := &<%= action.go_response_type %>{Action: inv.Action}
474
- err := inv.Action.Client.DoBodyRequest("<%= action.http_method %>", inv.Path, input, resp)
475
+ err := inv.Action.Client.DoBodyRequest(<%= go_string_literal(action.http_method) %>, inv.Path, input, resp)
475
476
  <% if action.has_output? -%>
476
477
  if err == nil && resp.Status {
477
478
  resp.Output = resp.Response.<%= action.output.go_namespace %>
@@ -563,15 +564,15 @@ func (resp *<%= action.go_response_type %>) CancelOperation() (*ActionActionStat
563
564
  func (inv *<%= action.go_invocation_type %>) convertInputToQueryParams(ret map[string]string) {
564
565
  if inv.Input != nil {
565
566
  <% action.input.parameters.each do |p| -%>
566
- if inv.IsParameterSelected("<%= p.go_name %>") {
567
+ if inv.IsParameterSelected(<%= go_string_literal(p.go_name) %>) {
567
568
  <% if p.nillable? -%>
568
- if inv.IsParameterNil("<%= p.go_name %>") {
569
- ret["<%= action.input.namespace %>[<%= p.name %>]"] = ""
569
+ if inv.IsParameterNil(<%= go_string_literal(p.go_name) %>) {
570
+ ret[<%= go_query_key(action.input.namespace, p.name) %>] = ""
570
571
  } else {
571
- ret["<%= action.input.namespace %>[<%= p.name %>]"] = <% if p.go_in_type == 'string' %>inv.Input.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.Input.<%= p.go_name %>)<% end %>
572
+ ret[<%= go_query_key(action.input.namespace, p.name) %>] = <% if p.go_in_type == 'string' %>inv.Input.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.Input.<%= p.go_name %>)<% end %>
572
573
  }
573
574
  <% else -%>
574
- ret["<%= action.input.namespace %>[<%= p.name %>]"] = <% if p.go_in_type == 'string' %>inv.Input.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.Input.<%= p.go_name %>)<% end %>
575
+ ret[<%= go_query_key(action.input.namespace, p.name) %>] = <% if p.go_in_type == 'string' %>inv.Input.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.Input.<%= p.go_name %>)<% end %>
575
576
  <% end -%>
576
577
  }
577
578
  <% end -%>
@@ -583,15 +584,15 @@ func (inv *<%= action.go_invocation_type %>) convertInputToQueryParams(ret map[s
583
584
  func (inv *<%= action.go_invocation_type %>) convertMetaInputToQueryParams(ret map[string]string) {
584
585
  if inv.MetaInput != nil {
585
586
  <% action.metadata.global.input.parameters.each do |p| -%>
586
- if inv.IsMetaParameterSelected("<%= p.go_name %>") {
587
+ if inv.IsMetaParameterSelected(<%= go_string_literal(p.go_name) %>) {
587
588
  <% if p.nillable? -%>
588
- if inv.IsMetaParameterNil("<%= p.go_name %>") {
589
- ret["<%= action.resource.api_version.metadata_namespace %>[<%= p.name %>]"] = ""
589
+ if inv.IsMetaParameterNil(<%= go_string_literal(p.go_name) %>) {
590
+ ret[<%= go_query_key(action.resource.api_version.metadata_namespace, p.name) %>] = ""
590
591
  } else {
591
- ret["<%= action.resource.api_version.metadata_namespace %>[<%= p.name %>]"] = <% if p.go_in_type == 'string' %>inv.MetaInput.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.MetaInput.<%= p.go_name %>)<% end %>
592
+ ret[<%= go_query_key(action.resource.api_version.metadata_namespace, p.name) %>] = <% if p.go_in_type == 'string' %>inv.MetaInput.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.MetaInput.<%= p.go_name %>)<% end %>
592
593
  }
593
594
  <% else -%>
594
- ret["<%= action.resource.api_version.metadata_namespace %>[<%= p.name %>]"] = <% if p.go_in_type == 'string' %>inv.MetaInput.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.MetaInput.<%= p.go_name %>)<% end %>
595
+ ret[<%= go_query_key(action.resource.api_version.metadata_namespace, p.name) %>] = <% if p.go_in_type == 'string' %>inv.MetaInput.<%= p.go_name %><% else %>convert<%= p.go_in_type.capitalize %>ToString(inv.MetaInput.<%= p.go_name %>)<% end %>
595
596
  <% end -%>
596
597
  }
597
598
  <% end -%>
@@ -617,15 +618,15 @@ func (inv *<%= action.go_invocation_type %>) makeInputParams() map[string]interf
617
618
 
618
619
  if inv.Input != nil {
619
620
  <% action.input.parameters.each do |p| -%>
620
- if inv.IsParameterSelected("<%= p.go_name %>") {
621
+ if inv.IsParameterSelected(<%= go_string_literal(p.go_name) %>) {
621
622
  <% if p.nillable? -%>
622
- if inv.IsParameterNil("<%= p.go_name %>") {
623
- ret["<%= p.name %>"] = nil
623
+ if inv.IsParameterNil(<%= go_string_literal(p.go_name) %>) {
624
+ ret[<%= go_string_literal(p.name) %>] = nil
624
625
  } else {
625
- ret["<%= p.name %>"] = inv.Input.<%= p.go_name %>
626
+ ret[<%= go_string_literal(p.name) %>] = inv.Input.<%= p.go_name %>
626
627
  }
627
628
  <% else -%>
628
- ret["<%= p.name %>"] = inv.Input.<%= p.go_name %>
629
+ ret[<%= go_string_literal(p.name) %>] = inv.Input.<%= p.go_name %>
629
630
  <% end -%>
630
631
  }
631
632
  <% end -%>
@@ -641,15 +642,15 @@ func (inv *<%= action.go_invocation_type %>) makeInputParams() map[string]interf
641
642
 
642
643
  if inv.MetaInput != nil {
643
644
  <% action.metadata.global.input.parameters.each do |p| -%>
644
- if inv.IsMetaParameterSelected("<%= p.go_name %>") {
645
+ if inv.IsMetaParameterSelected(<%= go_string_literal(p.go_name) %>) {
645
646
  <% if p.nillable? -%>
646
- if inv.IsMetaParameterNil("<%= p.go_name %>") {
647
- ret["<%= p.name %>"] = nil
647
+ if inv.IsMetaParameterNil(<%= go_string_literal(p.go_name) %>) {
648
+ ret[<%= go_string_literal(p.name) %>] = nil
648
649
  } else {
649
- ret["<%= p.name %>"] = inv.MetaInput.<%= p.go_name %>
650
+ ret[<%= go_string_literal(p.name) %>] = inv.MetaInput.<%= p.go_name %>
650
651
  }
651
652
  <% else -%>
652
- ret["<%= p.name %>"] = inv.MetaInput.<%= p.go_name %>
653
+ ret[<%= go_string_literal(p.name) %>] = inv.MetaInput.<%= p.go_name %>
653
654
  <% end -%>
654
655
  }
655
656
  <% end -%>
@@ -3,6 +3,8 @@ package <%= package %>
3
3
  import (
4
4
  "fmt"
5
5
  "net/http"
6
+ "net/url"
7
+ "strings"
6
8
  )
7
9
 
8
10
  type OAuth2Auth struct {
@@ -11,32 +13,42 @@ type OAuth2Auth struct {
11
13
  }
12
14
 
13
15
  func (auth *OAuth2Auth) Authenticate(request *http.Request) {
14
- request.Header.Set("<%= auth.http_header %>", auth.AccessToken)
16
+ request.Header.Set(<%= go_string_literal(auth.http_header) %>, auth.AccessToken)
15
17
  }
16
18
 
17
- // SetExistingTokenAuth will use a previously acquired access token
19
+ // SetExistingOAuth2Auth will use a previously acquired access token
18
20
  func (client *Client) SetExistingOAuth2Auth(accessToken string) {
19
21
  client.Authentication = &OAuth2Auth{
20
22
  AccessToken: accessToken,
21
23
  }
22
24
  }
23
25
 
24
- // RevokeAuthToken will revoke the access token and remove authentication
26
+ // RevokeAccessToken will revoke the access token and remove authentication
25
27
  // from the client
26
28
  func (client *Client) RevokeAccessToken() error {
27
- httpClient := &http.Client{}
29
+ auth, ok := client.Authentication.(*OAuth2Auth)
30
+ if !ok {
31
+ return fmt.Errorf("OAuth2 authentication is not configured")
32
+ }
28
33
 
29
- req, err := http.NewRequest("POST", "<%= auth.revoke_url %>", nil)
34
+ form := url.Values{}
35
+ form.Set("token", auth.AccessToken)
30
36
 
37
+ revokeURL, err := client.descriptionURL(<%= go_string_literal(auth.revoke_url) %>)
31
38
  if err != nil {
32
39
  return err
33
40
  }
34
41
 
35
- if client.Authentication != nil {
36
- client.Authentication.Authenticate(req)
42
+ req, err := http.NewRequest("POST", revokeURL, strings.NewReader(form.Encode()))
43
+
44
+ if err != nil {
45
+ return err
37
46
  }
38
47
 
39
- resp, err := httpClient.Do(req)
48
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
49
+ auth.Authenticate(req)
50
+
51
+ resp, err := client.do(req)
40
52
 
41
53
  if err != nil {
42
54
  return err
@@ -8,10 +8,10 @@ import (
8
8
  type Mode int
9
9
 
10
10
  const (
11
- // Send the token via HTTP header <%= auth.http_header %>
11
+ // Send the token via HTTP header <%= go_comment_text(auth.http_header) %>
12
12
  HttpHeader Mode = iota
13
13
 
14
- // Send the token via query parameter <%= auth.query_parameter %>
14
+ // Send the token via query parameter <%= go_comment_text(auth.query_parameter) %>
15
15
  QueryParameter = iota
16
16
  )
17
17
 
@@ -29,11 +29,11 @@ type TokenAuth struct {
29
29
  func (auth *TokenAuth) Authenticate(request *http.Request) {
30
30
  switch auth.Mode {
31
31
  case HttpHeader:
32
- request.Header.Set("<%= auth.http_header %>", auth.Token)
32
+ request.Header.Set(<%= go_string_literal(auth.http_header) %>, auth.Token)
33
33
 
34
34
  case QueryParameter:
35
35
  q := request.URL.Query()
36
- q.Add("<%= auth.query_parameter %>", auth.Token)
36
+ q.Add(<%= go_string_literal(auth.query_parameter) %>, auth.Token)
37
37
  request.URL.RawQuery = q.Encode()
38
38
  }
39
39
  }
@@ -95,20 +95,20 @@ func (auth *TokenAuth) setDefaultOptions(options *TokenAuthOptions) {
95
95
  // the authentication is completed
96
96
  func (auth *TokenAuth) nextAuthenticationStep(options *TokenAuthOptions, action string, token string) error {
97
97
  <% auth.custom_actions.each do |a| -%>
98
- if action == "<%= a.name %>" {
99
- action := auth.Resource.<%= a.go_name %>.Prepare()
100
- input := action.NewInput()
98
+ if action == <%= go_string_literal(a.name) %> {
99
+ request := auth.Resource.<%= a.go_name %>.Prepare()
100
+ input := request.NewInput()
101
101
  input.SetToken(token)
102
102
 
103
103
  if options.<%= "#{a.go_name}Callback" %> == nil {
104
- return fmt.Errorf("Implement callback <%= "#{a.go_name}Callback" %>")
104
+ return fmt.Errorf(<%= go_string_literal("Implement callback #{a.go_name}Callback") %>)
105
105
  }
106
106
 
107
107
  if err := options.<%= "#{a.go_name}Callback" %>(input); err != nil {
108
- return fmt.Errorf("<%= "#{a.go_name}Callback" %> failed: %v", err)
108
+ return fmt.Errorf(<%= go_string_literal("#{a.go_name}Callback failed: %v") %>, err)
109
109
  }
110
110
 
111
- resp, err := action.Call()
111
+ resp, err := request.Call()
112
112
 
113
113
  if err != nil {
114
114
  return err
@@ -1,5 +1,10 @@
1
1
  package <%= package %>
2
2
 
3
+ import (
4
+ "net/http"
5
+ "time"
6
+ )
7
+
3
8
  // Client represents a connection to an API server
4
9
  type Client struct {
5
10
  // API URL
@@ -8,15 +13,20 @@ type Client struct {
8
13
  // Options for authentication method
9
14
  Authentication Authenticator
10
15
 
16
+ httpClient *http.Client
17
+
11
18
  <% api.resources.each do |r| -%>
12
- // Resource <%= r.full_dot_name %>
19
+ // Resource <%= go_comment_text(r.full_dot_name) %>
13
20
  <%= r.go_name %> *<%= r.go_type %>
14
21
  <% end -%>
15
22
  }
16
23
 
17
24
  // Create a new client for API at url
18
25
  func New(url string) *Client {
19
- c := &Client{Url: url}
26
+ c := &Client{
27
+ Url: url,
28
+ httpClient: http.DefaultClient,
29
+ }
20
30
 
21
31
  <% api.resources.each do |r| -%>
22
32
  c.<%= r.go_name %> = New<%= r.go_type %>(c)
@@ -24,3 +34,32 @@ func New(url string) *Client {
24
34
 
25
35
  return c
26
36
  }
37
+
38
+ // SetHTTPClient configures the HTTP client used for all requests.
39
+ func (client *Client) SetHTTPClient(httpClient *http.Client) {
40
+ if httpClient == nil {
41
+ client.httpClient = http.DefaultClient
42
+ return
43
+ }
44
+
45
+ client.httpClient = httpClient
46
+ }
47
+
48
+ // SetTimeout configures an overall timeout for all HTTP requests.
49
+ func (client *Client) SetTimeout(timeout time.Duration) {
50
+ if client.httpClient == nil || client.httpClient == http.DefaultClient {
51
+ client.httpClient = &http.Client{Timeout: timeout}
52
+ return
53
+ }
54
+
55
+ client.httpClient.Timeout = timeout
56
+ }
57
+
58
+ func (client *Client) do(req *http.Request) (*http.Response, error) {
59
+ httpClient := client.httpClient
60
+ if httpClient == nil {
61
+ httpClient = http.DefaultClient
62
+ }
63
+
64
+ return httpClient.Do(req)
65
+ }
@@ -3,17 +3,116 @@ package <%= package %>
3
3
  import (
4
4
  "bytes"
5
5
  "encoding/json"
6
+ "fmt"
6
7
  "io/ioutil"
7
8
  "net/http"
9
+ "net/url"
10
+ "strings"
8
11
  )
9
12
 
13
+ func (client *Client) actionURL(path string) (string, error) {
14
+ if !strings.HasPrefix(path, "/") || strings.HasPrefix(path, "//") {
15
+ return "", fmt.Errorf("unsafe API action path %q", path)
16
+ }
17
+
18
+ ref, err := url.Parse(path)
19
+ if err != nil {
20
+ return "", err
21
+ }
22
+
23
+ if ref.IsAbs() || ref.Host != "" || ref.User != nil {
24
+ return "", fmt.Errorf("unsafe API action path %q", path)
25
+ }
26
+
27
+ return client.sameOriginURL(client.Url + path)
28
+ }
29
+
30
+ func (client *Client) descriptionURL(rawURL string) (string, error) {
31
+ base, err := client.parsedBaseURL()
32
+ if err != nil {
33
+ return "", err
34
+ }
35
+
36
+ ref, err := url.Parse(rawURL)
37
+ if err != nil {
38
+ return "", err
39
+ }
40
+
41
+ if ref.User != nil {
42
+ return "", fmt.Errorf("unsafe API description URL %q", rawURL)
43
+ }
44
+
45
+ resolved := base.ResolveReference(ref)
46
+ if !sameOrigin(base, resolved) {
47
+ return "", fmt.Errorf("API description URL %q is outside client origin", rawURL)
48
+ }
49
+
50
+ return resolved.String(), nil
51
+ }
52
+
53
+ func (client *Client) sameOriginURL(rawURL string) (string, error) {
54
+ base, err := client.parsedBaseURL()
55
+ if err != nil {
56
+ return "", err
57
+ }
58
+
59
+ resolved, err := url.Parse(rawURL)
60
+ if err != nil {
61
+ return "", err
62
+ }
63
+
64
+ if !sameOrigin(base, resolved) {
65
+ return "", fmt.Errorf("request URL %q is outside client origin", rawURL)
66
+ }
67
+
68
+ return resolved.String(), nil
69
+ }
70
+
71
+ func (client *Client) parsedBaseURL() (*url.URL, error) {
72
+ base, err := url.Parse(client.Url)
73
+ if err != nil {
74
+ return nil, err
75
+ }
76
+
77
+ if base.Scheme == "" || base.Host == "" {
78
+ return nil, fmt.Errorf("invalid client URL %q", client.Url)
79
+ }
80
+
81
+ return base, nil
82
+ }
83
+
84
+ func sameOrigin(a *url.URL, b *url.URL) bool {
85
+ return strings.EqualFold(a.Scheme, b.Scheme) &&
86
+ strings.EqualFold(a.Hostname(), b.Hostname()) &&
87
+ originPort(a) == originPort(b)
88
+ }
89
+
90
+ func originPort(u *url.URL) string {
91
+ port := u.Port()
92
+ if port != "" {
93
+ return port
94
+ }
95
+
96
+ switch strings.ToLower(u.Scheme) {
97
+ case "http":
98
+ return "80"
99
+ case "https":
100
+ return "443"
101
+ default:
102
+ return ""
103
+ }
104
+ }
105
+
10
106
  // DoQueryStringRequests makes a HTTP requests in which input parameters are
11
107
  // sent as query parameters.
12
108
  func (client *Client) DoQueryStringRequest(path string, queryParams map[string]string, output interface{}) error {
13
- httpClient := &http.Client{}
14
- url := client.Url + path
109
+ requestURL, err := client.actionURL(path)
110
+
111
+ if err != nil {
112
+ return err
113
+ }
15
114
 
16
- req, err := http.NewRequest("GET", url, nil)
115
+ req, err := http.NewRequest("GET", requestURL, nil)
17
116
 
18
117
  if err != nil {
19
118
  return err
@@ -31,7 +130,7 @@ func (client *Client) DoQueryStringRequest(path string, queryParams map[string]s
31
130
 
32
131
  req.URL.RawQuery = q.Encode()
33
132
 
34
- resp, err := httpClient.Do(req)
133
+ resp, err := client.do(req)
35
134
 
36
135
  if err != nil {
37
136
  return err
@@ -54,8 +153,7 @@ func (client *Client) DoQueryStringRequest(path string, queryParams map[string]s
54
153
  // DoBodyRequest makes a HTTP requests in which the input parameters are sent
55
154
  // within the request body, encoded in JSON.
56
155
  func (client *Client) DoBodyRequest(method string, path string, params interface{}, output interface{}) error {
57
- httpClient := &http.Client{}
58
- url := client.Url + path
156
+ requestURL, err := client.actionURL(path)
59
157
 
60
158
  jsonData, err := json.Marshal(params)
61
159
 
@@ -63,7 +161,7 @@ func (client *Client) DoBodyRequest(method string, path string, params interface
63
161
  return err
64
162
  }
65
163
 
66
- req, err := http.NewRequest(method, url, bytes.NewBuffer(jsonData))
164
+ req, err := http.NewRequest(method, requestURL, bytes.NewBuffer(jsonData))
67
165
 
68
166
  if err != nil {
69
167
  return err
@@ -75,7 +173,7 @@ func (client *Client) DoBodyRequest(method string, path string, params interface
75
173
  client.Authentication.Authenticate(req)
76
174
  }
77
175
 
78
- resp, err := httpClient.Do(req)
176
+ resp, err := client.do(req)
79
177
 
80
178
  if err != nil {
81
179
  return err