async-http 0.104.0 → 0.105.0

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: fe8ada6c5d6f03e7523b0867a298fe517d04602231bf2d06e84e49078cbb9eca
4
- data.tar.gz: ffe7b6eccb947931184ba506de0cf9515a9f03f81610fc4134618efd7322838a
3
+ metadata.gz: 47403cea6ef8a84389b0cbef1a81af900cc950f88657cb789bed7fa51550598b
4
+ data.tar.gz: 0fb0d5b68a012f6cb047d846d991a98cb8bf56cc6883d169f62d5089dfa4726e
5
5
  SHA512:
6
- metadata.gz: ad0e7abf8b4b720acbe07f7adad14b816ebde19ddbdc549b791b18a09e232191780cf160274469077c64b4073c15c11897b6d8b542d674c97b076f31fc4c9b3b
7
- data.tar.gz: 501720fd203bec472b0a5a01668ab3ce447b45b290ef303954c5703764b771c66256dfbbcad249b1414c982f18b20ef5d288696f9391fa92bb349d3b4be68d0b
6
+ metadata.gz: 317d49810ec9c0768c2ef0e12ca9881749648521e42d2fc84deff08434ec20d47b11d4a69e422a2f58e9e0de8fc061a901240c4ddb09a83909144b7a65d42c79
7
+ data.tar.gz: 70de4f9259a9290c00117050b068e4da34f7f91c475ca5ccdc73efb8293c1f39031ce38545677ccf21f5cb7a965987887a9e1274b36703431ff2edf068252e3e
checksums.yaml.gz.sig CHANGED
Binary file
@@ -12,6 +12,7 @@ require_relative "finishable"
12
12
 
13
13
  require "async/promise"
14
14
  require "console/event/failure"
15
+ require "protocol/http/body/buffered"
15
16
 
16
17
  module Async
17
18
  module HTTP
@@ -33,12 +34,15 @@ module Async
33
34
  @ready.resolve(nil)
34
35
  end
35
36
 
36
- # Write a failure response with the given status code.
37
+ # Write a failure response with the given status code and error class name.
37
38
  # @parameter status [Integer] The HTTP status code to send.
38
- def fail_request(status)
39
+ # @parameter error [Exception] The error which caused the request to fail.
40
+ def fail_request(status, error)
41
+ body = ::Protocol::HTTP::Body::Buffered.wrap(error.class.name)
42
+
39
43
  @persistent = false
40
- write_response(@version, status, {})
41
- write_body(@version, nil)
44
+ write_response(@version, status, {"content-type" => "text/plain; charset=utf-8"})
45
+ write_body(@version, body)
42
46
  rescue => error
43
47
  # At this point, there is very little we can do to recover:
44
48
  Console.debug(self, "Failed to write failure response!", error)
@@ -61,8 +65,8 @@ module Async
61
65
  end
62
66
 
63
67
  return request
64
- rescue ::Protocol::HTTP1::BadRequest
65
- fail_request(400)
68
+ rescue ::Protocol::HTTP::BadRequest => error
69
+ fail_request(400, error)
66
70
  # Conceivably we could retry here, but we don't really know how bad the error is, so it's better to just fail:
67
71
  raise
68
72
  end
@@ -24,6 +24,29 @@ module Async
24
24
 
25
25
  attr :request
26
26
 
27
+ # Write a failure response with the given status code and error class name.
28
+ # @parameter status [Integer] The HTTP status code to send.
29
+ # @parameter error [Exception] The error which caused the request to fail.
30
+ def fail_request(status, error)
31
+ body = error.class.name
32
+ headers = [
33
+ [STATUS, status.to_s],
34
+ ["content-type", "text/plain; charset=utf-8"],
35
+ ]
36
+
37
+ if @request.head?
38
+ send_headers(headers, ::Protocol::HTTP2::END_STREAM)
39
+ else
40
+ send_headers(headers)
41
+ send_data(body, ::Protocol::HTTP2::END_STREAM)
42
+ end
43
+
44
+ # The peer may still be sending a request body. The response is complete, so release the stream without reporting a protocol error.
45
+ send_reset_stream(::Protocol::HTTP2::Error::NO_ERROR) unless closed?
46
+ rescue => error
47
+ Console.debug(self, "Failed to write failure response!", error)
48
+ end
49
+
27
50
  # Process the initial headers received from the client and construct the request.
28
51
  # @parameter headers [Array] The list of header key-value pairs.
