http 2.0.0.pre → 2.0.0

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
  SHA1:
3
- metadata.gz: 528cd808cd0cf04d196ac3459063496777a46736
4
- data.tar.gz: a3a4cf179068d8f5c48bc803118075e5e71331d5
3
+ metadata.gz: 8ae83a6df13ab671375cfdd322ba65d1a15b8a43
4
+ data.tar.gz: 4e107db57baa353e23fb25d805a3a0a6f17d1310
5
5
  SHA512:
6
- metadata.gz: 1774996540d80f6f08866f5bee7d632baa72a33bd31122485f15fdb97d695de7645c0f9131a5e52188ef4706005c96c74bcc175ee3b5182a9a7b7b4597f07274
7
- data.tar.gz: 9cc27b2c73fee256c61409ce41069588e780c41df32d27662eea5c1d7de116e820c8843b3e08b670a84cfbb695b64d126c1f1b6e7b43de599cb84cad91f09d73
6
+ metadata.gz: fdc5e4ea2f1e56a213246c34b40320584a1e092d07fcb03f99dd9f11d260b81e40be26483640a997c57d601b4882c753ca367152bd7cca9ad5b0498cb1b6681b
7
+ data.tar.gz: e421f13bb1522ec92bd2eca7efd73a713036daba084416cdc86d69d681d72d8f050738fe9b664d101a186afb028dd0d46eea475c029587a17d3dc3dfa619ac21
@@ -1,8 +1,12 @@
1
+ language: ruby
2
+ sudo: false
3
+
1
4
  bundler_args: --without development doc
5
+
2
6
  env:
3
7
  global:
4
8
  - JRUBY_OPTS="$JRUBY_OPTS --debug"
5
- language: ruby
9
+
6
10
  rvm:
7
11
  - 2.0.0
8
12
  - 2.1
@@ -12,10 +16,14 @@ rvm:
12
16
  - jruby-head
13
17
  - ruby-head
14
18
  - rbx-2
19
+
15
20
  matrix:
16
21
  allow_failures:
17
22
  - rvm: jruby-head
18
23
  - rvm: ruby-head
19
24
  - rvm: rbx-2
20
25
  fast_finish: true
