x 0.9.0 → 0.9.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +8 -0
- data/lib/x/oauth_authenticator.rb +4 -8
- data/lib/x/request_builder.rb +10 -5
- data/lib/x/response_handler.rb +12 -8
- data/lib/x/version.rb +1 -1
- data/sig/x.rbs +12 -11
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2906018cf3e05342abe1bc6c938f3d1b3cf9d1d84c3813a96a11b693fbe0960
|
4
|
+
data.tar.gz: f84f47e1a9ea06b101712ae1f9fd7198d71b2cbc7487a654b8442dd13e3244e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c98c3ea7e22d0b023a328207c9599dca0f74b54d5ed05eea04378c5c2ed5a2803799b7dcafa54d041d3b7dac8b3e08c8559d4cacb03b2419796368fa153401e
|
7
|
+
data.tar.gz: 36c0faa98a5f6657a88ce770924e2669f91fcea2985b38f1c82dc0766d0c5a5cf6a4b0342d4684f5b679b41dc76f5fa94b791a6468b6f0514c28f6d70864b41a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.9.1] - 2023-10-06
|
4
|
+
|
5
|
+
- Allow successful empty responses (06bf7db)
|
6
|
+
- Update default User-Agent string (296b36a)
|
7
|
+
- Move query parameter escaping into RequestBuilder (56d6bd2)
|
8
|
+
|
3
9
|
## [0.9.0] - 2023-09-26
|
4
10
|
|
5
11
|
- Add support for HTTP proxies (3740f4f)
|
data/README.md
CHANGED
@@ -90,6 +90,14 @@ Building and maintaining an open-source project like this takes a considerable a
|
|
90
90
|
|
91
91
|
[Click here to sponsor this project.](https://github.com/sponsors/sferik)
|
92
92
|
|
93
|
+
## Sponsors
|
94
|
+
|
95
|
+
Many thanks to our sponsors (listed in order of when they sponsored this project):
|
96
|
+
|
97
|
+
<a href="https://betterstack.com"><img src="https://raw.githubusercontent.com/sferik/x-ruby/main/sponsor_logos/better_stack.svg" alt="Better Stack" width="200" align="middle"></a>
|
98
|
+
<img src="https://raw.githubusercontent.com/sferik/x-ruby/main/sponsor_logos/spacer.png" width="20" align="middle">
|
99
|
+
<a href="https://sentry.io"><img src="https://raw.githubusercontent.com/sferik/x-ruby/main/sponsor_logos/sentry.svg" alt="Sentry" width="200" align="middle"></a>
|
100
|
+
|
93
101
|
## Development
|
94
102
|
|
95
103
|
1. Checkout and repo:
|
@@ -72,22 +72,18 @@ module X
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def signature_base_string(method, url, params)
|
75
|
-
"#{method}&#{
|
76
|
-
end
|
77
|
-
|
78
|
-
def encode_params(params)
|
79
|
-
params.sort.map { |k, v| "#{k}=#{encode(v.to_s)}" }.join("&")
|
75
|
+
"#{method}&#{escape(url)}&#{escape(URI.encode_www_form(params.sort))}"
|
80
76
|
end
|
81
77
|
|
82
78
|
def signing_key
|
83
|
-
"#{
|
79
|
+
"#{escape(api_key_secret)}&#{escape(access_token_secret)}"
|
84
80
|
end
|
85
81
|
|
86
82
|
def format_oauth_header(params)
|
87
|
-
"OAuth #{params.sort.map { |k, v| "#{k}=\"#{
|
83
|
+
"OAuth #{params.sort.map { |k, v| "#{k}=\"#{escape(v.to_s)}\"" }.join(", ")}"
|
88
84
|
end
|
89
85
|
|
90
|
-
def
|
86
|
+
def escape(value)
|
91
87
|
# TODO: Replace CGI.escape with CGI.escapeURIComponent when support for Ruby 3.1 is dropped
|
92
88
|
CGI.escape(value.to_s).gsub("+", "%20")
|
93
89
|
end
|
data/lib/x/request_builder.rb
CHANGED
@@ -12,7 +12,7 @@ module X
|
|
12
12
|
delete: Net::HTTP::Delete
|
13
13
|
}.freeze
|
14
14
|
DEFAULT_CONTENT_TYPE = "application/json; charset=utf-8".freeze
|
15
|
-
DEFAULT_USER_AGENT = "X-Client/#{VERSION}
|
15
|
+
DEFAULT_USER_AGENT = "X-Client/#{VERSION} #{RUBY_ENGINE}/#{RUBY_VERSION} (#{RUBY_PLATFORM})".freeze
|
16
16
|
AUTHORIZATION_HEADER = "Authorization".freeze
|
17
17
|
CONTENT_TYPE_HEADER = "Content-Type".freeze
|
18
18
|
USER_AGENT_HEADER = "User-Agent".freeze
|
@@ -24,8 +24,8 @@ module X
|
|
24
24
|
@user_agent = user_agent
|
25
25
|
end
|
26
26
|
|
27
|
-
def build(authenticator, http_method,
|
28
|
-
request = create_request(http_method,
|
27
|
+
def build(authenticator, http_method, uri, body: nil)
|
28
|
+
request = create_request(http_method, uri, body)
|
29
29
|
add_authorization(request, authenticator)
|
30
30
|
add_content_type(request)
|
31
31
|
add_user_agent(request)
|
@@ -34,12 +34,13 @@ module X
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
-
def create_request(http_method,
|
37
|
+
def create_request(http_method, uri, body)
|
38
38
|
http_method_class = HTTP_METHODS[http_method]
|
39
39
|
|
40
40
|
raise ArgumentError, "Unsupported HTTP method: #{http_method}" unless http_method_class
|
41
41
|
|
42
|
-
|
42
|
+
escaped_uri = escape_query_params(uri)
|
43
|
+
request = http_method_class.new(escaped_uri)
|
43
44
|
request.body = body if body && http_method != :get
|
44
45
|
request
|
45
46
|
end
|
@@ -55,5 +56,9 @@ module X
|
|
55
56
|
def add_user_agent(request)
|
56
57
|
request.add_field(USER_AGENT_HEADER, user_agent) if user_agent
|
57
58
|
end
|
59
|
+
|
60
|
+
def escape_query_params(uri)
|
61
|
+
URI(uri).tap { |u| u.query = URI.encode_www_form(URI.decode_www_form(uri.query)) if uri.query }
|
62
|
+
end
|
58
63
|
end
|
59
64
|
end
|
data/lib/x/response_handler.rb
CHANGED
@@ -32,19 +32,23 @@ module X
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def handle(response)
|
35
|
-
if
|
36
|
-
|
35
|
+
if success?(response)
|
36
|
+
JSON.parse(response.body, array_class: array_class, object_class: object_class) if json?(response)
|
37
|
+
else
|
38
|
+
error_class = ERROR_CLASSES[response.code.to_i] || Error
|
39
|
+
error_message = "#{response.code} #{response.message}"
|
40
|
+
raise error_class.new(error_message, response: response)
|
37
41
|
end
|
38
|
-
|
39
|
-
error_class = ERROR_CLASSES[response.code.to_i] || Error
|
40
|
-
error_message = "#{response.code} #{response.message}"
|
41
|
-
raise error_class.new(error_message, response: response)
|
42
42
|
end
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
def
|
47
|
-
response.is_a?(Net::HTTPSuccess)
|
46
|
+
def success?(response)
|
47
|
+
response.is_a?(Net::HTTPSuccess)
|
48
|
+
end
|
49
|
+
|
50
|
+
def json?(response)
|
51
|
+
response.body && JSON_CONTENT_TYPE_REGEXP.match?(response["content-type"])
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
data/lib/x/version.rb
CHANGED
data/sig/x.rbs
CHANGED
@@ -28,10 +28,9 @@ module X
|
|
28
28
|
def generate_signature: (String method, String url, Hash[String, String] params) -> String
|
29
29
|
def hmac_signature: (String base_string) -> String
|
30
30
|
def signature_base_string: (String method, String url, Hash[String, String] params) -> String
|
31
|
-
def encode_params: (Hash[String, String] params) -> String
|
32
31
|
def signing_key: -> String
|
33
32
|
def format_oauth_header: (Hash[String, String] params) -> String
|
34
|
-
def
|
33
|
+
def escape: (String value) -> String
|
35
34
|
end
|
36
35
|
|
37
36
|
class Error < StandardError
|
@@ -121,13 +120,14 @@ module X
|
|
121
120
|
attr_accessor content_type: String
|
122
121
|
attr_accessor user_agent: String
|
123
122
|
def initialize: (?content_type: String, ?user_agent: String) -> void
|
124
|
-
def build: (BearerTokenAuthenticator | OauthAuthenticator authenticator, Symbol http_method, URI::Generic
|
123
|
+
def build: (BearerTokenAuthenticator | OauthAuthenticator authenticator, Symbol http_method, URI::Generic uri, ?body: String?) -> (Net::HTTPRequest)
|
125
124
|
|
126
125
|
private
|
127
|
-
def create_request: (Symbol http_method, URI::Generic
|
126
|
+
def create_request: (Symbol http_method, URI::Generic uri, String? body) -> (Net::HTTPRequest)
|
128
127
|
def add_authorization: (Net::HTTPRequest request, BearerTokenAuthenticator | OauthAuthenticator authenticator) -> void
|
129
128
|
def add_content_type: (Net::HTTPRequest request) -> void
|
130
129
|
def add_user_agent: (Net::HTTPRequest request) -> void
|
130
|
+
def escape_query_params: (URI::Generic uri) -> URI::Generic
|
131
131
|
end
|
132
132
|
|
133
133
|
class RedirectHandler
|
@@ -155,10 +155,11 @@ module X
|
|
155
155
|
attr_accessor array_class: Class
|
156
156
|
attr_accessor object_class: Class
|
157
157
|
def initialize: (?array_class: Class, ?object_class: Class) -> void
|
158
|
-
def handle: (Net::HTTPResponse response) -> Hash[String, untyped]
|
158
|
+
def handle: (Net::HTTPResponse response) -> Hash[String, untyped]?
|
159
159
|
|
160
160
|
private
|
161
|
-
def
|
161
|
+
def success?: (Net::HTTPResponse response) -> bool
|
162
|
+
def json?: (Net::HTTPResponse response) -> bool
|
162
163
|
end
|
163
164
|
|
164
165
|
class Client
|
@@ -171,13 +172,13 @@ module X
|
|
171
172
|
|
172
173
|
attr_reader base_uri: URI::Generic
|
173
174
|
def initialize: (?bearer_token: String?, ?api_key: String?, ?api_key_secret: String?, ?access_token: String?, ?access_token_secret: String?, ?base_url: URI::Generic | String, ?content_type: String, ?user_agent: String, ?open_timeout: Float | Integer, ?read_timeout: Float | Integer, ?write_timeout: Float | Integer, ?proxy_url: URI::Generic? | String?, ?debug_output: IO?, ?array_class: Class, ?object_class: Class, ?max_redirects: Integer) -> void
|
174
|
-
def get: (String endpoint) -> Hash[String, untyped]
|
175
|
-
def post: (String endpoint, ?nil body) -> Hash[String, untyped]
|
176
|
-
def put: (String endpoint, ?nil body) -> Hash[String, untyped]
|
177
|
-
def delete: (String endpoint) -> Hash[String, untyped]
|
175
|
+
def get: (String endpoint) -> Hash[String, untyped]?
|
176
|
+
def post: (String endpoint, ?nil body) -> Hash[String, untyped]?
|
177
|
+
def put: (String endpoint, ?nil body) -> Hash[String, untyped]?
|
178
|
+
def delete: (String endpoint) -> Hash[String, untyped]?
|
178
179
|
|
179
180
|
private
|
180
181
|
def initialize_authenticator: (String? bearer_token, String? api_key, String? api_key_secret, String? access_token, String? access_token_secret) -> (BearerTokenAuthenticator | OauthAuthenticator)
|
181
|
-
def send_request: (Symbol http_method, String endpoint, ?nil body) -> Hash[String, untyped]
|
182
|
+
def send_request: (Symbol http_method, String endpoint, ?nil body) -> Hash[String, untyped]?
|
182
183
|
end
|
183
184
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: x
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erik Berlin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0'
|
71
71
|
requirements: []
|
72
|
-
rubygems_version: 3.4.
|
72
|
+
rubygems_version: 3.4.20
|
73
73
|
signing_key:
|
74
74
|
specification_version: 4
|
75
75
|
summary: A Ruby interface to the X API.
|