httpi 4.0.4 → 4.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe1562efbf5ab9aceadc7635826a4cf7317b83d5847c413bdce3462e23728f50
4
- data.tar.gz: 2149ada8b2ec173323c1dd248a57d7666bdb9b6a1e0ae83c25e7f96f4c91539b
3
+ metadata.gz: d6d915a51674973b7ce1d5d435037f117c0c745223e72f992b21b4157c9abdf5
4
+ data.tar.gz: a4878abbbed22a7dbd1d4f02717066b0a088de74fdf935d0cc24d26ee982e837
5
5
  SHA512:
6
- metadata.gz: '0964bc62dd38fcd02d9c2c5ae9b07031b7719ccdb3ff831dc6d9f563a1fd0bd085d55e741cd30e063d64b6e3c548d347f8ec9ede647790ed54c4c68d8d50d222'
7
- data.tar.gz: 61d4a274d5a330c886ccce1f773ee41567f9d09b216f1eca513ab7646f484e708295548732670a0025726713294c09aa704630c840971a57f79d34db653b97c5
6
+ metadata.gz: 1709457a67aa799d46d6c7d8afb597b194f21311822d3531f91274961bee70d4a832103dbd6089569da4145d88e163642415d2d1535ae55c71c1ce29232e9115
7
+ data.tar.gz: e2d82c42ceb35d2967130068e82697e6966c49612367c9930c0ec48e88d59d9150e12dd4e539964526574ec81697dc6b3984bc0c087f6fb937e72aa43813d39c
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  * Add your changelog entry here
4
4
 