29
52
  # @parameter end_stream [Boolean] Whether the stream is complete after these headers.
@@ -67,11 +90,13 @@ module Async
67
90
  end
68
91
  end
69
92
 
70
- @request.headers = @headers
71
-
72
93
  unless @request.valid?
73
94
  raise ::Protocol::HTTP2::HeaderError, "Request is missing required headers!"
74
95
  else
96
+ # Validate structured headers before exposing the request to the application:
97
+ @headers.to_h
98
+ @request.headers = @headers
99
+
75
100
  # We only construct the input/body if data is coming.
76
101
  unless end_stream
77
102
  @request.body = prepare_input(@length)
@@ -82,6 +107,8 @@ module Async
82
107
  end
83
108
 
84
109
  return headers
110
+ rescue ::Protocol::HTTP::BadRequest => error
111
+ fail_request(400, error)
85
112
  end
86
113
 
87
114
  # Called when the stream is closed.
@@ -70,6 +70,8 @@ module Async
70
70
  # If this returns nil, we assume that the connection has been hijacked.
71
71
  self.call(request)
72
72
  end
73
+ rescue ::Protocol::HTTP::BadRequest
74
+ # Ignore bad requests, just close the connection.
73
75
  ensure
74
76
  connection&.close
75
77
  end
@@ -7,6 +7,6 @@
7
7
  module Async
8
8
  # @namespace
9
9
  module HTTP
10
- VERSION = "0.104.0"
10
+ VERSION = "0.105.0"
11
11
  end
12
12
  end
data/readme.md CHANGED
@@ -20,6 +20,10 @@ Please see the [project documentation](https://socketry.github.io/async-http/) f
20
20
 
21
21
  Please see the [project releases](https://socketry.github.io/async-http/releases/index) for all releases.
22
22
 
23
+ ### v0.105.0
24
+
25
+ - Respond with `400 Bad Request` for any `Protocol::HTTP::BadRequest` raised while parsing HTTP/1 or HTTP/2 requests, include the exception class name without reflecting request data, and avoid reporting them as unhandled server errors.
26
+
23
27
  ### v0.103.0
24
28
 
25
29
  - Handle `RST_STREAM(NO_ERROR)` as an orderly HTTP/2 stream closure while still failing requests whose streams close before any response headers are received.
@@ -57,10 +61,6 @@ Please see the [project releases](https://socketry.github.io/async-http/releases
57
61
 
58
62
  - Made `metrics` and `traces` optional runtime dependencies. Applications that use the providers should depend on the corresponding gem and require the provider explicitly.
59
63
 
60
- ### v0.95.1
61
-
62
- - Fix handling of reset stream causing complete connection failure.
63
-
64
64
  ## See Also
65
65
 
66
66
  - [benchmark-http](https://github.com/socketry/benchmark-http) — A benchmarking tool to report on web server concurrency.
data/releases.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Releases
2
2
 
3
+ ## v0.105.0
4
+
5
+ - Respond with `400 Bad Request` for any `Protocol::HTTP::BadRequest` raised while parsing HTTP/1 or HTTP/2 requests, include the exception class name without reflecting request data, and avoid reporting them as unhandled server errors.
6
+
3
7
  ## v0.103.0
4
8
 
5
9
  - Handle `RST_STREAM(NO_ERROR)` as an orderly HTTP/2 stream closure while still failing requests whose streams close before any response headers are received.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.104.0
4
+ version: 0.105.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -125,14 +125,14 @@ dependencies:
125
125
  requirements:
126
126
  - - "~>"
127
127
  - !ruby/object:Gem::Version
128
- version: '0.66'
128
+ version: '0.72'
129
129
  type: :runtime
130
130
  prerelease: false
131
131
  version_requirements: !ruby/object:Gem::Requirement
132
132
  requirements:
133
133
  - - "~>"
134
134
  - !ruby/object:Gem::Version
135
- version: '0.66'
135
+ version: '0.72'
136
136
  - !ruby/object:Gem::Dependency
137
137
  name: protocol-http1
138
138
  requirement: !ruby/object:Gem::Requirement
@@ -261,7 +261,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
261
261
  - !ruby/object:Gem::Version
262
262
  version: '0'
263
263
  requirements: []
264
- rubygems_version: 4.0.10
264
+ rubygems_version: 4.0.16
265
265
  specification_version: 4
266
266
  summary: A HTTP client and server library.
267
267
  test_files: []
metadata.gz.sig CHANGED
Binary file