21
- sudo: false
26
+
27
+ branches:
28
+ only:
29
+ - master
data/CHANGES.md CHANGED
@@ -1,4 +1,17 @@
1
- ## master (unreleased)
1
+ ## 2.0.0 (2016-04-23)
2
+
3
+ * [#333](https://github.com/httprb/http/pull/333)
4
+ Fix HTTPS request headline when sent via proxy.
5
+ ([@Connorhd])
6
+
7
+ * [#331](https://github.com/httprb/http/pull/331)
8
+ Add `#informational?`, `#success?`, `#redirect?`, `#client_error?` and
9
+ `#server_error?` helpers to `Response::Status`.
10
+ ([@mwitek])
11
+
12
+ * [#330](https://github.com/httprb/http/pull/330)
13
+ Support custom CONNECT headers (request/response) during HTTPS proxy requests.
14
+ ([@smudge])
2
15
 
3
16
  * [#319](https://github.com/httprb/http/pull/319)
4
17
  Drop Ruby 1.9.x support.
@@ -501,3 +514,5 @@ end
501
514
  [@jwinter]: https://github.com/jwinter
502
515
  [@nerdrew]: https://github.com/nerdrew
503
516
  [@kylekyle]: https://github.com/kylekyle
517
+ [@smudge]: https://github.com/smudge
518
+ [@mwitek]: https://github.com/mwitek
data/Gemfile CHANGED
@@ -20,11 +20,11 @@ group :test do
20
20
  gem "coveralls"
21
21
  gem "simplecov", ">= 0.9"
22
22
  gem "json", ">= 1.8.1"
23
- gem "rubocop", "= 0.36.0"
23
+ gem "rubocop", "= 0.39.0"
24
24
  gem "rspec", "~> 3.0"
25
25
  gem "rspec-its"
26
26
  gem "yardstick"
27
- gem "certificate_authority"
27
+ gem "certificate_authority", :require => false
28
28
  end
29
29
 
30
30
  group :doc do
@@ -93,7 +93,7 @@ module HTTP
93
93
  when :null then HTTP::Timeout::Null
94
94
  when :global then HTTP::Timeout::Global
95
95
  when :per_operation then HTTP::Timeout::PerOperation
96
- else fail ArgumentError, "Unsupported Timeout class: #{klass}"
96
+ else raise ArgumentError, "Unsupported Timeout class: #{klass}"
97
97
  end
98
98
 
99
99
  [:read, :write, :connect].each do |k|
@@ -153,8 +153,10 @@ module HTTP
153
153
  proxy_hash[:proxy_port] = proxy[1] if proxy[1].is_a?(Integer)
154
154
  proxy_hash[:proxy_username] = proxy[2] if proxy[2].is_a?(String)
155
155
  proxy_hash[:proxy_password] = proxy[3] if proxy[3].is_a?(String)
156
+ proxy_hash[:proxy_headers] = proxy[2] if proxy[2].is_a?(Hash)
157
+ proxy_hash[:proxy_headers] = proxy[4] if proxy[4].is_a?(Hash)
156
158
 
157
- fail(RequestError, "invalid HTTP proxy: #{proxy_hash}") unless [2, 4].include?(proxy_hash.keys.size)
159
+ raise(RequestError, "invalid HTTP proxy: #{proxy_hash}") unless (2..5).cover?(proxy_hash.keys.size)
158
160
 
159
161
  branch default_options.with_proxy(proxy_hash)
160
162
  end
@@ -68,12 +68,13 @@ module HTTP
68
68
  end
69
69
 
70
70
  res = Response.new(
71
- :status => @connection.status_code,
72
- :version => @connection.http_version,
73
- :headers => @connection.headers,
74
- :connection => @connection,
75
- :encoding => options.encoding,
76
- :uri => req.uri
71
+ :status => @connection.status_code,
72
+ :version => @connection.http_version,
73
+ :headers => @connection.headers,
74
+ :proxy_headers => @connection.proxy_response_headers,
75
+ :connection => @connection,
76
+ :encoding => options.encoding,
77
+ :uri => req.uri
77
78
  )
78
79
 
79
80
  @connection.finish_response if req.verb == :head
@@ -96,7 +97,7 @@ module HTTP
96
97
  # Verify our request isn't going to be made against another URI
97
98
  def verify_connection!(uri)
98
99
  if default_options.persistent? && uri.origin != default_options.persistent
99
- fail StateError, "Persistence is enabled for #{default_options.persistent}, but we got #{uri.origin}"
100
+ raise StateError, "Persistence is enabled for #{default_options.persistent}, but we got #{uri.origin}"
100
101
  # We re-create the connection object because we want to let prior requests
101
102
  # lazily load the body as long as possible, and this mimics prior functionality.
102
103
  elsif @connection && (!@connection.keep_alive? || @connection.expired?)
@@ -19,6 +19,9 @@ module HTTP
19
19
  # HTTP/1.1
20
20
  HTTP_1_1 = "1.1".freeze
21
21
 
22
+ # Returned after HTTP CONNECT (via proxy)
23
+ attr_reader :proxy_response_headers
24
+
22
25
  # @param [HTTP::Request] req
23
26
  # @param [HTTP::Options] options
24
27
  # @raise [HTTP::ConnectionError] when failed to connect
@@ -60,11 +63,8 @@ module HTTP
60
63
  # @param [Request] req Request to send to the server
61
64
  # @return [nil]
62
65
  def send_request(req)
63
- if @pending_response
64
- fail StateError, "Tried to send a request while one is pending already. Make sure you read off the body."
65
- elsif @pending_request
66
- fail StateError, "Tried to send a request while a response is pending. Make sure you've fully read the body from the request."
67
- end
66
+ raise StateError, "Tried to send a request while one is pending already. Make sure you read off the body." if @pending_response
67
+ raise StateError, "Tried to send a request while a response is pending. Make sure you read off the body." if @pending_request
68
68
 
69
69
  @pending_request = true
70
70
 
@@ -94,7 +94,7 @@ module HTTP
94
94
  def read_headers!
95
95
  loop do
96
96
  if read_more(BUFFER_SIZE) == :eof
97
- fail ConnectionError, "couldn't read response headers" unless @parser.headers?
97
+ raise ConnectionError, "couldn't read response headers" unless @parser.headers?
98
98
  break
99
99
  elsif @parser.headers?
100
100
  break
@@ -167,6 +167,7 @@ module HTTP
167
167
  @pending_response = true
168
168
 
169
169
  read_headers!
170
+ @proxy_response_headers = @parser.headers
170
171
 
171
172
  if @parser.status_code != 200
172
173
  @failed_proxy_connect = true
@@ -171,7 +171,7 @@ module HTTP
171
171
  when object.respond_to?(:to_hash) then object.to_hash
172
172
  when object.respond_to?(:to_h) then object.to_h
173
173
  when object.respond_to?(:to_a) then object.to_a
174
- else fail Error, "Can't coerce #{object.inspect} to Headers"
174
+ else raise Error, "Can't coerce #{object.inspect} to Headers"
175
175
  end
176
176
  end
177
177
 
@@ -197,7 +197,7 @@ module HTTP
197
197
 
198
198
  return normalized if normalized =~ COMPLIANT_NAME_RE
199
199
 
200
- fail InvalidHeaderNameError, "Invalid HTTP header field name: #{name.inspect}"
200
+ raise InvalidHeaderNameError, "Invalid HTTP header field name: #{name.inspect}"
201
201
  end
202
202
  end
203
203
  end
@@ -33,7 +33,7 @@ module HTTP
33
33
  # @raise [Error] if no adapter found
34
34
  # @return [Class]
35
35
  def [](type)
36
- adapters[normalize type] || fail(Error, "Unknown MIME type: #{type}")
36
+ adapters[normalize type] || raise(Error, "Unknown MIME type: #{type}")
37
37
  end
38
38
 
39
39
  # Register a shortcut for MIME type
@@ -135,7 +135,7 @@ module HTTP
135
135
  private
136
136
 
137
137
  def argument_error!(message)
138
- fail(Error, message, caller[1..-1])
138
+ raise(Error, message, caller[1..-1])
139
139
  end
140
140
  end
141
141
  end
@@ -51,8 +51,8 @@ module HTTP
51
51
  while REDIRECT_CODES.include? @response.status.code
52
52
  @visited << "#{@request.verb} #{@request.uri}"
53
53
 
54
- fail TooManyRedirectsError if too_many_hops?
55
- fail EndlessRedirectError if endless_loop?
54
+ raise TooManyRedirectsError if too_many_hops?
55
+ raise EndlessRedirectError if endless_loop?
56
56
 
57
57
  @response.flush
58
58
 
@@ -80,13 +80,13 @@ module HTTP
80
80
  # Redirect policy for follow
81
81
  # @return [Request]
82
82
  def redirect_to(uri)
83
- fail StateError, "no Location header in redirect" unless uri
83
+ raise StateError, "no Location header in redirect" unless uri
84
84
 
85
85
  verb = @request.verb
86
86
  code = @response.status.code
87
87
 
88
88
  if UNSAFE_VERBS.include?(verb) && STRICT_SENSITIVE_CODES.include?(code)
89
- fail StateError, "can't follow #{@response.status} redirect" if @strict
89
+ raise StateError, "can't follow #{@response.status} redirect" if @strict
90
90
  verb = :get
91
91
  end
92
92
 
@@ -77,8 +77,8 @@ module HTTP
77
77
  @uri = normalize_uri(opts.fetch(:uri))
78
78
  @scheme = @uri.scheme.to_s.downcase.to_sym if @uri.scheme
79
79
 
80
- fail(UnsupportedMethodError, "unknown method: #{verb}") unless METHODS.include?(@verb)
81
- fail(UnsupportedSchemeError, "unknown scheme: #{scheme}") unless SCHEMES.include?(@scheme)
80
+ raise(UnsupportedMethodError, "unknown method: #{verb}") unless METHODS.include?(@verb)
81
+ raise(UnsupportedSchemeError, "unknown scheme: #{scheme}") unless SCHEMES.include?(@scheme)
82
82
 
83
83
  @proxy = opts[:proxy] || {}
84
84
  @body = opts[:body]
@@ -106,7 +106,7 @@ module HTTP
106
106
 
107
107
  # Stream the request to a socket
108
108
  def stream(socket)
109
- include_proxy_authorization_header if using_authenticated_proxy? && !@uri.https?
109
+ include_proxy_headers if using_proxy? && !@uri.https?
110
110
  Request::Writer.new(socket, body, headers, headline).stream
111
111
  end
112
112
 
@@ -117,7 +117,12 @@ module HTTP
117
117
 
118
118
  # Is this request using an authenticated proxy?
119
119
  def using_authenticated_proxy?
120
- proxy && proxy.keys.size == 4
120
+ proxy && proxy.keys.size >= 4
121
+ end
122
+
123
+ def include_proxy_headers
124
+ headers.merge!(proxy[:proxy_headers]) if proxy.key?(:proxy_headers)
125
+ include_proxy_authorization_header if using_authenticated_proxy?
121
126
  end
122
127
 
123
128
  # Compute and add the Proxy-Authorization header
@@ -137,7 +142,7 @@ module HTTP
137
142
 
138
143
  # Compute HTTP request header for direct or proxy request
139
144
  def headline
140
- request_uri = using_proxy? ? uri : uri.omit(:scheme, :authority)
145
+ request_uri = (using_proxy? && !uri.https?) ? uri : uri.omit(:scheme, :authority)
141
146
  "#{verb.to_s.upcase} #{request_uri.omit :fragment} HTTP/#{version}"
142
147
  end
143
148
 
@@ -154,7 +159,7 @@ module HTTP
154
159
  )
155
160
 
156
161
  connect_headers[Headers::PROXY_AUTHORIZATION] = proxy_authorization_header if using_authenticated_proxy?
157
-
162
+ connect_headers.merge!(proxy[:proxy_headers]) if proxy.key?(:proxy_headers)
158
163
  connect_headers
159
164
  end
160
165
 
@@ -54,7 +54,7 @@ module HTTP
54
54
  if @body.is_a?(String) && !@headers[Headers::CONTENT_LENGTH]
55
55
  @request_header << "#{Headers::CONTENT_LENGTH}: #{@body.bytesize}"
56
56
  elsif @body.is_a?(Enumerable) && CHUNKED != @headers[Headers::TRANSFER_ENCODING]
57
- fail(RequestError, "invalid transfer encoding")
57
+ raise(RequestError, "invalid transfer encoding")
58
58
  end
59
59
  end
60
60
 
@@ -86,7 +86,7 @@ module HTTP
86
86
  end
87
87
 
88
88
  write(CHUNKED_END)
89
- else fail TypeError, "invalid body type: #{@body.class}"
89
+ else raise TypeError, "invalid body type: #{@body.class}"
90
90
  end
91
91
  end
92
92
 
@@ -102,7 +102,7 @@ module HTTP
102
102
 
103
103
  def validate_body_type!
104
104
  return if VALID_BODY_TYPES.any? { |type| @body.is_a? type }
105
- fail RequestError, "body of wrong type: #{@body.class}"
105
+ raise RequestError, "body of wrong type: #{@body.class}"
106
106
  end
107
107
  end
108
108
  end
@@ -23,20 +23,25 @@ module HTTP
23
23
  # @return [URI, nil]
24
24
  attr_reader :uri
25
25
 
26
+ # @return [Hash]
27
+ attr_reader :proxy_headers
28
+
26
29
  # Inits a new instance
27
30
  #
28
31
  # @option opts [Integer] :status Status code
29
32
  # @option opts [String] :version HTTP version
30
33
  # @option opts [Hash] :headers
34
+ # @option opts [Hash] :proxy_headers
31
35
  # @option opts [HTTP::Connection] :connection
32
36
  # @option opts [String] :encoding Encoding to use when reading body
33
37
  # @option opts [String] :body
34
38
  # @option opts [String] :uri
35
39
  def initialize(opts)
36
- @version = opts.fetch(:version)
37
- @uri = HTTP::URI.parse(opts.fetch(:uri)) if opts.include? :uri
38
- @status = HTTP::Response::Status.new(opts.fetch(:status))
39
- @headers = HTTP::Headers.coerce(opts[:headers] || {})
40
+ @version = opts.fetch(:version)
41
+ @uri = HTTP::URI.parse(opts.fetch(:uri)) if opts.include? :uri
42
+ @status = HTTP::Response::Status.new(opts.fetch(:status))
43
+ @headers = HTTP::Headers.coerce(opts[:headers] || {})
44
+ @proxy_headers = HTTP::Headers.coerce(opts[:proxy_headers] || {})
40
45
 
41
46
  if opts.include?(:connection)
42
47
  connection = opts.fetch(:connection)
@@ -33,7 +33,7 @@ module HTTP
33
33
  def to_s
34
34
  return @contents if @contents
35
35
 
36
- fail StateError, "body is being streamed" unless @streaming.nil?
36
+ raise StateError, "body is being streamed" unless @streaming.nil?
37
37
 
38
38
  # see issue 312
39
39
  begin
@@ -59,7 +59,7 @@ module HTTP
59
59
 
60
60
  # Assert that the body is actively being streamed
61
61
  def stream!
62
- fail StateError, "body has already been consumed" if @streaming == false
62
+ raise StateError, "body has already been consumed" if @streaming == false
63
63
  @streaming = true
64
64
  end
65
65
 
@@ -26,7 +26,7 @@ module HTTP
26
26
 
27
27
  return new code if code
28
28
 
29
- fail Error, "Can't coerce #{object.class}(#{object}) to #{self}"
29
+ raise Error, "Can't coerce #{object.class}(#{object}) to #{self}"
30
30
  end
31
31
  alias [] coerce
32
32
 
@@ -83,6 +83,36 @@ module HTTP
83
83
  "#{code} #{reason}".strip
84
84
  end
85
85
 
86
+ # Check if status code is informational (1XX)
87
+ # @return [Boolean]
88
+ def informational?
89
+ 100 <= code && code < 200
90
+ end
91
+
92
+ # Check if status code is successful (2XX)
93
+ # @return [Boolean]
94
+ def success?
95
+ 200 <= code && code < 300
96
+ end
97
+
98
+ # Check if status code is redirection (3XX)
99
+ # @return [Boolean]
100
+ def redirect?
101
+ 300 <= code && code < 400
102
+ end
103
+
104
+ # Check if status code is client error (4XX)
105
+ # @return [Boolean]
106
+ def client_error?
107
+ 400 <= code && code < 500
108
+ end
109
+
110
+ # Check if status code is server error (5XX)
111
+ # @return [Boolean]
112
+ def server_error?
113
+ 500 <= code && code < 600
114
+ end
115
+
86
116
  # Symbolized {#reason}
87
117
  #
88
118
  # @return [nil] unless code is well-known (see REASONS)
@@ -108,7 +138,7 @@ module HTTP
108
138
  end
109
139
 
110
140
  def __setobj__(obj)
111
- fail TypeError, "Expected #{obj.inspect} to respond to #to_i" unless obj.respond_to? :to_i
141
+ raise TypeError, "Expected #{obj.inspect} to respond to #to_i" unless obj.respond_to? :to_i
112
142
  @code = obj.to_i
113
143
  end
114
144
 
@@ -122,7 +122,7 @@ module HTTP
122
122
  def log_time
123
123
  @time_left -= (Time.now - @started)
124
124
  if time_left <= 0
125
- fail TimeoutError, "Timed out after using the allocated #{total_timeout} seconds"
125
+ raise TimeoutError, "Timed out after using the allocated #{total_timeout} seconds"
126
126
  end
127
127
 
128
128
  reset_timer
@@ -60,14 +60,12 @@ module HTTP
60
60
  def readpartial(size)
61
61
  loop do
62
62
  result = @socket.read_nonblock(size, :exception => false)
63
- if result.nil?
64
- return :eof
65
- elsif result != :wait_readable
66
- return result
67
- end
63
+
64
+ return :eof if result.nil?
65
+ return result if result != :wait_readable
68
66
 
69
67
  unless IO.select([@socket], nil, nil, read_timeout)
70
- fail TimeoutError, "Read timed out after #{read_timeout} seconds"
68
+ raise TimeoutError, "Read timed out after #{read_timeout} seconds"
71
69
  end
72
70
  end
73
71
  end
@@ -79,7 +77,7 @@ module HTTP
79
77
  return result unless result == :wait_writable
80
78
 
81
79
  unless IO.select(nil, [@socket], nil, write_timeout)
82
- fail TimeoutError, "Write timed out after #{write_timeout} seconds"
80
+ raise TimeoutError, "Write timed out after #{write_timeout} seconds"
83
81
  end
84
82
  end
85
83
  end
@@ -63,7 +63,7 @@ module HTTP
63
63
  @uri = Addressable::URI.new(options_or_uri)
64
64
  when Addressable::URI
65
65
  @uri = options_or_uri
66
- else fail TypeError, "expected Hash for options, got #{options_or_uri.class}"
66
+ else raise TypeError, "expected Hash for options, got #{options_or_uri.class}"
67
67
  end
68
68
  end
69
69
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module HTTP
3
- VERSION = "2.0.0.pre".freeze
3
+ VERSION = "2.0.0".freeze
4
4
  end
@@ -202,6 +202,12 @@ RSpec.describe HTTP::Request do
202
202
  context "with proxy" do
203
203
  let(:proxy) { {:user => "user", :pass => "pass"} }
204
204
  it { is_expected.to eq "GET http://example.com/foo?bar=baz HTTP/1.1" }
205
+
206
+ context "and HTTPS uri" do
207
+ let(:request_uri) { "https://example.com/foo?bar=baz" }
208
+
209
+ it { is_expected.to eq "GET /foo?bar=baz HTTP/1.1" }
210
+ end
205
211
  end
206
212
  end
207
213
  end
@@ -34,6 +34,126 @@ RSpec.describe HTTP::Response::Status do
34
34
  end
35
35
  end
36
36
 
37
+ context "with 1xx codes" do
38
+ subject { (100...200).map { |code| described_class.new code } }
39
+
40
+ it "is #informational?" do
41
+ expect(subject).to all satisfy(&:informational?)
42
+ end
43
+
44
+ it "is not #success?" do
45
+ expect(subject).to all satisfy { |status| !status.success? }
46
+ end
47
+
48
+ it "is not #redirect?" do
49
+ expect(subject).to all satisfy { |status| !status.redirect? }
50
+ end
51
+
52
+ it "is not #client_error?" do
53
+ expect(subject).to all satisfy { |status| !status.client_error? }
54
+ end
55
+
56
+ it "is not #server_error?" do
57
+ expect(subject).to all satisfy { |status| !status.server_error? }
58
+ end
59
+ end
60
+
61
+ context "with 2xx codes" do
62
+ subject { (200...300).map { |code| described_class.new code } }
63
+
64
+ it "is not #informational?" do
65
+ expect(subject).to all satisfy { |status| !status.informational? }
66
+ end
67
+
68
+ it "is #success?" do
69
+ expect(subject).to all satisfy(&:success?)
70
+ end
71
+
72
+ it "is not #redirect?" do
73
+ expect(subject).to all satisfy { |status| !status.redirect? }
74
+ end
75
+
76
+ it "is not #client_error?" do
77
+ expect(subject).to all satisfy { |status| !status.client_error? }
78
+ end
79
+
80
+ it "is not #server_error?" do
81
+ expect(subject).to all satisfy { |status| !status.server_error? }
82
+ end
83
+ end
84
+
85
+ context "with 3xx codes" do
86
+ subject { (300...400).map { |code| described_class.new code } }
87
+
88
+ it "is not #informational?" do
89
+ expect(subject).to all satisfy { |status| !status.informational? }
90
+ end
91
+
92
+ it "is not #success?" do
93
+ expect(subject).to all satisfy { |status| !status.success? }
94
+ end
95
+
96
+ it "is #redirect?" do
97
+ expect(subject).to all satisfy(&:redirect?)
98
+ end
99
+
100
+ it "is not #client_error?" do
101
+ expect(subject).to all satisfy { |status| !status.client_error? }
102
+ end
103
+
104
+ it "is not #server_error?" do
105
+ expect(subject).to all satisfy { |status| !status.server_error? }
106
+ end
107
+ end
108
+
109
+ context "with 4xx codes" do
110
+ subject { (400...500).map { |code| described_class.new code } }
111
+
112
+ it "is not #informational?" do
113
+ expect(subject).to all satisfy { |status| !status.informational? }
114
+ end
115
+
116
+ it "is not #success?" do
117
+ expect(subject).to all satisfy { |status| !status.success? }
118
+ end
119
+
120
+ it "is not #redirect?" do
121
+ expect(subject).to all satisfy { |status| !status.redirect? }
122
+ end
123
+
124
+ it "is #client_error?" do
125
+ expect(subject).to all satisfy(&:client_error?)
126
+ end
127
+
128
+ it "is not #server_error?" do
129
+ expect(subject).to all satisfy { |status| !status.server_error? }
130
+ end
131
+ end
132
+
133
+ context "with 5xx codes" do
134
+ subject { (500...600).map { |code| described_class.new code } }
135
+
136
+ it "is not #informational?" do
137
+ expect(subject).to all satisfy { |status| !status.informational? }
138
+ end
139
+
140
+ it "is not #success?" do
141
+ expect(subject).to all satisfy { |status| !status.success? }
142
+ end
143
+
144
+ it "is not #redirect?" do
145
+ expect(subject).to all satisfy { |status| !status.redirect? }
146
+ end
147
+
148
+ it "is not #client_error?" do
149
+ expect(subject).to all satisfy { |status| !status.client_error? }
150
+ end
151
+
152
+ it "is #server_error?" do
153
+ expect(subject).to all satisfy(&:server_error?)
154
+ end
155
+ end
156
+
37
157
  describe "#to_sym" do
38
158
  subject { described_class.new(code).to_sym }
39
159
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2016-04-03 00:00:00.000000000 Z
14
+ date: 2016-04-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: http_parser.rb
@@ -178,9 +178,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
178
178
  version: '0'
179
179
  required_rubygems_version: !ruby/object:Gem::Requirement
180
180
  requirements:
181
- - - ">"
181
+ - - ">="
182
182
  - !ruby/object:Gem::Version
183
- version: 1.3.1
183
+ version: '0'
184
184
  requirements: []
185
185
  rubyforge_project:
186
186
  rubygems_version: 2.5.1