Skip to content

Commit 21d02ec

Browse files
fix: align path encoding with RFC 3986 section 3.3
1 parent 6ed82a7 commit 21d02ec

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

lib/orb/internal/util.rb

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ def dig(data, pick, &blk)
237237
end
238238
end
239239

240+
# @type [Regexp]
241+
#
242+
# https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3
243+
RFC_3986_NOT_PCHARS = /[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/
244+
240245
class << self
241246
# @api private
242247
#
@@ -247,6 +252,15 @@ def uri_origin(uri)
247252
"#{uri.scheme}://#{uri.host}#{":#{uri.port}" unless uri.port == uri.default_port}"
248253
end
249254

255+
# @api private
256+
#
257+
# @param path [String, Integer]
258+
#
259+
# @return [String]
260+
def encode_path(path)
261+
path.to_s.gsub(Orb::Internal::Util::RFC_3986_NOT_PCHARS) { ERB::Util.url_encode(_1) }
262+
end
263+
250264
# @api private
251265
#
252266
# @param path [String, Array<String>]
@@ -259,7 +273,7 @@ def interpolate_path(path)
259273
in []
260274
""
261275
in [String => p, *interpolations]
262-
encoded = interpolations.map { ERB::Util.url_encode(_1) }
276+
encoded = interpolations.map { encode_path(_1) }
263277
format(p, *encoded)
264278
end
265279
end
@@ -576,10 +590,10 @@ def encode_query_params(query)
576590

577591
case val
578592
in Orb::FilePart unless val.filename.nil?
579-
filename = ERB::Util.url_encode(val.filename)
593+
filename = encode_path(val.filename)
580594
y << "; filename=\"#{filename}\""
581595
in Pathname | IO
582-
filename = ERB::Util.url_encode(::File.basename(val.to_path))
596+
filename = encode_path(::File.basename(val.to_path))
583597
y << "; filename=\"#{filename}\""
584598
else
585599
end

rbi/orb/internal/util.rbi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,20 @@ module Orb
144144
end
145145
end
146146

147+
# https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3
148+
RFC_3986_NOT_PCHARS = T.let(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/, Regexp)
149+
147150
class << self
148151
# @api private
149152
sig { params(uri: URI::Generic).returns(String) }
150153
def uri_origin(uri)
151154
end
152155

156+
# @api private
157+
sig { params(path: T.any(String, Integer)).returns(String) }
158+
def encode_path(path)
159+
end
160+
153161
# @api private
154162
sig { params(path: T.any(String, T::Array[String])).returns(String) }
155163
def interpolate_path(path)

sig/orb/internal/util.rbs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,12 @@ module Orb
4545
-> top?
4646
} -> top?
4747

48+
RFC_3986_NOT_PCHARS: Regexp
49+
4850
def self?.uri_origin: (URI::Generic uri) -> String
4951

52+
def self?.encode_path: (String | Integer path) -> String
53+
5054
def self?.interpolate_path: (String | ::Array[String] path) -> String
5155

5256
def self?.decode_query: (String? query) -> ::Hash[String, ::Array[String]]

0 commit comments

Comments
 (0)