Skip to content

Commit 875503f

Browse files
committed
Re-implement priority header according to RFC9218.
1 parent 8d7df08 commit 875503f

File tree

2 files changed

+49
-57
lines changed

2 files changed

+49
-57
lines changed

lib/protocol/http/header/priority.rb

+21-31
Original file line numberDiff line numberDiff line change
@@ -10,54 +10,44 @@ module HTTP
1010
module Header
1111
# Represents the `priority` header, used to indicate the relative importance of an HTTP request.
1212
#
13-
# The `priority` header allows clients to express their preference for how resources should be prioritized by the server. It can include directives like `urgency` to specify the importance of a request, and `progressive` to indicate whether a response can be delivered incrementally.
13+
# The `priority` header allows clients to express their preference for how resources should be prioritized by the server. It supports directives like `u=` to specify the urgency level of a request, and `i` to indicate whether a response can be delivered incrementally. The urgency levels range from 0 (highest priority) to 7 (lowest priority), while the `i` directive is a boolean flag.
1414
class Priority < Split
15-
# Urgency levels as defined in RFC 9218:
16-
#
17-
# These levels indicate the relative importance of a request, helping servers and intermediaries allocate resources efficiently. Properly setting urgency can significantly improve user-perceived performance by prioritizing critical content and deferring less important tasks.
18-
module Urgency
19-
# `background` priority indicates a request that is not time-sensitive and can be processed with minimal impact to other tasks. It is ideal for requests like analytics or logging, which do not directly impact the user's current experience.
20-
BACKGROUND = "background"
21-
22-
# `low` priority indicates a request that is important but not critical. It is suitable for content like non-blocking images, videos, or scripts that enhance the experience but do not affect core functionality.
23-
LOW = "low"
24-
25-
# `normal` priority (default) indicates the standard priority for most requests. It is appropriate for content like text, CSS, or essential images that are necessary for the primary user experience but do not require urgent delivery.
26-
NORMAL = "normal"
27-
28-
# `high` priority indicates the highest priority, used for requests that are essential and time-critical to the user experience. Examples include content above-the-fold on a webpage, critical API calls, or resources required for rendering.
29-
HIGH = "high"
30-
end
31-
32-
# The `progressive` flag indicates that the response can be delivered incrementally (progressively) as data becomes available. This is particularly useful for large resources like images or video streams, where partial delivery improves the user experience by allowing content to render or play before the full response is received.
33-
PROGRESSIVE = "progressive"
34-
3515
# Initialize the priority header with the given value.
3616
#
37-
# @parameter value [String | Nil] the value of the priority header, if any.
17+
# @parameter value [String | Nil] the value of the priority header, if any. The value should be a comma-separated string of directives.
3818
def initialize(value = nil)
3919
super(value&.downcase)
4020
end
4121

4222
# Add a value to the priority header.
23+
#
24+
# @parameter value [String] the directive to add to the header.
4325
def << value
4426
super(value.downcase)
4527
end
4628

47-
# Returns the urgency level if specified.
29+
# The default urgency level if not specified.
30+
DEFAULT_URGENCY = 3
31+
32+
# Returns the urgency level if specified. 0 is the highest priority, and 7 is the lowest.
4833
#
49-
# @returns [String | Nil] the urgency level if specified, or `nil`.
50-
def urgency
51-
if value = self.find{|value| value.start_with?("urgency=")}
34+
# @returns [Integer | Nil] the urgency level if specified, or `nil` if not present.
35+
def urgency(default = DEFAULT_URGENCY)
36+
if value = self.find { |value| value.start_with?("u=") }
5237
_, level = value.split("=", 2)
53-
54-
return level
38+
return level.to_i
5539
end
40+
41+
return default
5642
end
5743

58-
# @returns [Boolean] whether the request should be delivered progressively.
59-
def progressive?
60-
self.include?(PROGRESSIVE)
44+
# Checks if the response should be delivered incrementally.
45+
#
46+
# The `i` directive, when present, indicates that the response can be delivered incrementally as data becomes available.
47+
#
48+
# @returns [Boolean] whether the request should be delivered incrementally.
49+
def incremental?
50+
self.include?("i")
6151
end
6252
end
6353
end

test/protocol/http/header/priority.rb

+28-26
Original file line numberDiff line numberDiff line change
@@ -6,75 +6,77 @@
66
require "protocol/http/header/priority"
77

88
describe Protocol::HTTP::Header::Priority do
9-
let(:header) {subject.new(description)}
9+
let(:header) { subject.new(description) }
1010

11-
with "urgency=low, progressive" do
11+
with "u=1, i" do
1212
it "correctly parses priority header" do
1313
expect(header).to have_attributes(
14-
urgency: be == "low",
15-
progressive?: be == true,
14+
urgency: be == 1,
15+
incremental?: be == true,
1616
)
1717
end
1818
end
1919

20-
with "urgency=high" do
20+
with "u=0" do
2121
it "correctly parses priority header" do
2222
expect(header).to have_attributes(
23-
urgency: be == "high",
24-
progressive?: be == false,
23+
urgency: be == 0,
24+
incremental?: be == false,
2525
)
2626
end
2727
end
2828

29-
with "progressive" do
30-
it "correctly parses progressive flag" do
29+
with "i" do
30+
it "correctly parses incremental flag" do
3131
expect(header).to have_attributes(
32-
urgency: be_nil,
33-
progressive?: be == true,
32+
# Default urgency level is used:
33+
urgency: be == 3,
34+
incremental?: be == true,
3435
)
3536
end
3637
end
3738

38-
with "urgency=background" do
39-
it "correctly parses urgency" do
39+
with "u=6" do
40+
it "correctly parses urgency level" do
4041
expect(header).to have_attributes(
41-
urgency: be == "background",
42+
urgency: be == 6,
4243
)
4344
end
4445
end
4546

46-
with "urgency=extreeeeem, progressive" do
47-
it "gracefully handles non-standard urgency" do
47+
with "u=9, i" do
48+
it "gracefully handles non-standard urgency levels" do
4849
expect(header).to have_attributes(
4950
# Non-standard value is preserved
50-
urgency: be == "extreeeeem",
51-
progressive?: be == true,
51+
urgency: be == 9,
52+
incremental?: be == true,
5253
)
5354
end
5455
end
5556

56-
with "urgency=low, urgency=high" do
57+
with "u=2, u=5" do
5758
it "prioritizes the first urgency directive" do
5859
expect(header).to have_attributes(
59-
urgency: be == "low", # First occurrence takes precedence
60+
# First occurrence takes precedence
61+
urgency: be == 2,
6062
)
6163
end
6264
end
6365

6466
with "#<<" do
65-
let(:header) {subject.new}
67+
let(:header) { subject.new }
6668

6769
it "can append values" do
68-
header << "urgency=low"
70+
header << "u=4"
6971
expect(header).to have_attributes(
70-
urgency: be == "low",
72+
urgency: be == 4,
7173
)
7274
end
7375

74-
it "can append progressive flag" do
75-
header << "progressive"
76+
it "can append incremental flag" do
77+
header << "i"
7678
expect(header).to have_attributes(
77-
progressive?: be == true,
79+
incremental?: be == true,
7880
)
7981
end
8082
end

0 commit comments

Comments
 (0)