Skip to content

Commit b6445cf

Browse files
committed
Cover QUERY method and documentation
1 parent 2f2dbe0 commit b6445cf

10 files changed

Lines changed: 88 additions & 3 deletions

File tree

‎lib/protocol/http/body/deflate.rb‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,10 @@ def self.for(body, window_size = GZIP, level = DEFAULT_LEVEL)
110110
#
111111
# @returns [String | Nil] the compressed chunk or `nil` if the stream is closed.
112112
def read
113-
return if @stream.finished?
113+
if @stream.finished?
114+
# Once the stream is finished, there is no more compressed output to produce:
115+
return nil
116+
end
114117

115118
# The stream might have been closed while waiting for the chunk to come in.
116119
while chunk = super

‎lib/protocol/http/body/stream.rb‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ def read_until(pattern, offset = 0, chomp: false)
200200
split_offset = pattern.bytesize - 1
201201

202202
@buffer ||= read_next
203-
return nil if @buffer.nil?
203+
if @buffer.nil?
204+
# Without any buffered input, there is nothing to search for:
205+
return nil
206+
end
204207

205208
until index = @buffer.index(pattern, offset)
206209
offset = @buffer.bytesize - split_offset

‎lib/protocol/http/header/accept_charset.rb‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,19 @@ class AcceptCharset < Split
1717
# https://tools.ietf.org/html/rfc7231#section-5.3.3
1818
CHARSET = /\A(?<name>#{TOKEN})(;q=(?<q>#{QVALUE}))?\z/
1919

20+
# A parsed character set entry with an optional quality factor.
2021
Charset = Struct.new(:name, :q) do
22+
# The quality factor for this character set.
23+
#
24+
# @returns [Float] the parsed quality factor, defaulting to `1.0`.
2125
def quality_factor
2226
(q || 1.0).to_f
2327
end
2428

29+
# Compare character sets by descending quality factor.
30+
#
31+
# @parameter other [Charset] the other character set to compare.
32+
# @returns [Integer] the comparison result.
2533
def <=> other
2634
other.quality_factor <=> self.quality_factor
2735
end

‎lib/protocol/http/header/accept_encoding.rb‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,19 @@ class AcceptEncoding < Split
2020
# https://tools.ietf.org/html/rfc7231#section-5.3.4
2121
ENCODING = /\A(?<name>#{TOKEN})(;q=(?<q>#{QVALUE}))?\z/
2222

23+
# A parsed content encoding entry with an optional quality factor.
2324
Encoding = Struct.new(:name, :q) do
25+
# The quality factor for this encoding.
26+
#
27+
# @returns [Float] the parsed quality factor, defaulting to `1.0`.
2428
def quality_factor
2529
(q || 1.0).to_f
2630
end
2731

32+
# Compare encodings by descending quality factor.
33+
#
34+
# @parameter other [Encoding] the other encoding to compare.
35+
# @returns [Integer] the comparison result.
2836
def <=> other
2937
other.quality_factor <=> self.quality_factor
3038
end

‎lib/protocol/http/header/accept_language.rb‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,19 @@ class AcceptLanguage < Split
2323
# https://greenbytes.de/tech/webdav/rfc7231.html#quality.values
2424
LANGUAGE = /\A(?<name>#{NAME})(\s*;\s*q=(?<q>#{QVALUE}))?\z/
2525

26+
# A parsed language entry with an optional quality factor.
2627
Language = Struct.new(:name, :q) do
28+
# The quality factor for this language.
29+
#
30+
# @returns [Float] the parsed quality factor, defaulting to `1.0`.
2731
def quality_factor
2832
(q || 1.0).to_f
2933
end
3034

35+
# Compare languages by descending quality factor.
36+
#
37+
# @parameter other [Language] the other language to compare.
38+
# @returns [Integer] the comparison result.
3139
def <=> other
3240
other.quality_factor <=> self.quality_factor
3341
end

‎lib/protocol/http/header/te.rb‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,24 @@ class TE < Split
4545

4646
# A single transfer coding entry with optional quality factor
4747
TransferCoding = Struct.new(:name, :q) do
48+
# The quality factor for this transfer coding.
49+
#
50+
# @returns [Float] the parsed quality factor, defaulting to `1.0`.
4851
def quality_factor
4952
(q || 1.0).to_f
5053
end
5154

55+
# Compare transfer codings by descending quality factor.
56+
#
57+
# @parameter other [TransferCoding] the other transfer coding to compare.
58+
# @returns [Integer] the comparison result.
5259
def <=> other
5360
other.quality_factor <=> self.quality_factor
5461
end
5562

63+
# Convert the transfer coding entry to a header value.
64+
#
65+
# @returns [String] the formatted transfer coding with quality factor when present.
5666
def to_s
5767
if q && q != 1.0
5868
"#{name};q=#{q}"
@@ -143,4 +153,3 @@ def self.trailer?
143153
end
144154
end
145155
end
146-

‎readme.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ Please see the [project documentation](https://socketry.github.io/protocol-http/
3030

3131
Please see the [project releases](https://socketry.github.io/protocol-http/releases/index) for all releases.
3232

33+
### Unreleased
34+
35+
- Add support for the HTTP `QUERY` method.
36+
3337
### v0.62.1
3438

3539
- Fix handling of `Stream#read(0)`, it must return a mutable string (or clear the given buffer).

‎test/protocol/http/body/stream.rb‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@
208208
it "can read until a pattern which isn't encountered" do
209209
expect(stream.read_until("X")).to be_nil
210210
end
211+
212+
with "empty input" do
213+
let(:input) {Protocol::HTTP::Body::Buffered.new}
214+
215+
it "returns nil" do
216+
expect(stream.read_until("X")).to be_nil
217+
end
218+
end
211219
end
212220

213221
with "#gets" do

‎test/protocol/http/methods.rb‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# Copyright, 2019-2025, by Samuel Williams.
55

66
require "protocol/http/methods"
7+
require "protocol/http/request"
78

89
ValidMethod = Sus::Shared("valid method") do |name|
910
it "defines #{name} method" do
@@ -39,6 +40,23 @@
3940
expect(subject.constants.length).to be == 10
4041
end
4142

43+
it "defines QUERY helper method" do
44+
middleware = Class.new(subject) do
45+
attr :request
46+
47+
def call(request)
48+
@request = request
49+
end
50+
end.new
51+
52+
middleware.query("/search", body: "term=ruby")
53+
54+
expect(middleware.request).to have_attributes(
55+
method: be == "QUERY",
56+
path: be == "/search",
57+
)
58+
end
59+
4260
with ".valid?" do
4361
with "FOOBAR" do
4462
it "is not a valid method" do

‎test/protocol/http/request.rb‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,22 @@
136136
end
137137
end
138138

139+
with "POST request without a body" do
140+
let(:request) {subject["POST", "/submit"]}
141+
142+
it "should not be idempotent" do
143+
expect(request).not.to be(:idempotent?)
144+
end
145+
end
146+
147+
with "PUT request with a body" do
148+
let(:request) {subject["PUT", "/resource", body: "content"]}
149+
150+
it "should not be idempotent" do
151+
expect(request).not.to be(:idempotent?)
152+
end
153+
end
154+
139155
it "should have a string representation" do
140156
expect(request.to_s).to be == "http://localhost: GET /index.html HTTP/1.0"
141157
end

0 commit comments

Comments
 (0)