protocol-rack 0.13.0 → 0.15.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: b70faf13a5271971f02ddae3e19e17262c9df2ce74832cce7e0f6312265d76df
4
- data.tar.gz: e9a4a1dfc0cb419d6395a7e68300f270e26398fadb00661b08093c60b47b7ea2
3
+ metadata.gz: a0994443c638a7cf147afcb7a8b88a1a6e5e8ab607071c10792d65c912fb9b37
4
+ data.tar.gz: 22a6c27089e34db868a7af15fac1061979791872c811aef51762b68435fb9346
5
5
  SHA512:
6
- metadata.gz: 1d8a7f11acb1220d0ed05626c4ddfb87ef23578922741e92d15bf32e0e0294c433ebfa2149e538f10352695b3c0cf30af69667ab34033beead13f799dbbbdad5
7
- data.tar.gz: 4d59623d81149838f7b2bf5f0ce67a13bdf39a0d5b04e17367ab6d07d57468d008834d6ad439cd6f41e42dcf95e6d314694334b38bfcfe02ba0d96f5a35b5def
6
+ metadata.gz: 60caa82495eb534bfb3367009b7567304c1c36b2db646fbee99d7c68eaba810c9913ad8c847c7939e0d60bb29bd049bdfb67ff365f68f9142b65d6cf7a7bf8f8
7
+ data.tar.gz: 63313385d9603b0bdaddeb39410dbcf7a3485652478d886ffbb5e8ea926a1b5006bcbd21bdc3b6a3851e43f1f601ded523021d700cd00dd0d2ab252b529378fa
checksums.yaml.gz.sig CHANGED
Binary file
@@ -119,7 +119,7 @@ module Protocol
119
119
 
120
120
  # HTTP/2 prefers `:authority` over `host`, so we do this for backwards compatibility.
121
121
  env[CGI::HTTP_HOST] ||= request.authority
122
-
122
+
123
123
  if peer = request.peer
124
124
  env[CGI::REMOTE_ADDR] = peer.ip_address
125
125
  end
@@ -6,7 +6,9 @@
6
6
  require_relative "body/streaming"
7
7
  require_relative "body/enumerable"
8
8
  require_relative "constants"
9
+
9
10
  require "protocol/http/body/completable"
11
+ require "protocol/http/body/head"
10
12
 
11
13
  module Protocol
12
14
  module Rack
@@ -37,8 +39,9 @@ module Protocol
37
39
  # @parameter headers [Hash] The response headers.
38
40
  # @parameter body [Object] The response body to wrap.
39
41
  # @parameter input [Object] Optional input for streaming bodies.
42
+ # @parameter head [Boolean] Indicates if this is a HEAD request, which should not have a body.
40
43
  # @returns [Protocol::HTTP::Body] The wrapped response body.
41
- def self.wrap(env, status, headers, body, input = nil)
44
+ def self.wrap(env, status, headers, body, input = nil, head = false)
42
45
  # In no circumstance do we want this header propagating out:
43
46
  if length = headers.delete(CONTENT_LENGTH)
44
47
  # We don't really trust the user to provide the right length to the transport.
@@ -84,6 +87,19 @@ module Protocol
84
87
  end
85
88
  end
86
89
 
90
+ # There are two main situations we need to handle:
91
+ # 1. The application has the `Rack::Head` middleware in the stack, which means we should not return a body, and the application is also responsible for setting the content-length header. `Rack::Head` will result in an empty enumerable body.
92
+ # 2. The application does not have `Rack::Head`, in which case it will return a body and we need to extract the length.
93
+ # In both cases, we need to ensure that the body is wrapped correctly. If there is no body and we don't know the length, we also just return `nil`.
94
+ if head
95
+ if body
96
+ body = ::Protocol::HTTP::Body::Head.for(body)
97
+ elsif length
98
+ body = ::Protocol::HTTP::Body::Head.new(length)
99
+ end
100
+ # Otherwise, body is `nil` and we don't know the length either.
101
+ end
102
+
87
103
  return body
88
104
  end
89
105
 
@@ -4,7 +4,7 @@
4
4
  # Copyright, 2022-2025, by Samuel Williams.
5
5
  # Copyright, 2023, by Genki Takiuchi.
6
6
 
7
- require "protocol/http/body/stream"
7
+ require "io/stream/readable"
8
8
 
9
9
  module Protocol
10
10
  module Rack
@@ -14,22 +14,21 @@ module Protocol
14
14
  #
15
15
  # This implementation is not always rewindable, to avoid buffering the input when handling large uploads. See {Rewindable} for more details.
16
16
  class Input
17
+ include IO::Stream::Readable
18
+
17
19
  # Initialize the input wrapper.
