Skip to content

Commit 260712e

Browse files
committed
Backport HTTP parser upgrade (#489) from master
1 parent 0f5b26d commit 260712e

8 files changed

Lines changed: 67 additions & 26 deletions

File tree

.travis.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@ env: JRUBY_OPTS="$JRUBY_OPTS --debug"
1717

1818
rvm:
1919
# Include JRuby first because it takes the longest
20-
- jruby-9.1.16.0
20+
- jruby-9.2.5.0
2121
- 2.3
2222
- 2.4
2323
- 2.5
24+
- 2.6
2425

2526
matrix:
2627
fast_finish: true
2728
include:
2829
# Only run RuboCop and Yardstick metrics on the latest Ruby
29-
- rvm: 2.5
30+
- rvm: 2.6
3031
env: SUITE="rubocop"
31-
- rvm: 2.5
32+
- rvm: 2.6
3233
env: SUITE="yardstick"
3334

3435
branches:

CHANGES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 4.2.0 (WIP)
2+
3+
* [#489](https://github.com/httprb/http/pull/489)
4+
Fix HTTP parser.
5+
([@ixti], [@fxposter])
6+
7+
18
## 4.1.1 (2019-03-12)
29

310
* Add `HTTP::Headers::ACCEPT_ENCODING` constant.
@@ -771,4 +778,5 @@ end
771778
[@tycoon]: https://github.com/tycooon
772779
[@paul]: https://github.com/paul
773780
[@RickCSong]: https://github.com/RickCSong
781+
[@fxposter]: https://github.com/fxposter
774782
[@mamoonraja]: https://github.com/mamoonraja

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[![Build Status](https://secure.travis-ci.org/httprb/http.svg?branch=4-x-stable)](https://travis-ci.org/httprb/http)
55
[![Code Climate](https://codeclimate.com/github/httprb/http.svg?branch=4-x-stable)](https://codeclimate.com/github/httprb/http)
66
[![Coverage Status](https://coveralls.io/repos/httprb/http/badge.svg?branch=4-x-stable)](https://coveralls.io/r/httprb/http)
7-
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/httprb/http/blob/master/LICENSE.txt)
7+
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/httprb/http/blob/4-x-stable/LICENSE.txt)
88

99
[Documentation]
1010

@@ -167,7 +167,8 @@ versions:
167167
* Ruby 2.3.x
168168
* Ruby 2.4.x
169169
* Ruby 2.5.x
170-
* JRuby 9.1.x.x
170+
* Ruby 2.6.x
171+
* JRuby 9.2.x.x
171172

172173
If something doesn't work on one of these versions, it's a bug.
173174

@@ -197,5 +198,5 @@ dropped.
197198

198199
## Copyright
199200

200-
Copyright (c) 2011-2018 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
201+
Copyright (c) 2011-2019 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
201202
See LICENSE.txt for further details.

http.gemspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ Gem::Specification.new do |gem|
2727

2828
gem.required_ruby_version = ">= 2.3"
2929

30-
gem.add_runtime_dependency "http_parser.rb", "~> 0.6.0"
31-
gem.add_runtime_dependency "http-form_data", "~> 2.0"
32-
gem.add_runtime_dependency "http-cookie", "~> 1.0"
3330
gem.add_runtime_dependency "addressable", "~> 2.3"
31+
gem.add_runtime_dependency "http-cookie", "~> 1.0"
32+
gem.add_runtime_dependency "http-form_data", "~> 2.0"
33+
gem.add_runtime_dependency "http-parser", "~> 1.2.0"
3434

3535
gem.add_development_dependency "bundler", "~> 2.0"
3636

lib/http.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# frozen_string_literal: true
22

3-
require "http/parser"
4-
53
require "http/errors"
64
require "http/timeout/null"
75
require "http/timeout/per_operation"

lib/http/response/parser.rb

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,66 @@
11
# frozen_string_literal: true
22

3+
require "http-parser"
4+
35
module HTTP
46
class Response
7+
# @api private
8+
#
9+
# NOTE(ixti): This class is a subject of future refactoring, thus don't
10+
# expect this class API to be stable until this message disappears and
11+
# class is not marked as private anymore.
512
class Parser
613
attr_reader :headers
714

815
def initialize
9-
@parser = HTTP::Parser.new(self)
16+
@state = HttpParser::Parser.new_instance { |i| i.type = :response }
17+
@parser = HttpParser::Parser.new(self)
18+
1019
reset
1120
end
1221

22+
# @return [self]
1323
def add(data)
14-
@parser << data
24+
# XXX(ixti): API doc of HttpParser::Parser is misleading, it says that
25+
# it returns boolean true if data was parsed successfully, but instead
26+
# it's response tells if there was an error; So when it's `true` that
27+
# means parse failed, and `false` means parse was successful.
28+
# case of success.
29+
return self unless @parser.parse(@state, data)
30+
31+
raise IOError, "Could not parse data"
1532
end
1633
alias << add
1734

1835
def headers?
19-
!!@headers
36+
@finished[:headers]
2037
end
2138

2239
def http_version
23-
@parser.http_version.join(".")
40+
@state.http_version
2441
end
2542

2643
def status_code
27-
@parser.status_code
44+
@state.http_status
2845
end
2946

3047
#
3148
# HTTP::Parser callbacks
3249
#
3350

34-
def on_headers_complete(headers)
35-
@headers = headers
51+
def on_header_field(_response, field)
52+
@field = field
53+
end
54+
55+
def on_header_value(_response, value)
56+
@headers.add(@field, value) if @field
57+
end
58+
59+
def on_headers_complete(_reposse)
60+
@finished[:headers] = true
3661
end
3762

38-
def on_body(chunk)
63+
def on_body(_response, chunk)
3964
if @chunk
4065
@chunk << chunk
4166
else
@@ -57,20 +82,21 @@ def read(size)
5782
chunk
5883
end
5984

60-
def on_message_complete
61-
@finished = true
85+
def on_message_complete(_response)
86+
@finished[:message] = true
6287
end
6388

6489
def reset
65-
@parser.reset!
90+
@state.reset!
6691

67-
@finished = false
68-
@headers = nil
92+
@finished = Hash.new(false)
93+
@headers = HTTP::Headers.new
94+
@field = nil
6995
@chunk = nil
7096
end
7197

7298
def finished?
73-
@finished
99+
@finished[:message]
74100
end
75101
end
76102
end

lib/http/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module HTTP
4-
VERSION = "4.1.1"
4+
VERSION = "4.2.0.pre"
55
end

spec/regression_specs.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,11 @@
1414
expect { HTTP.get(google_uri).to_s }.not_to raise_error
1515
end
1616
end
17+
18+
describe "#422" do
19+
it "reads body when 200 OK response contains Upgrade header" do
20+
res = HTTP.get("https://httpbin.org/response-headers?Upgrade=h2,h2c")
21+
expect(res.parse(:json)).to include("Upgrade" => "h2,h2c")
22+
end
23+
end
1724
end

0 commit comments

Comments
 (0)