Skip to content

Commit

Permalink
Add priority header. (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix authored Nov 28, 2024
1 parent f0a9782 commit 5d91c76
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 2 deletions.
62 changes: 62 additions & 0 deletions lib/protocol/http/header/priority.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

require_relative "split"

module Protocol
module HTTP
module Header
class Priority < Split
# Urgency levels as defined in RFC 9218:
#
# 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.
module Urgency
# `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.
BACKGROUND = "background"

# `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.
LOW = "low"

# `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.
NORMAL = "normal"

# `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.
HIGH = "high"
end

# 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.
PROGRESSIVE = "progressive"

# Initialize the priority header with the given value.
#
# @parameter value [String | Nil] the value of the priority header, if any.
def initialize(value = nil)
super(value&.downcase)
end

# Add a value to the priority header.
def << value
super(value.downcase)
end

# Returns the urgency level if specified.
#
# @returns [String | Nil] the urgency level if specified, or `nil`.
def urgency
if value = self.find{|value| value.start_with?("urgency=")}
_, level = value.split("=", 2)

return level
end
end

# @returns [Boolean] whether the request should be delivered progressively.
def progressive?
self.include?(PROGRESSIVE)
end
end
end
end
end
4 changes: 2 additions & 2 deletions lib/protocol/http/header/split.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ module Header
class Split < Array
COMMA = /\s*,\s*/

def initialize(value)
def initialize(value = nil)
if value
super(value.split(COMMA))
else
super([])
super()
end
end

Expand Down
2 changes: 2 additions & 0 deletions lib/protocol/http/headers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
require_relative "header/vary"
require_relative "header/authorization"
require_relative "header/date"
require_relative "header/priority"

module Protocol
module HTTP
Expand Down Expand Up @@ -218,6 +219,7 @@ def []= key, value
"connection" => Header::Connection,
"cache-control" => Header::CacheControl,
"vary" => Header::Vary,
"priority" => Header::Priority,

# Headers specifically for proxies:
"via" => Split,
Expand Down
81 changes: 81 additions & 0 deletions test/protocol/http/header/priority.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2024, by Samuel Williams.

require "protocol/http/header/priority"

describe Protocol::HTTP::Header::Priority do
let(:header) {subject.new(description)}

with "urgency=low, progressive" do
it "correctly parses priority header" do
expect(header).to have_attributes(
urgency: be == "low",
progressive?: be == true,
)
end
end

with "urgency=high" do
it "correctly parses priority header" do
expect(header).to have_attributes(
urgency: be == "high",
progressive?: be == false,
)
end
end

with "progressive" do
it "correctly parses progressive flag" do
expect(header).to have_attributes(
urgency: be_nil,
progressive?: be == true,
)
end
end

with "urgency=background" do
it "correctly parses urgency" do
expect(header).to have_attributes(
urgency: be == "background",
)
end
end

with "urgency=extreeeeem, progressive" do
it "gracefully handles non-standard urgency" do
expect(header).to have_attributes(
# Non-standard value is preserved
urgency: be == "extreeeeem",
progressive?: be == true,
)
end
end

with "urgency=low, urgency=high" do
it "prioritizes the first urgency directive" do
expect(header).to have_attributes(
urgency: be == "low", # First occurrence takes precedence
)
end
end

with "#<<" do
let(:header) {subject.new}

it "can append values" do
header << "urgency=low"
expect(header).to have_attributes(
urgency: be == "low",
)
end

it "can append progressive flag" do
header << "progressive"
expect(header).to have_attributes(
progressive?: be == true,
)
end
end
end

0 comments on commit 5d91c76

Please sign in to comment.