protocol-http1 0.14.6 → 0.15.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a46985e11bfc9d2130f9abceacbd769c4aa83881a1a607afe9d0b4d07ad37e81
4
- data.tar.gz: cb08e884e92c03ab5a05b2d83e75478d458335502222dc89eabf961a43d08ba1
3
+ metadata.gz: 628996f62e649fce9998463a3147bba9690074ccd422d8973b56840f169ddbef
4
+ data.tar.gz: 368fd3265a87abe2f0300741f568194d5f479121fd49ccf51e0fdce6725dd080
5
5
  SHA512:
6
- metadata.gz: 0e78ae57c521f71a09aafec920e852dae0a66068bcc35271029567e053211967e56797e123a6046eb5323a703c6617ca9310d500ead439574c45d6c49c615000
7
- data.tar.gz: aae580287000a506cfd34cfee5ccd00c0ee26194cacf73725462885c37acff442a04ac69ca1ba0a4f4d996fcad2317741773d4a81d2a9cbc1045ecf3270f3053
6
+ metadata.gz: c3b589a20fb9395b6245ace8b113b7c57f541e9077562cece7673e8ba3577c0825bc71ed229902447e7abc735e126e6d2cd7a2b4a5b9385e24b5e5fb7c3596da
7
+ data.tar.gz: 15ff254cb06790546e76b00de892c10e712eb42ca30629b9c527d90034c252993c9de71be6d6b9f3f0cb26745ab554cf71e75e63e18a8b847c510d2bad16d45c
checksums.yaml.gz.sig CHANGED
Binary file
@@ -35,12 +35,20 @@ module Protocol
35
35
  super
36
36
  end
37
37
 
38
+ VALID_CHUNK_LENGTH = /\A[0-9a-fA-F]+\z/
39
+
38
40
  # Follows the procedure outlined in https://tools.ietf.org/html/rfc7230#section-4.1.3
39
41
  def read
40
42
  return nil if @finished
41
43
 
44
+ length, extensions = read_line.split(";", 2)
45
+
46
+ unless length =~ VALID_CHUNK_LENGTH
47
+ raise BadRequest, "Invalid chunk length: #{length.dump}"
48
+ end
49
+
42
50
  # It is possible this line contains chunk extension, so we use `to_i` to only consider the initial integral part:
43
- length = read_line.to_i(16)
51
+ length = Integer(length, 16)
44
52
 
45
53
  if length == 0
46
54
  @finished = true
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2022, by Samuel Williams.
4
+ # Copyright, 2019-2023, by Samuel Williams.
5
5
 
6
6
  require 'protocol/http/body/readable'
7
7
 
@@ -23,6 +23,7 @@ module Protocol
23
23
  end
24
24
 
25
25
  def close(error = nil)
26
+ # If we are closing the body without fully reading it, the underlying connection is now in an undefined state.
26
27
  if @remaining != 0
27
28
  @stream.close
28
29
  end
@@ -30,14 +31,16 @@ module Protocol
30
31
  super
31
32
  end
32
33
 
34
+ # @raises EOFError if the stream is closed before the expected length is read.
33
35
  def read
34
36
  if @remaining > 0
37
+ # `readpartial` will raise `EOFError` if the stream is closed/finished:
35
38
  if chunk = @stream.readpartial(@remaining)
36
39
  @remaining -= chunk.bytesize
37
40
 
38
41
  return chunk
39
- else
40
- raise EOFError, "Stream closed with #{@remaining} bytes remaining!"
42
+ # else
43
+ # raise EOFError, "Stream closed with #{@remaining} bytes remaining!"
41
44
  end
42
45
  end
43
46
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2022, by Samuel Williams.
4
+ # Copyright, 2019-2023, by Samuel Williams.
5
+ # Copyright, 2019, by Brian Morearty.
5
6
  # Copyright, 2020, by Bruno Sutic.
6
7
 
7
8
  require 'protocol/http/headers'
@@ -31,7 +32,7 @@ module Protocol
31
32
  UPGRADE = 'upgrade'
32
33
 
33
34
  # HTTP/1.x request line parser:
