Skip to content

Commit e6bd679

Browse files
committed
Move URL and Reference to Protocol::URL gem.
1 parent e796678 commit e6bd679

File tree

17 files changed

+179
-789
lines changed

17 files changed

+179
-789
lines changed

lib/protocol/http/cookie.rb

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,37 @@
44
# Copyright, 2019-2025, by Samuel Williams.
55
# Copyright, 2022, by Herrick Fang.
66

7-
require_relative "url"
7+
require_relative "quoted_string"
88

99
module Protocol
1010
module HTTP
1111
# Represents an individual cookie key-value pair.
1212
class Cookie
13+
# Valid cookie name characters according to RFC 6265.
14+
# cookie-name = token (RFC 2616 defines token)
15+
VALID_COOKIE_KEY = /\A#{TOKEN}\z/.freeze
16+
17+
# Valid cookie value characters according to RFC 6265.
18+
# cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
19+
# cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
20+
# Excludes control chars, whitespace, DQUOTE, comma, semicolon, and backslash
21+
VALID_COOKIE_VALUE = /\A[\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]*\z/.freeze
22+
1323
# Initialize the cookie with the given name, value, and directives.
1424
#
15-
# @parameter name [String] The name of the cookiel, e.g. "session_id".
25+
# @parameter name [String] The name of the cookie, e.g. "session_id".
1626
# @parameter value [String] The value of the cookie, e.g. "1234".
1727
# @parameter directives [Hash] The directives of the cookie, e.g. `{"path" => "/"}`.
18-
def initialize(name, value, directives)
28+
# @raises [ArgumentError] If the name or value contains invalid characters.
29+
def initialize(name, value, directives = nil)
30+
unless VALID_COOKIE_KEY.match?(name)
31+
raise ArgumentError, "Invalid cookie name: #{name.inspect}"
32+
end
33+
34+
if value && !VALID_COOKIE_VALUE.match?(value)
35+
raise ArgumentError, "Invalid cookie value: #{value.inspect}"
36+
end
37+
1938
@name = name
2039
@value = value
2140
@directives = directives
@@ -30,41 +49,37 @@ def initialize(name, value, directives)
3049
# @attribute [Hash] The directives of the cookie.
3150
attr :directives
3251