5
+ ### 4.0.6 (2026-10-29)
6
+
7
+ * Republish the 4.0.5 changes as 4.0.6. The 4.0.5 gem never reached RubyGems, as its push workflow failed before the push step. The 4.0.5 tag is protected, so a new version carries the same gem code.
8
+
9
+ ### 4.0.5 (2026-10-29)
10
+
11
+ * Add `logger` as a direct dependency, so the gem works on Ruby 4.0, which no longer ships `logger` (#276)
12
+ * Fix the Rack adapter to send Content-Type and Content-Length without the `HTTP_` prefix, as the Rack SPEC requires
13
+
5
14
  ### 4.0.4 (2024-07-14)
6
15
 
7
16
  * gemspec: Exclude spec files from published gem by @ChristopherBert in https://github.com/savonrb/httpi/pull/252
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # HTTPI
2
2
 
3
- A common interface for Ruby's HTTP libraries. This project is now in maintenance mode. For new projects, we recommend [faraday](https://github.com/lostisland/faraday).
3
+ A common interface for Ruby's HTTP libraries. This project is now in [maintenance mode](https://github.com/savonrb/httpi/issues/238): it receives bug fixes, security updates, and ecosystem-compatibility changes, but no new features. For new projects, we recommend [faraday](https://github.com/lostisland/faraday).
4
4
 
5
5
  [Documentation](https://www.rubydoc.info/gems/httpi)
6
6
 
7
- [![Development](https://github.com/savonrb/httpi/actions/workflows/development.yml/badge.svg)](https://github.com/savonrb/httpi/actions/workflows/development.yml)
7
+ [![CI](https://github.com/savonrb/httpi/actions/workflows/ci.yml/badge.svg)](https://github.com/savonrb/httpi/actions/workflows/ci.yml)
8
8
 
9
9
  ## Installation
10
10
 
@@ -2,13 +2,11 @@ require "httpi/adapter"
2
2
 
3
3
  module HTTPI
4
4
  module Adapter
5
-
6
5
  # HTTPI::Adapter::Base
7
6
  #
8
7
  # Allows you to build your own adapter by implementing all public instance methods.
9
8
  # Register your adapter by calling the base class' .register method.
10
9
  class Base
11
-
12
10
  # Registers an adapter.
13
11
  def self.register(name, options = {})
14
12
  deps = options.fetch(:deps, [])
@@ -28,7 +26,6 @@ module HTTPI
28
26
  def request(method)
29
27
  raise NotImplementedError, "Adapters need to implement a #request method"
30
28
  end
31
-
32
29
  end
33
30
  end
34
31
  end
@@ -3,14 +3,12 @@ require "httpi/response"
3
3
 
4
4
  module HTTPI
5
5
  module Adapter
6
-
7
6
  # = HTTPI::Adapter::Curb
8
7
  #
9
8
  # Adapter for the Curb client.
10
9
  # http://rubygems.org/gems/curb
11
10
  class Curb < Base
12
-
13
- register :curb, :deps => %w(curb)
11
+ register :curb, deps: %w[curb]
14
12
 
15
13
  def initialize(request)
16
14
  @request = request
@@ -98,7 +96,7 @@ module HTTPI
98
96
  # The curl man page (http://curl.haxx.se/docs/manpage.html) says that
99
97
  # you have to specify a fake username when using Negotiate auth, and
100
98
  # they use ':' in their example.
101
- @client.username = ':'
99
+ @client.username = ":"
102
100
  end
103
101
 
104
102
  def setup_ssl_auth
@@ -116,21 +114,21 @@ module HTTPI
116
114
  @client.cert_key = ssl.cert_key_file
117
115
  @client.cert = ssl.cert_file
118
116
  @client.certpassword = ssl.cert_key_password
119
- @client.set(:ssl_cipher_list, ssl.ciphers.join(':')) if ssl.ciphers
117
+ @client.set(:ssl_cipher_list, ssl.ciphers.join(":")) if ssl.ciphers
120
118
 
121
119
  @client.ssl_verify_peer = ssl.verify_mode == :peer
122
120
  end
123
121
 
124
122
  @client.ssl_version = case ssl.ssl_version
125
- when :TLSv1_2 then 1
126
- when :TLSv1_1 then 1
127
- when :TLSv1 then 1
128
- when :SSLv2 then 2
129
- when :SSLv23 then 2
130
- when :SSLv3 then 3
123
+ when :TLSv1_2 then 1
124
+ when :TLSv1_1 then 1
125
+ when :TLSv1 then 1
126
+ when :SSLv2 then 2
127
+ when :SSLv23 then 2
128
+ when :SSLv3 then 3
131
129
  end
132
130
  if ssl.min_version || ssl.max_version
133
- raise NotSupportedError, 'Curb adapter does not support #min_version or #max_version. Please, use #ssl_version instead.'
131
+ raise NotSupportedError, "Curb adapter does not support #min_version or #max_version. Please, use #ssl_version instead."
134
132
  end
135
133
  end
136
134
 
@@ -145,15 +143,15 @@ module HTTPI
145
143
  status, headers = nil, {}
146
144
  return [status, headers] unless header_string
147
145
 
148
- header_string.split(/\r\n/).each do |header|
149
- if header =~ %r|^HTTP/1.[01] \d\d\d (.*)|
146
+ header_string.split("\r\n").each do |header|
147
+ if header =~ %r{^HTTP/1.[01] \d\d\d (.*)}
150
148
  status = $1
151
149
  else
152
- parts = header.split(':', 2)
150
+ parts = header.split(":", 2)
153
151
  unless parts.empty?
154
- parts[1].strip! unless parts[1].nil?
152
+ parts[1]&.strip!
155
153
  if headers.has_key?(parts[0])
156
- headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].kind_of? Array
154
+ headers[parts[0]] = [headers[parts[0]]] unless headers[parts[0]].is_a? Array
157
155
  headers[parts[0]] << parts[1]
158
156
  else
159
157
  headers[parts[0]] = parts[1]
@@ -164,7 +162,6 @@ module HTTPI
164
162
 
165
163
  [status, headers]
166
164
  end
167
-
168
165
  end
169
166
  end
170
167
  end
@@ -3,7 +3,6 @@ require "httpi/response"
3
3
 
4
4
  module HTTPI
5
5
  module Adapter
6
-
7
6
  # An HTTPI adapter for `EventMachine::HttpRequest`. Due to limitations of
8
7
  # the em-httprequest library, not all features are supported. In particular,
9
8
  #
@@ -28,8 +27,7 @@ module HTTPI
28
27
  #
29
28
  # are supported by em-httprequest but not HTTPI.
30
29
  class EmHttpRequest < Base
31
-
32
- register :em_http, :deps => %w(em-synchrony em-synchrony/em-http em-http)
30
+ register :em_http, deps: %w[em-synchrony em-synchrony/em-http em-http]
33
31
 
34
32
  def initialize(request)
35
33
  @request = request
@@ -82,17 +80,17 @@ module HTTPI
82
80
 
83
81
  def client_options
84
82
  {
85
- :query => @request.url.query,
86
- :head => @request.headers.to_hash,
87
- :body => @request.body
83
+ query: @request.url.query,
84
+ head: @request.headers.to_hash,
85
+ body: @request.body
88
86
  }
89
87
  end
90
88
 
91
89
  def proxy_options
92
90
  {
93
- :host => @request.proxy.host,
94
- :port => @request.proxy.port,
95
- :authorization => [@request.proxy.user, @request.proxy.password]
91
+ host: @request.proxy.host,
92
+ port: @request.proxy.port,
93
+ authorization: [@request.proxy.user, @request.proxy.password]
96
94
  }
97
95
  end
98
96
 
@@ -134,6 +132,5 @@ module HTTPI
134
132
  result
135
133
  end
136
134
  end
137
-
138
135
  end
139
136
  end
@@ -3,18 +3,16 @@ require "httpi/response"
3
3
 
4
4
  module HTTPI
5
5
  module Adapter
6
-
7
6
  # = HTTPI::Adapter::Excon
8
7
  #
9
8
  # Adapter for the Excon client.
10
9
  # https://github.com/geemus/excon
11
10
  class Excon < Base
12
-
13
- register :excon, :deps => %w(excon)
11
+ register :excon, deps: %w[excon]
14
12
 
15
13
  def initialize(request)
16
14
  @request = request
17
- @client = ::Excon::Connection.new client_opts
15
+ @client = ::Excon::Connection.new client_opts
18
16
  end
19
17
 
20
18
  attr_reader :client
@@ -36,18 +34,18 @@ module HTTPI
36
34
  private
37
35
 
38
36
  def client_opts
39
- url = @request.url
40
- ssl = @request.auth.ssl
37
+ url = @request.url
38
+ ssl = @request.auth.ssl
41
39
 
42
40
  opts = {
43
- :host => url.host,
44
- :hostname => url.hostname,
45
- :path => url.path,
46
- :port => url.port,
47
- :query => url.query,
48
- :scheme => url.scheme,
49
- :headers => @request.headers,
50
- :body => @request.body
41
+ host: url.host,
42
+ hostname: url.hostname,
43
+ path: url.path,
44
+ port: url.port,
45
+ query: url.query,
46
+ scheme: url.scheme,
47
+ headers: @request.headers,
48
+ body: @request.body
51
49
  }
52
50
 
53
51
  if @request.auth.digest?
@@ -58,16 +56,16 @@ module HTTPI
58
56
 
59
57
  opts[:user], opts[:password] = *@request.auth.credentials if @request.auth.basic?
60
58
  opts[:connect_timeout] = @request.open_timeout if @request.open_timeout
61
- opts[:read_timeout] = @request.read_timeout if @request.read_timeout
62
- opts[:write_timeout] = @request.write_timeout if @request.write_timeout
63
- opts[:response_block] = @request.on_body if @request.on_body
64
- opts[:proxy] = @request.proxy if @request.proxy
59
+ opts[:read_timeout] = @request.read_timeout if @request.read_timeout
60
+ opts[:write_timeout] = @request.write_timeout if @request.write_timeout
61
+ opts[:response_block] = @request.on_body if @request.on_body
62
+ opts[:proxy] = @request.proxy if @request.proxy
65
63
 
66
64
  case ssl.verify_mode
67
65
  when :peer
68
66
  opts[:ssl_verify_peer] = true
69
67
  opts[:ssl_ca_file] = ssl.ca_cert_file if ssl.ca_cert_file
70
- opts[:certificate] = ssl.cert.to_pem if ssl.cert
68
+ opts[:certificate] = ssl.cert.to_pem if ssl.cert
71
69
  opts[:private_key] = ssl.cert_key.to_pem if ssl.cert_key
72
70
  when :none
73
71
  opts[:ssl_verify_peer] = false
@@ -88,7 +86,6 @@ module HTTPI
88
86
  end
89
87
  Response.new response.status, headers, response.body
90
88
  end
91
-
92
89
  end
93
90
  end
94
91
  end
@@ -3,14 +3,12 @@ require "httpi/response"
3
3
 
4
4
  module HTTPI
5
5
  module Adapter
6
-
7
6
  # = HTTPI::Adapter::HTTP
8
7
  #
9
8
  # Adapter for the http.rb client.
10
9
  # https://github.com/httprb/http.rb
11
10
  class HTTP < Base
12
-
13
- register :http, :deps => %w(http)
11
+ register :http, deps: %w[http]
14
12
 
15
13
  def initialize(request)
16
14
  if request.auth.digest?
@@ -33,7 +31,7 @@ module HTTPI
33
31
  raise NotSupportedError, "http.rb does not support custom HTTP methods"
34
32
  end
35
33
  response = begin
36
- @client.send(method, @request.url, :body => @request.body)
34
+ @client.send(method, @request.url, body: @request.body)
37
35
  rescue OpenSSL::SSL::SSLError
38
36
  raise SSLError
39
37
  end
@@ -49,30 +47,30 @@ module HTTPI
49
47
 
50
48
  context.options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
51
49
 
52
- if @request.auth.ssl.ca_cert_file != nil
50
+ if !@request.auth.ssl.ca_cert_file.nil?
53
51
  context.ca_file = @request.auth.ssl.ca_cert_file
54
52
  else
55
53
  context.cert_store = OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
56
54
  end
57
55
 
58
- context.cert = @request.auth.ssl.cert
59
- context.key = @request.auth.ssl.cert_key
60
- context.ssl_version = @request.auth.ssl.ssl_version if @request.auth.ssl.ssl_version != nil
61
- context.min_version = @request.auth.ssl.min_version if @request.auth.ssl.min_version != nil
62
- context.max_version = @request.auth.ssl.max_version if @request.auth.ssl.max_version != nil
56
+ context.cert = @request.auth.ssl.cert
57
+ context.key = @request.auth.ssl.cert_key
58
+ context.ssl_version = @request.auth.ssl.ssl_version if !@request.auth.ssl.ssl_version.nil?
59
+ context.min_version = @request.auth.ssl.min_version if !@request.auth.ssl.min_version.nil?
60
+ context.max_version = @request.auth.ssl.max_version if !@request.auth.ssl.max_version.nil?
63
61
  context.verify_mode = @request.auth.ssl.openssl_verify_mode
64
- context.ciphers = @request.auth.ssl.ciphers if @request.auth.ssl.ciphers
62
+ context.ciphers = @request.auth.ssl.ciphers if @request.auth.ssl.ciphers
65
63
 
66
- client = ::HTTP::Client.new(:ssl_context => context)
64
+ client = ::HTTP::Client.new(ssl_context: context)
67
65
  else
68
66
  client = ::HTTP
69
67
  end
70
68
 
71
69
  if @request.auth.basic?
72
- client = client.basic_auth(:user => @request.auth.credentials[0], :pass => @request.auth.credentials[1])
70
+ client = client.basic_auth(user: @request.auth.credentials[0], pass: @request.auth.credentials[1])
73
71
  end
74
72
 
75
- if @request.proxy != nil
73
+ if !@request.proxy.nil?
76
74
  client = client.via(@request.proxy.host, @request.proxy.port, @request.proxy.user, @request.proxy.password)
77
75
  end
78
76
 
@@ -3,14 +3,12 @@ require "httpi/response"
3
3
 
4
4
  module HTTPI
5
5
  module Adapter
6
-
7
6
  # = HTTPI::Adapter::HTTPClient
8
7
  #
9
8
  # Adapter for the HTTPClient client.
10
9
  # http://rubygems.org/gems/httpclient
11
10
  class HTTPClient < Base
12
-
13
- register :httpclient, :deps => %w(httpclient)
11
+ register :httpclient, deps: %w[httpclient]
14
12
 
15
13
  def initialize(request)
16
14
  @request = request
@@ -80,22 +78,21 @@ module HTTPI
80
78
 
81
79
  @client.ssl_config.ssl_version = ssl.ssl_version.to_s if ssl.ssl_version
82
80
  if ssl.min_version || ssl.max_version
83
- raise NotSupportedError, 'Httpclient adapter does not support #min_version or #max_version. Please, use #ssl_version instead'
81
+ raise NotSupportedError, "Httpclient adapter does not support #min_version or #max_version. Please, use #ssl_version instead"
84
82
  end
85
83
  end
86
84
 
87
85
  def respond_with(response)
88
86
  headers = {}
89
87
  response.header.all.each do |(header, value)|
90
- if headers.key?(header)
91
- headers[header] = Array(headers[header]) << value
88
+ headers[header] = if headers.key?(header)
89
+ Array(headers[header]) << value
92
90
  else
93
- headers[header] = value
91
+ value
94
92
  end
95
93
  end
96
94
  Response.new response.code, headers, response.content
97
95
  end
98
-
99
96
  end
100
97
  end
101
98
  end
@@ -2,19 +2,17 @@ require "uri"
2
2
 
3
3
  require "httpi/adapter/base"
4
4
  require "httpi/response"
5
- require 'kconv'
6
- require 'socket'
5
+ require "kconv"
6
+ require "socket"
7
7
 
8
8
  module HTTPI
9
9
  module Adapter
10
-
11
10
  # = HTTPI::Adapter::NetHTTP
12
11
  #
13
12
  # Adapter for the Net::HTTP client.
14
13
  # http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/
15
14
  class NetHTTP < Base
16
-
17
- register :net_http, :deps => %w(net/https)
15
+ register :net_http, deps: %w[net/https]
18
16
  def initialize(request)
19
17
  check_net_ntlm_version! if request.auth.ntlm?
20
18
  @request = request
@@ -28,14 +26,14 @@ module HTTPI
28
26
  def request(method)
29
27
  # Determine if Net::HTTP supports the method using reflection
30
28
  unless Net::HTTP.const_defined?(:"#{method.to_s.capitalize}") &&
31
- Net::HTTP.const_get(:"#{method.to_s.capitalize}").class == Class
29
+ Net::HTTP.const_get(:"#{method.to_s.capitalize}").instance_of?(Class)
32
30
 
33
- raise NotSupportedError, "Net::HTTP does not support "\
31
+ raise NotSupportedError, "Net::HTTP does not support " \
34
32
  "#{method.to_s.upcase}"
35
33
  end
36
34
  do_request(method) do |http, http_request|
37
35
  http_request.body = @request.body
38
- if @request.on_body then
36
+ if @request.on_body
39
37
  perform(http, http_request) do |res|
40
38
  res.read_body do |seg|
41
39
  @request.on_body.call(seg)
@@ -53,19 +51,18 @@ module HTTPI
53
51
  end
54
52
 
55
53
  private
54
+
56
55
  def ntlm_version
57
56
  Net::NTLM::VERSION::STRING
58
57
  end
59
58
 
60
59
  def check_net_ntlm_version!
61
- begin
62
- require 'net/ntlm'
63
- require 'net/ntlm/version' unless Net::NTLM.const_defined?(:VERSION, false)
64
- unless ntlm_version >= '0.3.2'
65
- raise ArgumentError, 'Invalid version of rubyntlm. Please use v0.3.2+.'
66
- end
67
- rescue LoadError
60
+ require "net/ntlm"
61
+ require "net/ntlm/version" unless Net::NTLM.const_defined?(:VERSION, false)
62
+ unless ntlm_version >= "0.3.2"
63
+ raise ArgumentError, "Invalid version of rubyntlm. Please use v0.3.2+."
68
64
  end
65
+ rescue LoadError
69
66
  end
70
67
 
71
68
  def perform(http, http_request, &block)
@@ -74,10 +71,10 @@ module HTTPI
74
71
 
75
72
  def create_client
76
73
  proxy_url = @request.proxy || URI("")
77
- if URI(proxy_url).scheme == 'socks'
78
- proxy =Net::HTTP.SOCKSProxy(proxy_url.host, proxy_url.port)
74
+ proxy = if URI(proxy_url).scheme == "socks"
75
+ Net::HTTP.SOCKSProxy(proxy_url.host, proxy_url.port)
79
76
  else
80
- proxy = Net::HTTP::Proxy(proxy_url.host, proxy_url.port, proxy_url.user, proxy_url.password)
77
+ Net::HTTP::Proxy(proxy_url.host, proxy_url.port, proxy_url.user, proxy_url.password)
81
78
  end
82
79
  proxy.new(@request.url.host, @request.url.port)
83
80
  end
@@ -98,24 +95,24 @@ module HTTPI
98
95
 
99
96
  def negotiate_ntlm_auth(http, &requester)
100
97
  unless Net.const_defined?(:NTLM)
101
- raise NotSupportedError, 'Net::NTLM is not available. Install via gem install rubyntlm.'
98
+ raise NotSupportedError, "Net::NTLM is not available. Install via gem install rubyntlm."
102
99
  end
103
100
 
104
101
  # first figure out if we should use NTLM or Negotiate
105
102
  nego_auth_response = respond_with(requester.call(http, request_client(:head)))
106
- if nego_auth_response.headers['www-authenticate'] && nego_auth_response.headers['www-authenticate'].include?('Negotiate')
107
- auth_method = 'Negotiate'
108
- elsif nego_auth_response.headers['www-authenticate'] && nego_auth_response.headers['www-authenticate'].include?('NTLM')
109
- auth_method = 'NTLM'
103
+ if nego_auth_response.headers["www-authenticate"]&.include?("Negotiate")
104
+ auth_method = "Negotiate"
105
+ elsif nego_auth_response.headers["www-authenticate"]&.include?("NTLM")
106
+ auth_method = "NTLM"
110
107
  else
111
- auth_method = 'NTLM'
112
- HTTPI.logger.debug 'Server does not support NTLM/Negotiate. Trying NTLM anyway'
108
+ auth_method = "NTLM"
109
+ HTTPI.logger.debug "Server does not support NTLM/Negotiate. Trying NTLM anyway"
113
110
  end
114
111
 
115
112
  # initiate a request is to authenticate (exchange secret and auth) using the method determined above...
116
113
  ntlm_message_type1 = Net::NTLM::Message::Type1.new
117
- %w(workstation domain).each do |a|
118
- ntlm_message_type1.send("#{a}=",'')
114
+ %w[workstation domain].each do |a|
115
+ ntlm_message_type1.send("#{a}=", "")
119
116
  ntlm_message_type1.enable(a.to_sym)
120
117
  end
121
118
 
@@ -134,14 +131,14 @@ module HTTPI
134
131
  message_builder[:password] = @request.auth.ntlm[1]
135
132
 
136
133
  # we need to provide a domain in the packet if an only if it was provided by the user in the auth request
137
- if @request.auth.ntlm[2]
138
- message_builder[:domain] = @request.auth.ntlm[2].upcase
134
+ message_builder[:domain] = if @request.auth.ntlm[2]
135
+ @request.auth.ntlm[2].upcase
139
136
  else
140
- message_builder[:domain] = ''
137
+ ""
141
138
  end
142
139
 
143
- ntlm_response = ntlm_message.response(message_builder ,
144
- {:ntlmv2 => true})
140
+ ntlm_response = ntlm_message.response(message_builder,
141
+ {ntlmv2: true})
145
142
  # Finally add header of Authorization
146
143
  @request.headers["Authorization"] = "#{auth_method} #{ntlm_response.encode64}"
147
144
  end
@@ -212,10 +209,9 @@ module HTTPI
212
209
  headers.each do |key, value|
213
210
  headers[key] = value[0] if value.size <= 1
214
211
  end
215
- body = (response.body.kind_of?(Net::ReadAdapter) ? "" : response.body)
212
+ body = (response.body.is_a?(Net::ReadAdapter) ? "" : response.body)
216
213
  Response.new response.code, headers, body
217
214
  end
218
-
219
215
  end
220
216
  end
221
217
  end
@@ -1,18 +1,16 @@
1
1
  module HTTPI
2
2
  module Adapter
3
-
4
3
  # = HTTPI::Adapter::NetHTTPPersistent
5
4
  #
6
5
  # Adapter for the Net::HTTP::Persistent client.
7
6
  # http://docs.seattlerb.org/net-http-persistent/Net/HTTP/Persistent.html
8
7
  class NetHTTPPersistent < NetHTTP
9
-
10
- register :net_http_persistent, :deps => %w(net/http/persistent)
8
+ register :net_http_persistent, deps: %w[net/http/persistent]
11
9
 
12
10
  private
13
11
 
14
12
  def create_client
15
- if Gem::Version.new(Net::HTTP::Persistent::VERSION) >= Gem::Version.new('3.0.0')
13
+ if Gem::Version.new(Net::HTTP::Persistent::VERSION) >= Gem::Version.new("3.0.0")
16
14
  Net::HTTP::Persistent.new name: thread_key
17
15
  else
18
16
  Net::HTTP::Persistent.new thread_key
@@ -40,7 +38,7 @@ module HTTPI
40
38
  end
41
39
 
42
40
  def thread_key
43
- @request.url.host.split(/\W/).reject{|p|p == ""}.join('-')
41
+ @request.url.host.split(/\W/).reject { |p| p == "" }.join("-")
44
42
  end
45
43
  end
46
44
  end
@@ -1,10 +1,9 @@
1
- require 'base64'
2
- require 'httpi/adapter/base'
3
- require 'httpi/response'
1
+ require "base64"
2
+ require "httpi/adapter/base"
3
+ require "httpi/response"
4
4
 
5
5
  module HTTPI
6
6
  module Adapter
7
-
8
7
  # = HTTPI::Adapter::Rack
9
8
  #
10
9
  # Adapter for Rack::MockRequest.
@@ -16,7 +15,7 @@ module HTTPI
16
15
  # HTTPI::Adapter::Rack.mount 'application', RackApplication
17
16
  # HTTPI.get("http://application/path", :rack)
18
17
  class Rack < Base
19
- register :rack, :deps => %w(rack/mock)
18
+ register :rack, deps: %w[rack/mock]
20
19
 
21
20
  attr_reader :client
22
21
 
@@ -29,27 +28,26 @@ module HTTPI
29
28
  # Attaches Rack endpoint at specified host.
30
29
  # Endpoint will be acessible at {http://host/ http://host/} url.
31
30
  def self.mount(host, application)
32
- self.mounted_apps[host] = application
31
+ mounted_apps[host] = application
33
32
  end
34
33
 
35
34
  # Removes Rack endpoint.
36
35
  def self.unmount(host)
37
- self.mounted_apps.delete(host)
36
+ mounted_apps.delete(host)
38
37
  end
39
38
 
40
39
  def initialize(request)
41
40
  @app = self.class.mounted_apps[request.url.host]
42
41
 
43
-
44
42
  if @app.nil?
45
- message = "Application '#{request.url.host}' not mounted: ";
43
+ message = "Application '#{request.url.host}' not mounted: "
46
44
  message += "use `HTTPI::Adapter::Rack.mount('#{request.url.host}', RackApplicationClass)`"
47
45
 
48
46
  raise message
49
47
  end
50
48
 
51
49
  @request = request
52
- @client = ::Rack::MockRequest.new(@app)
50
+ @client = ::Rack::MockRequest.new(@app)
53
51
  end
54
52
 
55
53
  # Executes arbitrary HTTP requests.
@@ -68,9 +66,9 @@ module HTTPI
68
66
 
69
67
  if @request.auth.http?
70
68
  if @request.auth.basic?
71
- basic_auth = @request.auth.basic.join(':')
72
- encoded = Base64.encode64(basic_auth).gsub('\n', '')
73
- @request.headers['Authorization'] = "Basic #{encoded}"
69
+ basic_auth = @request.auth.basic.join(":")
70
+ encoded = Base64.encode64(basic_auth).gsub('\n', "")
71
+ @request.headers["Authorization"] = "Basic #{encoded}"
74
72
  else
75
73
  raise NotSupportedError, "Rack adapter does not support HTTP #{@request.auth.type} auth"
76
74
  end
@@ -86,14 +84,24 @@ module HTTPI
86
84
 
87
85
  env = {}
88
86
  @request.headers.each do |header, value|
89
- env["HTTP_#{header.gsub('-', '_').upcase}"] = value
87
+ # The headers CONTENT_TYPE and CONTENT_LENGTH should not have "HTTP_"
88
+ # added as a prefix. For all other headers, add the prefix "HTTP_"
89
+ # https://github.com/rack/rack/blob/main/SPEC.rdoc#label-HTTP_+Headers
90
+ normalized = header.tr("-", "_").upcase
91
+ key = if normalized == "CONTENT_TYPE" || normalized == "CONTENT_LENGTH"
92
+ normalized
93
+ else
94
+ "HTTP_#{normalized}"
95
+ end
96
+
97
+ env[key] = value
90
98
  end
91
99
 
92
100
  response = @client.request(method.to_s.upcase, @request.url.to_s,
93
- { :fatal => true, :input => @request.body.to_s }.merge(env))
101
+ {fatal: true, input: @request.body.to_s}.merge(env))
94
102
 
95
103
  Response.new(response.status, response.headers, response.body)
96
104
  end
97
105
  end
98
106
  end
99
- end
107
+ end