34
- TOKEN = /[!#$%&'*+-\.^_`|~0-9a-zA-Z]+/.freeze
35
+ TOKEN = /[!#$%&'*+\-\.\^_`|~0-9a-zA-Z]+/.freeze
35
36
  REQUEST_LINE = /\A(#{TOKEN}) ([^\s]+) (HTTP\/\d.\d)\z/.freeze
36
37
 
37
38
  # HTTP/1.x header parser:
@@ -63,12 +64,6 @@ module Protocol
63
64
  # The number of requests processed.
64
65
  attr :count
65
66
 
66
- def upgrade?(headers)
67
- if upgrade = headers[UPGRADE]
68
- return upgrade
69
- end
70
- end
71
-
72
67
  def persistent?(version, method, headers)
73
68
  if method == HTTP::Methods::CONNECT
74
69
  return false
@@ -281,7 +276,7 @@ module Protocol
281
276
  chunk_length += chunk.bytesize
282
277
 
283
278
  if chunk_length > length
284
- raise Error, "Trying to write #{chunk_length} bytes, but content length was #{length} bytes!"
279
+ raise ContentLengthError, "Trying to write #{chunk_length} bytes, but content length was #{length} bytes!"
285
280
  end
286
281
 
287
282
  @stream.write(chunk)
@@ -291,7 +286,7 @@ module Protocol
291
286
  @stream.flush
292
287
 
293
288
  if chunk_length != length
294
- raise Error, "Wrote #{chunk_length} bytes, but content length was #{length} bytes!"
289
+ raise ContentLengthError, "Wrote #{chunk_length} bytes, but content length was #{length} bytes!"
295
290
  end
296
291
  end
297
292
 
@@ -400,13 +395,21 @@ module Protocol
400
395
  read_remainder_body
401
396
  end
402
397
 
403
- def read_upgrade_body(protocol)
404
- read_remainder_body
405
- end
406
-
407
398
  HEAD = "HEAD"
408
399
  CONNECT = "CONNECT"
409
400
 
401
+ VALID_CONTENT_LENGTH = /\A\d+\z/
402
+
403
+ def extract_content_length(headers)
404
+ if content_length = headers.delete(CONTENT_LENGTH)
405
+ if content_length =~ VALID_CONTENT_LENGTH
406
+ yield Integer(content_length, 10)
407
+ else
408
+ raise BadRequest, "Invalid content length: #{content_length}"
409
+ end
410
+ end
411
+ end
412
+
410
413
  def read_response_body(method, status, headers)
411
414
  # RFC 7230 3.3.3
412
415
  # 1. Any response to a HEAD request and any response with a 1xx
@@ -415,19 +418,16 @@ module Protocol
415
418
  # header fields, regardless of the header fields present in the
416
419
  # message, and thus cannot contain a message body.
417
420
  if method == HTTP::Methods::HEAD
418
- if content_length = headers.delete(CONTENT_LENGTH)
419
- length = Integer(content_length)
420
-
421
+ extract_content_length(headers) do |length|
421
422
  if length > 0
422
423
  return read_head_body(length)
423
- elsif length == 0
424
- return nil
425
424
  else
426
- raise BadRequest, "Invalid content length: #{content_length}"
425
+ return nil
427
426
  end
428
- else
429
- return nil
430
427
  end
428
+
429
+ # There is no body for a HEAD request if there is no content length:
430
+ return nil
431
431
  end
432
432
 
433
433
  if (status >= 100 and status < 200) or status == 204 or status == 304
@@ -499,14 +499,11 @@ module Protocol
499
499
  # the recipient times out before the indicated number of octets are
500
500
  # received, the recipient MUST consider the message to be
501
501
  # incomplete and close the connection.
502
- if content_length = headers.delete(CONTENT_LENGTH)
503
- length = Integer(content_length)
502
+ extract_content_length(headers) do |length|
504
503
  if length > 0
505
504
  return read_fixed_body(length)
506
- elsif length == 0
507
- return nil
508
505
  else
509
- raise BadRequest, "Invalid content length: #{content_length}"
506
+ return nil
510
507
  end
511
508
  end
512
509
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2022, by Samuel Williams.
4
+ # Copyright, 2019-2023, by Samuel Williams.
5
5
 
6
6
  require 'protocol/http/error'
7
7
 
@@ -13,6 +13,10 @@ module Protocol
13
13
  class InvalidRequest < Error
14
14
  end
15
15
 
16
+ # The specified content length and the given content's length do not match.
17
+ class ContentLengthError < Error
18
+ end
19
+
16
20
  # The request was parsed correctly, but was invalid for some other reason.
17
21
  class BadRequest < Error
18
22
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2022, by Samuel Williams.
4
+ # Copyright, 2019-2023, by Samuel Williams.
5
5
 
6
6
  module Protocol
7
7
  module HTTP1
8
- VERSION = "0.14.6"
8
+ VERSION = "0.15.1"
9
9
  end
10
10
  end
data/license.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2019-2022, by Samuel Williams.
3
+ Copyright, 2019-2023, by Samuel Williams.
4
+ Copyright, 2019, by Brian Morearty.
5
+ Copyright, 2020, by Olle Jonsson.
4
6
  Copyright, 2020, by Bruno Sutic.
5
7
 
6
8
  Permission is hereby granted, free of charge, to any person obtaining a copy
data/readme.md CHANGED
@@ -61,32 +61,18 @@ end
61
61
 
62
62
  ## Contributing
63
63
 
64
- 1. Fork it
65
- 2. Create your feature branch (`git checkout -b my-new-feature`)
66
- 3. Commit your changes (`git commit -am 'Add some feature'`)
67
- 4. Push to the branch (`git push origin my-new-feature`)
68
- 5. Create new Pull Request
69
-
70
- ## License
71
-
72
- Released under the MIT license.
73
-
74
- Copyright, 2019, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
75
-
76
- Permission is hereby granted, free of charge, to any person obtaining a copy
77
- of this software and associated documentation files (the "Software"), to deal
78
- in the Software without restriction, including without limitation the rights
79
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
80
- copies of the Software, and to permit persons to whom the Software is
81
- furnished to do so, subject to the following conditions:
82
-
83
- The above copyright notice and this permission notice shall be included in
84
- all copies or substantial portions of the Software.
85
-
86
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
87
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
88
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
89
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
90
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
91
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
92
- THE SOFTWARE.
64
+ We welcome contributions to this project.
65
+
66
+ 1. Fork it.
67
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
68
+ 3. Commit your changes (`git commit -am 'Add some feature'`).
69
+ 4. Push to the branch (`git push origin my-new-feature`).
70
+ 5. Create new Pull Request.
71
+
72
+ ### Developer Certificate of Origin
73
+
74
+ This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted.
75
+
76
+ ### Contributor Covenant
77
+
78
+ This project is governed by [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-http1
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.6
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -40,7 +40,7 @@ cert_chain:
40
40
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
41
41
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
42
42
  -----END CERTIFICATE-----
43
- date: 2022-08-29 00:00:00.000000000 Z
43
+ date: 2023-07-30 00:00:00.000000000 Z
44
44
  dependencies:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: protocol-http
@@ -56,76 +56,6 @@ dependencies:
56
56
  - - "~>"
57
57
  - !ruby/object:Gem::Version
58
58
  version: '0.22'
59
- - !ruby/object:Gem::Dependency
60
- name: bundler
61
- requirement: !ruby/object:Gem::Requirement
62
- requirements:
63
- - - ">="
64
- - !ruby/object:Gem::Version
65
- version: '0'
66
- type: :development
67
- prerelease: false
68
- version_requirements: !ruby/object:Gem::Requirement
69
- requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: '0'
73
- - !ruby/object:Gem::Dependency
74
- name: covered
75
- requirement: !ruby/object:Gem::Requirement
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- version: '0'
80
- type: :development
81
- prerelease: false
82
- version_requirements: !ruby/object:Gem::Requirement
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- version: '0'
87
- - !ruby/object:Gem::Dependency
88
- name: rspec
89
- requirement: !ruby/object:Gem::Requirement
90
- requirements:
91
- - - "~>"
92
- - !ruby/object:Gem::Version
93
- version: '3.0'
94
- type: :development
95
- prerelease: false
96
- version_requirements: !ruby/object:Gem::Requirement
97
- requirements:
98
- - - "~>"
99
- - !ruby/object:Gem::Version
100
- version: '3.0'
101
- - !ruby/object:Gem::Dependency
102
- name: rspec-files
103
- requirement: !ruby/object:Gem::Requirement
104
- requirements:
105
- - - "~>"
106
- - !ruby/object:Gem::Version
107
- version: '1.0'
108
- type: :development
109
- prerelease: false
110
- version_requirements: !ruby/object:Gem::Requirement
111
- requirements:
112
- - - "~>"
113
- - !ruby/object:Gem::Version
114
- version: '1.0'
115
- - !ruby/object:Gem::Dependency
116
- name: rspec-memory
117
- requirement: !ruby/object:Gem::Requirement
118
- requirements:
119
- - - "~>"
120
- - !ruby/object:Gem::Version
121
- version: '1.0'
122
- type: :development
123
- prerelease: false
124
- version_requirements: !ruby/object:Gem::Requirement
125
- requirements:
126
- - - "~>"
127
- - !ruby/object:Gem::Version
128
- version: '1.0'
129
59
  description:
130
60
  email:
131
61
  executables: []
@@ -154,14 +84,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
84
  requirements:
155
85
  - - ">="
156
86
  - !ruby/object:Gem::Version
157
- version: '2.4'
87
+ version: 2.7.6b
158
88
  required_rubygems_version: !ruby/object:Gem::Requirement
159
89
  requirements:
160
90
  - - ">="
161
91
  - !ruby/object:Gem::Version
162
92
  version: '0'
163
93
  requirements: []
164
- rubygems_version: 3.3.7
94
+ rubygems_version: 3.4.10
165
95
  signing_key:
166
96
  specification_version: 4
167
97
  summary: A low level implementation of the HTTP/1 protocol.
metadata.gz.sig CHANGED
Binary file