protocol-url 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/protocol/url/absolute.rb +26 -2
- data/lib/protocol/url/encoding.rb +11 -0
- data/lib/protocol/url/reference.rb +31 -10
- data/lib/protocol/url/relative.rb +71 -0
- data/lib/protocol/url/version.rb +1 -1
- data/readme.md +20 -4
- data/releases.md +16 -0
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fb5e51237375afb74dda311e130ad550240453d53c42c5c0c05ddc532231261f
|
|
4
|
+
data.tar.gz: fbcf705936fedf9e967af1eb66ef2d901f68448bfe9e47d3ffd21156486207f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c49c2bc6639b2b0777ae93c3b8ee34bd7c496831deb32da8af725ebc4f873d2666a47b68bc6aa031d7b1dbee522488927011c1d5ceb9b81140e4ea3c4ae2e575
|
|
7
|
+
data.tar.gz: 05c41426fdc297a5bae0a59d6ef4ca31e88a0cc592769038474c28b948b7615b5cecae17943d6263fe8bd02b079f178d427b2cdc7c4ea1393a5e28da8ccaa55f
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -10,6 +10,13 @@ module Protocol
|
|
|
10
10
|
# Represents an absolute URL with scheme and/or authority.
|
|
11
11
|
# Examples: "https://example.com/path", "//cdn.example.com/lib.js", "http://localhost/"
|
|
12
12
|
class Absolute < Relative
|
|
13
|
+
# Initialize a new absolute URL.
|
|
14
|
+
#
|
|
15
|
+
# @parameter scheme [String] The URL scheme (e.g., "https", "http").
|
|
16
|
+
# @parameter authority [String] The authority component (e.g., "example.com", "user@host:port").
|
|
17
|
+
# @parameter path [String] The path component (defaults to "/").
|
|
18
|
+
# @parameter query [String, nil] The query string.
|
|
19
|
+
# @parameter fragment [String, nil] The fragment identifier.
|
|
13
20
|
def initialize(scheme, authority, path = "/", query = nil, fragment = nil)
|
|
14
21
|
@scheme = scheme
|
|
15
22
|
@authority = authority
|
|
@@ -18,13 +25,22 @@ module Protocol
|
|
|
18
25
|
super(path, query, fragment)
|
|
19
26
|
end
|
|
20
27
|
|
|
28
|
+
# @attribute [String] The URL scheme.
|
|
21
29
|
attr :scheme
|
|
30
|
+
|
|
31
|
+
# @attribute [String] The authority component.
|
|
22
32
|
attr :authority
|
|
23
33
|
|
|
34
|
+
# Check if the URL has a non-empty scheme.
|
|
35
|
+
#
|
|
36
|
+
# @returns [Boolean] True if a scheme is present and non-empty.
|
|
24
37
|
def scheme?
|
|
25
38
|
@scheme and !@scheme.empty?
|
|
26
39
|
end
|
|
27
40
|
|
|
41
|
+
# Check if the URL has a non-empty authority.
|
|
42
|
+
#
|
|
43
|
+
# @returns [Boolean] True if an authority is present and non-empty.
|
|
28
44
|
def authority?
|
|
29
45
|
@authority and !@authority.empty?
|
|
30
46
|
end
|
|
@@ -93,8 +109,6 @@ module Protocol
|
|
|
93
109
|
super(buffer)
|
|
94
110
|
end
|
|
95
111
|
|
|
96
|
-
UNSPECIFIED = Object.new
|
|
97
|
-
|
|
98
112
|
# Create a new Absolute URL with modified components.
|
|
99
113
|
#
|
|
100
114
|
# @parameter scheme [String, nil] The scheme to use (nil to remove scheme).
|
|
@@ -118,14 +132,24 @@ module Protocol
|
|
|
118
132
|
self.class.new(scheme, authority, Path.expand(@path, path, pop), query, fragment)
|
|
119
133
|
end
|
|
120
134
|
|
|
135
|
+
# Convert the URL to an array representation.
|
|
136
|
+
#
|
|
137
|
+
# @returns [Array] An array of `[scheme, authority, path, query, fragment]`.
|
|
121
138
|
def to_ary
|
|
122
139
|
[@scheme, @authority, @path, @query, @fragment]
|
|
123
140
|
end
|
|
124
141
|
|
|
142
|
+
# Compare this URL with another for sorting purposes.
|
|
143
|
+
#
|
|
144
|
+
# @parameter other [Absolute] The URL to compare with.
|
|
145
|
+
# @returns [Integer] -1, 0, or 1 based on component-wise comparison.
|
|
125
146
|
def <=>(other)
|
|
126
147
|
to_ary <=> other.to_ary
|
|
127
148
|
end
|
|
128
149
|
|
|
150
|
+
# Convert the URL to its string representation.
|
|
151
|
+
#
|
|
152
|
+
# @returns [String] The formatted absolute URL string.
|
|
129
153
|
def to_s
|
|
130
154
|
append
|
|
131
155
|
end
|
|
@@ -233,6 +233,17 @@ module Protocol
|
|
|
233
233
|
|
|
234
234
|
return parameters
|
|
235
235
|
end
|
|
236
|
+
|
|
237
|
+
# Decode an `application/x-www-form-urlencoded` string into a hash.
|
|
238
|
+
# In addition to percent encoding, this format represents spaces using `+`.
|
|
239
|
+
#
|
|
240
|
+
# @parameter string [String] The form-encoded string to decode.
|
|
241
|
+
# @parameter maximum [Integer] The maximum number of keys in a path.
|
|
242
|
+
# @parameter symbolize_keys [Boolean] Whether to symbolize keys.
|
|
243
|
+
# @returns [Hash] The decoded form values.
|
|
244
|
+
def self.decode_www_form(string, maximum = 8, symbolize_keys: false)
|
|
245
|
+
return self.decode(string.gsub("+", "%20"), maximum, symbolize_keys: symbolize_keys)
|
|
246
|
+
end
|
|
236
247
|
end
|
|
237
248
|
end
|
|
238
249
|
end
|
|
@@ -17,6 +17,35 @@ module Protocol
|
|
|
17
17
|
class Reference < Relative
|
|
18
18
|
include Comparable
|
|
19
19
|
|
|
20
|
+
# Coerce a value into a {Reference} instance.
|
|
21
|
+
#
|
|
22
|
+
# This method provides flexible conversion from various types into a {Reference}.
|
|
23
|
+
# When given a {String}, it parses the URL-encoded path, query, and fragment components
|
|
24
|
+
# and unescapes them for internal storage. When given a {Relative}, it converts the
|
|
25
|
+
# encoded values to unescaped form suitable for {Reference} instances.
|
|
26
|
+
#
|
|
27
|
+
# @parameter value [String | Relative | Nil] The value to coerce.
|
|
28
|
+
# @parameter parameters [Hash | Nil] Optional user-supplied parameters to append to the query string.
|
|
29
|
+
#
|
|
30
|
+
# @returns [Reference | Nil] A new reference instance, or `nil` if the input is `nil`.
|
|
31
|
+
#
|
|
32
|
+
# @raises [ArgumentError] If the string contains whitespace or control characters.
|
|
33
|
+
# @raises [ArgumentError] If the value cannot be coerced to a {Reference}.
|
|
34
|
+
#
|
|
35
|
+
# @example Coerce a string with path, query, and fragment.
|
|
36
|
+
# reference = Reference["/search?q=ruby#results"]
|
|
37
|
+
# reference.path # => "/search"
|
|
38
|
+
# reference.query # => "q=ruby"
|
|
39
|
+
# reference.fragment # => "results"
|
|
40
|
+
#
|
|
41
|
+
# @example Coerce with additional parameters.
|
|
42
|
+
# reference = Reference["/search", {"limit" => "10"}]
|
|
43
|
+
# reference.to_s # => "/search?limit=10"
|
|
44
|
+
#
|
|
45
|
+
# @example Coerce a Relative instance.
|
|
46
|
+
# relative = Relative.new("/path%20with%20spaces", nil, "top")
|
|
47
|
+
# reference = Reference[relative]
|
|
48
|
+
# reference.path # => "/path with spaces"
|
|
20
49
|
def self.[](value, parameters = nil)
|
|
21
50
|
case value
|
|
22
51
|
when String
|
|
@@ -25,7 +54,7 @@ module Protocol
|
|
|
25
54
|
query = match[:query]
|
|
26
55
|
fragment = match[:fragment]
|
|
27
56
|
|
|
28
|
-
# Unescape path and fragment for user-friendly internal storage
|
|
57
|
+
# Unescape path and fragment for user-friendly internal storage:
|
|
29
58
|
# Query strings are kept as-is since they contain = and & syntax
|
|
30
59
|
path = Encoding.unescape(path) if path && !path.empty?
|
|
31
60
|
fragment = Encoding.unescape(fragment) if fragment
|
|
@@ -35,7 +64,7 @@ module Protocol
|
|
|
35
64
|
raise ArgumentError, "Invalid URL (contains whitespace or control characters): #{value.inspect}"
|
|
36
65
|
end
|
|
37
66
|
when Relative
|
|
38
|
-
# Relative stores encoded values, so we need to unescape them for Reference
|
|
67
|
+
# Relative stores encoded values, so we need to unescape them for Reference:
|
|
39
68
|
path = value.path
|
|
40
69
|
fragment = value.fragment
|
|
41
70
|
|
|
@@ -95,14 +124,6 @@ module Protocol
|
|
|
95
124
|
[@path, @query, @fragment, @parameters]
|
|
96
125
|
end
|
|
97
126
|
|
|
98
|
-
# Compare two references.
|
|
99
|
-
#
|
|
100
|
-
# @parameter other [Reference] The other reference to compare.
|
|
101
|
-
# @returns [Integer] -1, 0, 1 if the reference is less than, equal to, or greater than the other reference.
|
|
102
|
-
def <=> other
|
|
103
|
-
to_ary <=> other.to_ary
|
|
104
|
-
end
|
|
105
|
-
|
|
106
127
|
# @returns [Boolean] Whether the reference has parameters.
|
|
107
128
|
def parameters?
|
|
108
129
|
@parameters and !@parameters.empty?
|
|
@@ -12,16 +12,29 @@ module Protocol
|
|
|
12
12
|
class Relative
|
|
13
13
|
include Comparable
|
|
14
14
|
|
|
15
|
+
# Initialize a new relative URL.
|
|
16
|
+
#
|
|
17
|
+
# @parameter path [String] The path component.
|
|
18
|
+
# @parameter query [String, nil] The query string.
|
|
19
|
+
# @parameter fragment [String, nil] The fragment identifier.
|
|
15
20
|
def initialize(path, query = nil, fragment = nil)
|
|
16
21
|
@path = path.to_s
|
|
17
22
|
@query = query
|
|
18
23
|
@fragment = fragment
|
|
19
24
|
end
|
|
20
25
|
|
|
26
|
+
# @attribute [String] The path component of the URL.
|
|
21
27
|
attr :path
|
|
28
|
+
|
|
29
|
+
# @attribute [String, nil] The query string component.
|
|
22
30
|
attr :query
|
|
31
|
+
|
|
32
|
+
# @attribute [String, nil] The fragment identifier.
|
|
23
33
|
attr :fragment
|
|
24
34
|
|
|
35
|
+
# Convert the URL path to a local filesystem path.
|
|
36
|
+
#
|
|
37
|
+
# @returns [String] The local filesystem path.
|
|
25
38
|
def to_local_path
|
|
26
39
|
Path.to_local_path(@path)
|
|
27
40
|
end
|
|
@@ -131,18 +144,76 @@ module Protocol
|
|
|
131
144
|
return buffer
|
|
132
145
|
end
|
|
133
146
|
|
|
147
|
+
# Convert the URL to an array representation.
|
|
148
|
+
#
|
|
149
|
+
# @returns [Array] An array of `[path, query, fragment]`.
|
|
134
150
|
def to_ary
|
|
135
151
|
[@path, @query, @fragment]
|
|
136
152
|
end
|
|
137
153
|
|
|
154
|
+
# Compute a hash value for the URL based on its components.
|
|
155
|
+
#
|
|
156
|
+
# @returns [Integer] The hash value.
|
|
157
|
+
def hash
|
|
158
|
+
to_ary.hash
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Check if this URL is equal to another URL by comparing components.
|
|
162
|
+
#
|
|
163
|
+
# @parameter other [Relative] The URL to compare with.
|
|
164
|
+
# @returns [Boolean] True if the URLs have identical components.
|
|
165
|
+
def equal?(other)
|
|
166
|
+
to_ary == other.to_ary
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Compare this URL with another for sorting purposes.
|
|
170
|
+
#
|
|
171
|
+
# @parameter other [Relative] The URL to compare with.
|
|
172
|
+
# @returns [Integer] -1, 0, or 1 based on component-wise comparison.
|
|
138
173
|
def <=>(other)
|
|
139
174
|
to_ary <=> other.to_ary
|
|
140
175
|
end
|
|
141
176
|
|
|
177
|
+
# Check structural equality by comparing components.
|
|
178
|
+
#
|
|
179
|
+
# @parameter other [Relative] The URL to compare with.
|
|
180
|
+
# @returns [Boolean] True if the URLs have identical components.
|
|
181
|
+
def ==(other)
|
|
182
|
+
to_ary == other.to_ary
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Check string equality, useful for case statements.
|
|
186
|
+
#
|
|
187
|
+
# @parameter other [String, Relative] The value to compare with.
|
|
188
|
+
# @returns [Boolean] True if the string representations match.
|
|
189
|
+
def ===(other)
|
|
190
|
+
to_s === other
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Convert the URL to its string representation.
|
|
194
|
+
#
|
|
195
|
+
# @returns [String] The formatted URL string.
|
|
142
196
|
def to_s
|
|
143
197
|
append
|
|
144
198
|
end
|
|
145
199
|
|
|
200
|
+
# Convert the URL to a JSON-compatible representation.
|
|
201
|
+
#
|
|
202
|
+
# @returns [String] The URL as a string.
|
|
203
|
+
def as_json(...)
|
|
204
|
+
to_s
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Convert the URL to JSON.
|
|
208
|
+
#
|
|
209
|
+
# @returns [String] The JSON-encoded URL.
|
|
210
|
+
def to_json(...)
|
|
211
|
+
as_json.to_json(...)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Generate a human-readable representation for debugging.
|
|
215
|
+
#
|
|
216
|
+
# @returns [String] A string like `#<Protocol::URL::Relative /path?query#fragment>`.
|
|
146
217
|
def inspect
|
|
147
218
|
"#<#{self.class} #{to_s}>"
|
|
148
219
|
end
|
data/lib/protocol/url/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -6,11 +6,11 @@ Provides abstractions for working with URLs.
|
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
|
-
Please see the [project documentation](https://github.
|
|
9
|
+
Please see the [project documentation](https://socketry.github.io/protocol-url/) for more details.
|
|
10
10
|
|
|
11
|
-
- [Getting Started](https://github.
|
|
11
|
+
- [Getting Started](https://socketry.github.io/protocol-url/guides/getting-started/index) - This guide explains how to get started with `protocol-url` for parsing, manipulating, and constructing URLs in Ruby.
|
|
12
12
|
|
|
13
|
-
- [Working with References](https://github.
|
|
13
|
+
- [Working with References](https://socketry.github.io/protocol-url/guides/working-with-references/index) - This guide explains how to use <code class="language-ruby">Protocol::URL::Reference</code> for managing URLs with query parameters and fragments.
|
|
14
14
|
|
|
15
15
|
## Contributing
|
|
16
16
|
|
|
@@ -32,7 +32,23 @@ This project is best served by a collaborative and respectful environment. Treat
|
|
|
32
32
|
|
|
33
33
|
## Releases
|
|
34
34
|
|
|
35
|
-
Please see the [project releases](https://github.
|
|
35
|
+
Please see the [project releases](https://socketry.github.io/protocol-url/releases/index) for all releases.
|
|
36
|
+
|
|
37
|
+
### v0.5.0
|
|
38
|
+
|
|
39
|
+
- Add `Protocol::URL::Encoding.decode_www_form` for decoding HTML form data where `+` represents a space.
|
|
40
|
+
|
|
41
|
+
### v0.4.0
|
|
42
|
+
|
|
43
|
+
- Add comparison methods to `Protocol::URL::Relative` (and by inheritance to `Protocol::URL::Absolute`):
|
|
44
|
+
- `#==` for structural equality comparison (compares path, query, fragment components).
|
|
45
|
+
- `#===` for string equality comparison (enables case statement matching).
|
|
46
|
+
- `#<=>` for ordering and sorting.
|
|
47
|
+
- `#hash` for hash key support.
|
|
48
|
+
- `#equal?` for component-based equality checking.
|
|
49
|
+
- Add JSON serialization support to `Protocol::URL::Relative`:
|
|
50
|
+
- `#as_json` returns the string representation.
|
|
51
|
+
- `#to_json` returns a JSON-encoded string.
|
|
36
52
|
|
|
37
53
|
### v0.3.0
|
|
38
54
|
|
data/releases.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.5.0
|
|
4
|
+
|
|
5
|
+
- Add `Protocol::URL::Encoding.decode_www_form` for decoding HTML form data where `+` represents a space.
|
|
6
|
+
|
|
7
|
+
## v0.4.0
|
|
8
|
+
|
|
9
|
+
- Add comparison methods to `Protocol::URL::Relative` (and by inheritance to `Protocol::URL::Absolute`):
|
|
10
|
+
- `#==` for structural equality comparison (compares path, query, fragment components).
|
|
11
|
+
- `#===` for string equality comparison (enables case statement matching).
|
|
12
|
+
- `#<=>` for ordering and sorting.
|
|
13
|
+
- `#hash` for hash key support.
|
|
14
|
+
- `#equal?` for component-based equality checking.
|
|
15
|
+
- Add JSON serialization support to `Protocol::URL::Relative`:
|
|
16
|
+
- `#as_json` returns the string representation.
|
|
17
|
+
- `#to_json` returns a JSON-encoded string.
|
|
18
|
+
|
|
3
19
|
## v0.3.0
|
|
4
20
|
|
|
5
21
|
- Add `relative(target, from)` for computing relative paths between URLs.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: protocol-url
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -58,6 +58,7 @@ licenses:
|
|
|
58
58
|
- MIT
|
|
59
59
|
metadata:
|
|
60
60
|
source_code_uri: https://github.com/socketry/protocol-url.git
|
|
61
|
+
documentation_uri: https://socketry.github.io/protocol-url/
|
|
61
62
|
rdoc_options: []
|
|
62
63
|
require_paths:
|
|
63
64
|
- lib
|
|
@@ -72,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
72
73
|
- !ruby/object:Gem::Version
|
|
73
74
|
version: '0'
|
|
74
75
|
requirements: []
|
|
75
|
-
rubygems_version:
|
|
76
|
+
rubygems_version: 4.0.10
|
|
76
77
|
specification_version: 4
|
|
77
78
|
summary: Provides abstractions for working with URLs.
|
|
78
79
|
test_files: []
|
metadata.gz.sig
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
s��Ѽ�2=�p���
|
|
2
|
+
�_|�xy-ꡨ]A=�q��L������,h��H�*��m�DR�oM��A���C�u���1���ϻ���T���r���IA���eK��5`}���E͎5����j�;�,����\��2����0��m��*�v#��r�=s�Z�@K^�N�Lw�`��TOS"�K ����k|wN(� 0��r�g�FmM���3�T$8��_�z�}6
|
|
3
|
+
HH���bX!��r�����U�v����dDN���EP�ۛ�<�Z�wx8��{��`��J?6��֩��S0ڲ����,1g�Sľ���P������ Fq{13�X�?c�.p. ��,�N�3!��
|