18
20
  # @parameter body [Protocol::HTTP::Body::Readable]
19
- def initialize(body)
21
+ def initialize(body, ...)
20
22
  @body = body
21
23
  @closed = false
22
24
 
23
- # Will hold remaining data in `#read`.
24
- @buffer = nil
25
+ super(...)
25
26
  end
26
27
 
27
28
  # The input body.
28
29
  # @attribute [Protocol::HTTP::Body::Readable]
29
30
  attr :body
30
31
 
31
- include Protocol::HTTP::Body::Stream::Reader
32
-
33
32
  # Enumerate chunks of the request body.
34
33
  # @yields {|chunk| ...}
35
34
  # @parameter chunk [String]
@@ -65,7 +64,6 @@ module Protocol
65
64
  # If the body is not rewindable, this will fail.
66
65
  @body.rewind
67
66
 
68
- @buffer = nil
69
67
  @finished = false
70
68
  @closed = false
71
69
 
@@ -87,7 +85,11 @@ module Protocol
87
85
 
88
86
  private
89
87
 
90
- def read_next
88
+ def flush
89
+ # No-op.
90
+ end
91
+
92
+ def sysread(size, buffer = nil)
91
93
  if @body
92
94
  # User's may forget to call #close...
93
95
  if chunk = @body.read
@@ -98,7 +100,15 @@ module Protocol
98
100
  @closed = true
99
101
  end
100
102
 
101
- return chunk
103
+ if buffer
104
+ # If a buffer is provided, we copy the chunk into it:
105
+ buffer.replace(chunk)
106
+ else
107
+ # Otherwise we return the chunk directly:
108
+ buffer = chunk
109
+ end
110
+
111
+ return buffer
102
112
  else
103
113
  unless @closed
104
114
  # So if we are at the end of the stream, we close it automatically:
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022-2024, by Samuel Williams.
4
+ # Copyright, 2022-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "body"
7
7
  require_relative "constants"
@@ -50,12 +50,7 @@ module Protocol
50
50
  body = hijack_body
51
51
  end
52
52
 
53
- body = Body.wrap(env, status, headers, body, request&.body)
54
-
55
- if request&.head?
56
- # I thought about doing this in Output.wrap, but decided the semantics are too tricky. Specifically, the various ways a rack response body can be wrapped, and the need to invoke #close at the right point.
57
- body = ::Protocol::HTTP::Body::Head.for(body)
58
- end
53
+ body = Body.wrap(env, status, headers, body, request&.body, request&.head?)
59
54
 
60
55
  protocol = meta[RACK_PROTOCOL]
61
56
 
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Protocol
7
7
  module Rack
8
- VERSION = "0.13.0"
8
+ VERSION = "0.15.0"
9
9
  end
10
10
  end
data/readme.md CHANGED
@@ -67,6 +67,14 @@ run proc{|env|
67
67
 
68
68
  Please see the [project releases](https://socketry.github.io/protocol-rack/releases/index) for all releases.
69
69
 
70
+ ### v0.15.0
71
+
72
+ - Use `IO::Stream::Readable` for the input body, which is a better tested and more robust interface.
73
+
74
+ ### v0.14.0
75
+
76
+ - Handling of `HEAD` requests is now more robust.
77
+
70
78
  ### v0.13.0
71
79
 
72
80
  - 100% test and documentation coverage.
data/releases.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Releases
2
2
 
3
+ ## v0.15.0
4
+
5
+ - Use `IO::Stream::Readable` for the input body, which is a better tested and more robust interface.
6
+
7
+ ## v0.14.0
8
+
9
+ - Handling of `HEAD` requests is now more robust.
10
+
3
11
  ## v0.13.0
4
12
 
5
13
  - 100% test and documentation coverage.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -38,8 +38,22 @@ cert_chain:
38
38
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
39
39
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
40
40
  -----END CERTIFICATE-----
41
- date: 2025-05-10 00:00:00.000000000 Z
41
+ date: 1980-01-02 00:00:00.000000000 Z
42
42
  dependencies:
43
+ - !ruby/object:Gem::Dependency
44
+ name: io-stream
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0.10'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0.10'
43
57
  - !ruby/object:Gem::Dependency
44
58
  name: protocol-http
45
59
  requirement: !ruby/object:Gem::Requirement
@@ -111,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
125
  - !ruby/object:Gem::Version
112
126
  version: '0'
113
127
  requirements: []
114
- rubygems_version: 3.6.2
128
+ rubygems_version: 3.6.7
115
129
  specification_version: 4
116
130
  summary: An implementation of the Rack protocol/specification.
117
131
  test_files: []
metadata.gz.sig CHANGED
Binary file