haveapi-go-client 0.27.3 → 0.28.1

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.
@@ -3,17 +3,180 @@ 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
+ return client.descriptionURLWithTrustedOrigins(rawURL, nil)
32
+ }
33
+
34
+ func (client *Client) oauth2DescriptionURL(rawURL string) (string, error) {
35
+ return client.descriptionURLWithTrustedOrigins(rawURL, client.oauth2TrustedOrigins)
36
+ }
37
+
38
+ // AllowOAuth2Origin permits OAuth2 endpoints from an additional trusted origin.
39
+ func (client *Client) AllowOAuth2Origin(rawOrigin string) error {
40
+ origin, err := parseTrustedOrigin(rawOrigin)
41
+ if err != nil {
42
+ return err
43
+ }
44
+
45
+ if client.oauth2TrustedOrigins == nil {
46
+ client.oauth2TrustedOrigins = make(map[string]struct{})
47
+ }
48
+
49
+ client.oauth2TrustedOrigins[origin] = struct{}{}
50
+ return nil
51
+ }
52
+
53
+ func (client *Client) descriptionURLWithTrustedOrigins(rawURL string, trustedOrigins map[string]struct{}) (string, error) {
54
+ base, err := client.parsedBaseURL()
55
+ if err != nil {
56
+ return "", err
57
+ }
58
+
59
+ ref, err := url.Parse(rawURL)
60
+ if err != nil {
61
+ return "", err
62
+ }
63
+
64
+ if ref.User != nil {
65
+ return "", fmt.Errorf("unsafe API description URL %q", rawURL)
66
+ }
67
+
68
+ if ref.Host != "" && ref.Scheme == "" {
69
+ return "", fmt.Errorf("unsafe API description URL %q", rawURL)
70
+ }
71
+
72
+ resolved := base.ResolveReference(ref)
73
+ if !sameOrigin(base, resolved) && !originAllowed(resolved, trustedOrigins) {
74
+ return "", fmt.Errorf("API description URL %q is outside client origin", rawURL)
75
+ }
76
+
77
+ return resolved.String(), nil
78
+ }
79
+
80
+ func (client *Client) sameOriginURL(rawURL string) (string, error) {
81
+ base, err := client.parsedBaseURL()
82
+ if err != nil {
83
+ return "", err
84
+ }
85
+
86
+ resolved, err := url.Parse(rawURL)
87
+ if err != nil {
88
+ return "", err
89
+ }
90
+
91
+ if !sameOrigin(base, resolved) {
92
+ return "", fmt.Errorf("request URL %q is outside client origin", rawURL)
93
+ }
94
+
95
+ return resolved.String(), nil
96
+ }
97
+
98
+ func (client *Client) parsedBaseURL() (*url.URL, error) {
99
+ base, err := url.Parse(client.Url)
100
+ if err != nil {
101
+ return nil, err
102
+ }
103
+
104
+ if base.Scheme == "" || base.Host == "" {
105
+ return nil, fmt.Errorf("invalid client URL %q", client.Url)
106
+ }
107
+
108
+ return base, nil
109
+ }
110
+
111
+ func sameOrigin(a *url.URL, b *url.URL) bool {
112
+ return strings.EqualFold(a.Scheme, b.Scheme) &&
113
+ strings.EqualFold(a.Hostname(), b.Hostname()) &&
114
+ originPort(a) == originPort(b)
115
+ }
116
+
117
+ func originAllowed(u *url.URL, trustedOrigins map[string]struct{}) bool {
118
+ if len(trustedOrigins) == 0 {
119
+ return false
120
+ }
121
+
122
+ _, ok := trustedOrigins[originKey(u)]
123
+ return ok
124
+ }
125
+
126
+ func parseTrustedOrigin(rawOrigin string) (string, error) {
127
+ if rawOrigin == "" || strings.ContainsAny(rawOrigin, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\\") {
128
+ return "", fmt.Errorf("invalid trusted OAuth2 origin %q", rawOrigin)
129
+ }
130
+
131
+ parsed, err := url.Parse(rawOrigin)
132
+ if err != nil {
133
+ return "", err
134
+ }
135
+
136
+ if parsed.Scheme == "" || parsed.Host == "" || parsed.User != nil ||
137
+ (parsed.Path != "" && parsed.Path != "/") ||
138
+ parsed.RawQuery != "" || parsed.Fragment != "" {
139
+ return "", fmt.Errorf("invalid trusted OAuth2 origin %q", rawOrigin)
140
+ }
141
+
142
+ return originKey(parsed), nil
143
+ }
144
+
145
+ func originKey(u *url.URL) string {
146
+ host := strings.ToLower(u.Hostname())
147
+ if strings.Contains(host, ":") {
148
+ host = "[" + host + "]"
149
+ }
150
+
151
+ return strings.ToLower(u.Scheme) + "://" + host + ":" + originPort(u)
152
+ }
153
+
154
+ func originPort(u *url.URL) string {
155
+ port := u.Port()
156
+ if port != "" {
157
+ return port
158
+ }
159
+
160
+ switch strings.ToLower(u.Scheme) {
161
+ case "http":
162
+ return "80"
163
+ case "https":
164
+ return "443"
165
+ default:
166
+ return ""
167
+ }
168
+ }
169
+
10
170
  // DoQueryStringRequests makes a HTTP requests in which input parameters are
