Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions lib/protocol/http/body/head.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,24 @@ module Body
# Represents a body suitable for HEAD requests, in other words, a body that is empty and has a known length.
class Head < Readable
# Create a head body for the given body, capturing its length and then closing it.
def self.for(body)
head = self.new(body.length)

body.close
#
# If a body is provided, the length is determined from the body, and the body is closed.
# If no body is provided, and the content length is provided, a head body is created with that length.
# This is useful for creating a head body when you only know the content length but not the actual body, which may happen in adapters for HTTP applications where the application may not provide a body for HEAD requests, but the content length is known.
#
# @parameter body [Readable | Nil] the body to create a head for.
# @parameter length [Integer | Nil] the content length of the body, if known.
# @returns [Head | Nil] the head body, or nil if the body is nil.
def self.for(body, length = nil)
if body
head = self.new(body.length)
body.close
return head
elsif length
return self.new(length)
end

return head
return nil
end

# Initialize the head body with the given length.
Expand Down
1 change: 1 addition & 0 deletions releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- `Protocol::HTTP::Headers` now raise a `DuplicateHeaderError` when a duplicate singleton header (e.g. `content-length`) is added.
- `Protocol::HTTP::Headers#add` now coerces the value to a string when adding a header, ensuring consistent behaviour.
- `Protocol::HTTP::Body::Head.for` now accepts an optional `length` parameter, allowing it to create a head body even when the body is not provided, based on the known content length.

## v0.50.0

Expand Down
31 changes: 25 additions & 6 deletions test/protocol/http/body/head.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,33 @@
end

with ".for" do
let(:source) {Protocol::HTTP::Body::Buffered.wrap("!")}
let(:body) {subject.for(source)}
with "body" do
let(:source) {Protocol::HTTP::Body::Buffered.wrap("!")}
let(:body) {subject.for(source)}

it "captures length and closes existing body" do
expect(source).to receive(:close)

expect(body).to have_attributes(length: be == 1)
body.close
end
end

it "captures length and closes existing body" do
expect(source).to receive(:close)
with "content length" do
let(:body) {subject.for(nil, 42)}

expect(body).to have_attributes(length: be == 1)
body.close
it "uses the content length if no body is provided" do
expect(body).to have_attributes(length: be == 42)
expect(body).to be(:empty?)
expect(body).to be(:ready?)
end
end
end

with ".for with nil body" do
it "returns nil when body is nil" do
body = subject.for(nil)
expect(body).to be_nil
end
end
end
Loading