x 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ff134774b6d6b28f3f72c740c74b1f44b11ce94cff63fbfe4eabc0414f600c3
4
- data.tar.gz: 9f3b9abd3ca2628979676b5f634781b960adf6afe8a77559cf6f3a96ee738098
3
+ metadata.gz: e2906018cf3e05342abe1bc6c938f3d1b3cf9d1d84c3813a96a11b693fbe0960
4
+ data.tar.gz: f84f47e1a9ea06b101712ae1f9fd7198d71b2cbc7487a654b8442dd13e3244e0
5
5
  SHA512:
6
- metadata.gz: cd471d0b216161f5e68832e83b5024a8a89cdda1c815f49543f8361b225776ad46f84690eddf9a9b884cf0ab540924ecae94ebd145f26ac07e44ffdf7c4ff1f2
7
- data.tar.gz: 3670666ca95e154a253be800af600cdcaf44195b9dcd3d001e1404d85f27dd5939ce09bd25588cfbe81cefef92ce22bfcd26e105dcb70d813bc4efa221a4360d
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}&#{encode(url)}&#{encode(encode_params(params))}"
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
- "#{encode(api_key_secret)}&#{encode(access_token_secret)}"
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}=\"#{encode(v.to_s)}\"" }.join(", ")}"
83
+ "OAuth #{params.sort.map { |k, v| "#{k}=\"#{escape(v.to_s)}\"" }.join(", ")}"
88
84
  end
89
85
 
90
- def encode(value)
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
@@ -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} Ruby/#{RUBY_VERSION}".freeze
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, url, body: nil)
28
- request = create_request(http_method, url, body)
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, url, body)
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
- request = http_method_class.new(url)
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
@@ -32,19 +32,23 @@ module X
32
32
  end
33
33
 
34
34
  def handle(response)
35
- if successful_json_response?(response)
36
- return JSON.parse(response.body, array_class: array_class, object_class: object_class)
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 successful_json_response?(response)
47
- response.is_a?(Net::HTTPSuccess) && response.body && JSON_CONTENT_TYPE_REGEXP.match?(response["content-type"])
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
@@ -1,5 +1,5 @@
1
1
  require "rubygems/version"
2
2
 
3
3
  module X
4
- VERSION = Gem::Version.create("0.9.0")
4
+ VERSION = Gem::Version.create("0.9.1")
5
5
  end
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 encode: (String value) -> String
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 url, ?body: String?) -> (Net::HTTPRequest)
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 url, String? body) -> (Net::HTTPRequest)
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 successful_json_response?: (Net::HTTPResponse response) -> bool
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.0
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-09-26 00:00:00.000000000 Z
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.19
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.