11
171
  // sent as query parameters.
12
172
  func (client *Client) DoQueryStringRequest(path string, queryParams map[string]string, output interface{}) error {
13
- httpClient := &http.Client{}
14
- url := client.Url + path
173
+ requestURL, err := client.actionURL(path)
174
+
175
+ if err != nil {
176
+ return err
177
+ }
15
178
 
16
- req, err := http.NewRequest("GET", url, nil)
179
+ req, err := http.NewRequest("GET", requestURL, nil)
17
180
 
18
181
  if err != nil {
19
182
  return err
@@ -31,7 +194,7 @@ func (client *Client) DoQueryStringRequest(path string, queryParams map[string]s
31
194
 
32
195
  req.URL.RawQuery = q.Encode()
33
196
 
34
- resp, err := httpClient.Do(req)
197
+ resp, err := client.do(req)
35
198
 
36
199
  if err != nil {
37
200
  return err
@@ -54,8 +217,7 @@ func (client *Client) DoQueryStringRequest(path string, queryParams map[string]s
54
217
  // DoBodyRequest makes a HTTP requests in which the input parameters are sent
55
218
  // within the request body, encoded in JSON.
56
219
  func (client *Client) DoBodyRequest(method string, path string, params interface{}, output interface{}) error {
57
- httpClient := &http.Client{}
58
- url := client.Url + path
220
+ requestURL, err := client.actionURL(path)
59
221
 
60
222
  jsonData, err := json.Marshal(params)
61
223
 
@@ -63,7 +225,7 @@ func (client *Client) DoBodyRequest(method string, path string, params interface
63
225
  return err
64
226
  }
65
227
 
66
- req, err := http.NewRequest(method, url, bytes.NewBuffer(jsonData))
228
+ req, err := http.NewRequest(method, requestURL, bytes.NewBuffer(jsonData))
67
229
 
68
230
  if err != nil {
69
231
  return err
@@ -75,7 +237,7 @@ func (client *Client) DoBodyRequest(method string, path string, params interface
75
237
  client.Authentication.Authenticate(req)
76
238
  }
77
239
 
78
- resp, err := httpClient.Do(req)
240
+ resp, err := client.do(req)
79
241
 
80
242
  if err != nil {
81
243
  return err
@@ -1,17 +1,17 @@
1
1
  package <%= package %>
2
2
 
3
- // Type for resource <%= resource.full_dot_name %>
3
+ // Type for resource <%= go_comment_text(resource.full_dot_name) %>
4
4
  type <%= resource.go_type %> struct {
5
5
  // Pointer to client
6
6
  Client *Client
7
7
 
8
8
  <% resource.resources.each do |r| -%>
9
- // Resource <%= r.full_dot_name %>
9
+ // Resource <%= go_comment_text(r.full_dot_name) %>
10
10
  <%= r.go_name %> *<%= r.go_type %>
11
11
  <% end -%>
12
12
  <% resource.actions.each do |a| -%>
13
13
  <% a.all_names do |go_name| -%>
14
- // Action <%= a.full_dot_name %>
14
+ // Action <%= go_comment_text(a.full_dot_name) %>
15
15
  <%= go_name %> *<%= a.go_type %>
16
16
  <% end -%>
17
17
  <% end -%>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi-go-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.3
4
+ version: 0.28.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.27.3
18
+ version: 0.28.1
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.27.3
25
+ version: 0.28.1
26
26
  description: Go client generator
27
27
  email:
28
28
  - jakub.skokan@vpsfree.cz
@@ -60,7 +60,6 @@ files:
60
60
  - lib/haveapi/go_client/resource.rb
61
61
  - lib/haveapi/go_client/utils.rb
62
62
  - lib/haveapi/go_client/version.rb
63
- - shell.nix
64
63
  - spec/integration/generator_spec.rb
65
64
  - spec/spec_helper.rb
66
65
  - spec/support/test_server.rb
data/shell.nix DELETED
@@ -1,23 +0,0 @@
1
- let
2
- pkgs = import <nixpkgs> {};
3
- stdenv = pkgs.stdenv;
4
-
5
- in stdenv.mkDerivation rec {
6
- name = "haveapi-go-client";
7
-
8
- buildInputs = with pkgs;[
9
- git
10
- go
11
- gotools
12
- openssl
13
- ruby_3_3
14
- ];
15
-
16
- shellHook = ''
17
- export GEM_HOME=$(pwd)/.gems
18
- export PATH="$GEM_HOME/.gems/bin:$PATH"
19
- gem install bundler
20
- bundler install
21
- export RUBYOPT=-rbundler/setup
22
- '';
23
- }