Skip to content

Commit 8d7df08

Browse files
committed
Reapply "Add priority header. (#73)"
This reverts commit caed992.
1 parent caed992 commit 8d7df08

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# frozen_string_literal: true
2+
3+
# Released under the MIT License.
4+
# Copyright, 2024, by Samuel Williams.
5+
6+
require_relative "split"
7+
8+
module Protocol
9+
module HTTP
10+
module Header
11+
# Represents the `priority` header, used to indicate the relative importance of an HTTP request.
12+
#
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.
14+
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+
35+
# Initialize the priority header with the given value.
36+
#
37+
# @parameter value [String | Nil] the value of the priority header, if any.
38+
def initialize(value = nil)
39+
super(value&.downcase)
40+
end
41+
42+
# Add a value to the priority header.
43+
def << value
44+
super(value.downcase)
45+
end
46+
47+
# Returns the urgency level if specified.
48+
#
49+
# @returns [String | Nil] the urgency level if specified, or `nil`.
50+
def urgency
51+
if value = self.find{|value| value.start_with?("urgency=")}
52+
_, level = value.split("=", 2)
53+
54+
return level
55+
end
56+
end
57+
58+
# @returns [Boolean] whether the request should be delivered progressively.
59+
def progressive?
60+
self.include?(PROGRESSIVE)
61+
end
62+
end
63+
end
64+
end
65+
end

lib/protocol/http/headers.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
require_relative "header/vary"
1414
require_relative "header/authorization"
1515
require_relative "header/date"
16+
require_relative "header/priority"
1617

1718
module Protocol
1819
module HTTP
@@ -246,6 +247,7 @@ def []= key, value
246247
"connection" => Header::Connection,
247248
"cache-control" => Header::CacheControl,
248249
"vary" => Header::Vary,
250+
"priority" => Header::Priority,
249251

250252
# Headers specifically for proxies:
251253
"via" => Split,
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# frozen_string_literal: true
2+
3+
# Released under the MIT License.
4+
# Copyright, 2024, by Samuel Williams.
5+
6+
require "protocol/http/header/priority"
7+
8+
describe Protocol::HTTP::Header::Priority do
9+
let(:header) {subject.new(description)}
10+
11+
with "urgency=low, progressive" do
12+
it "correctly parses priority header" do
13+
expect(header).to have_attributes(
14+
urgency: be == "low",
15+
progressive?: be == true,
16+
)
17+
end
18+
end
19+
20+
with "urgency=high" do
21+
it "correctly parses priority header" do
22+
expect(header).to have_attributes(
23+
urgency: be == "high",
24+
progressive?: be == false,
25+
)
26+
end
27+
end
28+
29+
with "progressive" do
30+
it "correctly parses progressive flag" do
31+
expect(header).to have_attributes(
32+
urgency: be_nil,
33+
progressive?: be == true,
34+
)
35+
end
36+
end
37+
38+
with "urgency=background" do
39+
it "correctly parses urgency" do
40+
expect(header).to have_attributes(
41+
urgency: be == "background",
42+
)
43+
end
44+
end
45+
46+
with "urgency=extreeeeem, progressive" do
47+
it "gracefully handles non-standard urgency" do
48+
expect(header).to have_attributes(
49+
# Non-standard value is preserved
50+
urgency: be == "extreeeeem",
51+
progressive?: be == true,
52+
)
53+
end
54+
end
55+
56+
with "urgency=low, urgency=high" do
57+
it "prioritizes the first urgency directive" do
58+
expect(header).to have_attributes(
59+
urgency: be == "low", # First occurrence takes precedence
60+
)
61+
end
62+
end
63+
64+
with "#<<" do
65+
let(:header) {subject.new}
66+
67+
it "can append values" do
68+
header << "urgency=low"
69+
expect(header).to have_attributes(
70+
urgency: be == "low",
71+
)
72+
end
73+
74+
it "can append progressive flag" do
75+
header << "progressive"
76+
expect(header).to have_attributes(
77+
progressive?: be == true,
78+
)
79+
end
80+
end
81+
end

0 commit comments

Comments
 (0)