33-
# Encode the name of the cookie.
34-
def encoded_name
35-
URL.escape(@name)
36-
end
37-
38-
# Encode the value of the cookie.
39-
def encoded_value
40-
URL.escape(@value)
52+
# Encode a string for use in a cookie, escaping characters that are not allowed.
53+
#
54+
# @parameter string [String] The string to encode.
55+
# @returns [String] The encoded string.
56+
def self.encode(string)
57+
string.b.gsub(/([^!#$%&'*+\-\.\/0-9A-Z\^_`a-z|~]+)/) do |match|
58+
"%" + match.unpack("H2" * match.bytesize).join("%").upcase
59+
end
4160
end
4261

4362
# Convert the cookie to a string.
4463
#
4564
# @returns [String] The string representation of the cookie.
46-
def to_s
47-
buffer = String.new.b
48-
49-
buffer << encoded_name << "=" << encoded_value
50-
51-
if @directives
52-
@directives.collect do |key, value|
53-
buffer << ";"
54-
55-
case value
56-
when String
57-
buffer << key << "=" << value
58-
when TrueClass
59-
buffer << key
60-
end
65+
def to_s
66+
buffer = String.new
67+
68+
buffer << @name << "=" << @value
69+
70+
if @directives
71+
@directives.each do |key, value|
72+
buffer << ";"
73+
buffer << key
74+
75+
if value != true
76+
buffer << "=" << value.to_s
6177
end
6278
end
63-
64-
return buffer
6579
end
6680

67-
# Parse a string into a cookie.
81+
return buffer
82+
end # Parse a string into a cookie.
6883
#
6984
# @parameter string [String] The string to parse.
7085
# @returns [Cookie] The parsed cookie.
@@ -74,11 +89,7 @@ def self.parse(string)
7489
key, value = head.split("=", 2)
7590
directives = self.parse_directives(directives)
7691

77-
self.new(
78-
URL.unescape(key),
79-
URL.unescape(value),
80-
directives,
81-
)
92+
self.new(key, value, directives)
8293
end
8394

8495
# Parse a list of strings into a hash of directives.

lib/protocol/http/header/accept.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Copyright, 2025, by William T. Nelson.
66

77
require_relative "split"
8-
require_relative "quoted_string"
8+
require_relative "../quoted_string"
99
require_relative "../error"
1010

1111
module Protocol

lib/protocol/http/header/accept_charset.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright, 2025, by Samuel Williams.
55

66
require_relative "split"
7-
require_relative "quoted_string"
7+
require_relative "../quoted_string"
88
require_relative "../error"
99

1010
module Protocol

lib/protocol/http/header/accept_encoding.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright, 2025, by Samuel Williams.
55

66
require_relative "split"
7-
require_relative "quoted_string"
7+
require_relative "../quoted_string"
88
require_relative "../error"
99

1010
module Protocol

lib/protocol/http/header/accept_language.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright, 2025, by Samuel Williams.
55

66
require_relative "split"
7-
require_relative "quoted_string"
7+
require_relative "../quoted_string"
88
require_relative "../error"
99

1010
module Protocol

lib/protocol/http/header/digest.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright, 2025, by Samuel Williams.
55

66
require_relative "split"
7-
require_relative "quoted_string"
7+
require_relative "../quoted_string"
88
require_relative "../error"
99

1010
module Protocol

lib/protocol/http/header/server_timing.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright, 2025, by Samuel Williams.
55

66
require_relative "split"
7-
require_relative "quoted_string"
7+
require_relative "../quoted_string"
88
require_relative "../error"
99

1010
module Protocol

lib/protocol/http/header/te.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright, 2025, by Samuel Williams.
55

66
require_relative "split"
7-
require_relative "quoted_string"
7+
require_relative "../quoted_string"
88
require_relative "../error"
99

1010
module Protocol

lib/protocol/http/header/quoted_string.rb renamed to lib/protocol/http/quoted_string.rb

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,16 @@
55

66
module Protocol
77
module HTTP
8-
module Header
9-
# According to https://tools.ietf.org/html/rfc7231#appendix-C
10-
TOKEN = /[!#$%&'*+\-.^_`|~0-9A-Z]+/i
11-
12-
QUOTED_STRING = /"(?:.(?!(?<!\\)"))*.?"/
13-
14-
# https://tools.ietf.org/html/rfc7231#section-5.3.1
15-
QVALUE = /0(\.[0-9]{0,3})?|1(\.[0]{0,3})?/
16-
17-
# Handling of HTTP quoted strings.
18-
module QuotedString
8+
# According to https://tools.ietf.org/html/rfc7231#appendix-C
9+
TOKEN = /[!#$%&'*+\-.^_`|~0-9A-Z]+/i
10+
11+
QUOTED_STRING = /"(?:.(?!(?<!\\)"))*.?"/
12+
13+
# https://tools.ietf.org/html/rfc7231#section-5.3.1
14+
QVALUE = /0(\.[0-9]{0,3})?|1(\.[0]{0,3})?/
15+
16+
# Handling of HTTP quoted strings.
17+
module QuotedString
1918
# Unquote a "quoted-string" value according to <https://tools.ietf.org/html/rfc7230#section-3.2.6>. It should already match the QUOTED_STRING pattern above by the parser.
2019
def self.unquote(value, normalize_whitespace = true)
2120
value = value[1...-1]
@@ -41,9 +40,8 @@ def self.quote(value, force = false)
4140
"\"#{value.gsub(/["\\]/, '\\\\\0')}\""
4241
else
4342
value
44-
end
4543
end
4644
end
4745
end
4846
end
49-
end
47+
end

0 commit comments

Comments
 (0)