Skip to content

Commit ae88427

Browse files
authored
Minor uri utils refactor (#4553)
* use class << self instead of private_class_method
1 parent b227eee commit ae88427

File tree

1 file changed

+86
-83
lines changed

1 file changed

+86
-83
lines changed

lib/utils/uri_utils.rb

Lines changed: 86 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -11,111 +11,114 @@ module UriUtils
1111
(#{DOCKER_TAG_REGEX.source}@#{DOCKER_DIGEST_REGEX.source}) | #{DOCKER_DIGEST_REGEX.source})\\Z", Regexp::EXTENDED)
1212

1313
class InvalidDockerURI < StandardError; end
14+
class << self
15+
def is_uri?(candidate)
16+
!!(candidate.is_a?(String) && /\A#{URI::DEFAULT_PARSER.make_regexp}\Z/ =~ candidate && URI(candidate))
17+
rescue StandardError
18+
false
19+
end
1420

15-
def self.is_uri?(candidate)
16-
!!(candidate.is_a?(String) && /\A#{URI::DEFAULT_PARSER.make_regexp}\Z/ =~ candidate && URI(candidate))
17-
rescue StandardError
18-
false
19-
end
21+
def is_buildpack_uri?(candidate)
22+
return false unless candidate.is_a?(String)
23+
return true if is_uri?(candidate)
2024

21-
def self.is_buildpack_uri?(candidate)
22-
return false unless candidate.is_a?(String)
23-
return true if is_uri?(candidate)
25+
!!(SSH_REGEX.match(candidate) || GIT_REGEX.match(candidate))
26+
end
2427

25-
!!(SSH_REGEX.match(candidate) || GIT_REGEX.match(candidate))
26-
end
28+
def is_cnb_buildpack_uri?(candidate)
29+
return false unless candidate.is_a?(String)
30+
return is_uri?(candidate) if candidate.start_with?(%r{\Ahttp(s)?://}x)
31+
return !!parse_docker_uri(candidate.split('://').last) if candidate.start_with?('docker://')
2732

28-
def self.is_cnb_buildpack_uri?(candidate)
29-
return false unless candidate.is_a?(String)
30-
return is_uri?(candidate) if candidate.start_with?(%r{\Ahttp(s)?://}x)
31-
return !!parse_docker_uri(candidate.split('://').last) if candidate.start_with?('docker://')
33+
false
34+
rescue StandardError
35+
false
36+
end
3237

33-
false
34-
rescue StandardError
35-
false
36-
end
38+
def is_uri_path?(candidate)
39+
!!(candidate.is_a?(String) && candidate =~ %r{^(?:/|/([^\s/]\S*)?)$})
40+
end
3741

38-
def self.is_uri_path?(candidate)
39-
!!(candidate.is_a?(String) && candidate =~ %r{^(?:/|/([^\s/]\S*)?)$})
40-
end
42+
# This escapes only the values in queries.
43+
def uri_escape(uri)
44+
parts = uri.split('?', 2)
45+
return uri if parts.size == 1
46+
47+
query = parts[1].split('&').map do |subquery|
48+
subparts = subquery.split('=', 2)
49+
if subparts.size == 1
50+
CGI.escape(subparts[0])
51+
else
52+
[subparts[0], CGI.escape(subparts[1])].join('=')
53+
end
54+
end.join('&')
55+
[parts[0].tr(' ', '+'), query].join('?')
56+
end
4157

42-
# This escapes only the values in queries.
43-
def self.uri_escape(uri)
44-
parts = uri.split('?', 2)
45-
return uri if parts.size == 1
46-
47-
query = parts[1].split('&').map do |subquery|
48-
subparts = subquery.split('=', 2)
49-
if subparts.size == 1
50-
CGI.escape(subparts[0])
51-
else
52-
[subparts[0], CGI.escape(subparts[1])].join('=')
53-
end
54-
end.join('&')
55-
[parts[0].tr(' ', '+'), query].join('?')
56-
end
58+
def parse_docker_uri(docker_uri)
59+
name_parts = docker_uri.split('/', 2)
5760

58-
def self.parse_docker_uri(docker_uri)
59-
name_parts = docker_uri.split('/', 2)
61+
host = name_parts[0]
62+
path = name_parts[1]
6063

61-
host = name_parts[0]
62-
path = name_parts[1]
64+
if missing_registry(name_parts)
65+
host = ''
66+
path = docker_uri
67+
end
6368

64-
if missing_registry(name_parts)
65-
host = ''
66-
path = docker_uri
67-
end
69+
path = 'library/' + path if (official_docker_registry(name_parts[0]) || missing_registry(name_parts)) && path.exclude?('/')
70+
path, tag_digest = parse_docker_tag_digest_from_path(path)
6871

69-
path = 'library/' + path if (official_docker_registry(name_parts[0]) || missing_registry(name_parts)) && path.exclude?('/')
70-
path, tag_digest = parse_docker_tag_digest_from_path(path)
72+
raise InvalidDockerURI.new "Invalid image name [#{path}]" unless DOCKER_PATH_REGEX =~ path
73+
raise InvalidDockerURI.new "Invalid image tag [#{tag_digest}]" if tag_digest && DOCKER_TAG_DIGEST_REGEX !~ tag_digest
7174

72-
raise InvalidDockerURI.new "Invalid image name [#{path}]" unless DOCKER_PATH_REGEX =~ path
73-
raise InvalidDockerURI.new "Invalid image tag [#{tag_digest}]" if tag_digest && DOCKER_TAG_DIGEST_REGEX !~ tag_digest
75+
# if only sha256 presented, we add hash value as fragment to the uri,
76+
# since the ruby uri parser confuses because of second ':' in uri's path part.
77+
if tag_digest && tag_digest.start_with?('sha256:')
78+
_, hash_value = tag_digest.split(':')
79+
path += '@sha256'
80+
tag_digest = hash_value
81+
end
7482

75-
# if only sha256 presented, we add hash value as fragment to the uri,
76-
# since the ruby uri parser confuses because of second ':' in uri's path part.
77-
if tag_digest && tag_digest.start_with?('sha256:')
78-
_, hash_value = tag_digest.split(':')
79-
path += '@sha256'
80-
tag_digest = hash_value
83+
[host, path, tag_digest]
8184
end
8285

83-
[host, path, tag_digest]
84-
end
86+
private
8587

86-
private_class_method def self.official_docker_registry(host)
87-
host == DOCKER_INDEX_SERVER
88-
end
88+
def official_docker_registry(host)
89+
host == DOCKER_INDEX_SERVER
90+
end
8991

90-
private_class_method def self.missing_registry(name_parts)
91-
host = name_parts[0]
92-
name_parts.length == 1 ||
93-
(host.exclude?('.') && host.exclude?(':') && host != 'localhost')
94-
end
92+
def missing_registry(name_parts)
93+
host = name_parts[0]
94+
name_parts.length == 1 ||
95+
(host.exclude?('.') && host.exclude?(':') && host != 'localhost')
96+
end
9597

96-
private_class_method def self.parse_docker_tag_digest_from_path(path)
97-
# Split path into base path and digest if digest is present (after '@')
98-
base_path, digest = path.split('@', 2)
98+
def parse_docker_tag_digest_from_path(path)
99+
# Split path into base path and digest if digest is present (after '@')
100+
base_path, digest = path.split('@', 2)
99101

100-
if digest
101-
# If digest is present and base_path contains a tag (':'), split it
102-
if base_path.include?(':')
103-
base_path, tag = base_path.split(':', 2)
104-
# Return path and combined tag@digest
105-
return [base_path, "#{tag}@#{digest}"]
106-
end
102+
if digest
103+
# If digest is present and base_path contains a tag (':'), split it
104+
if base_path.include?(':')
105+
base_path, tag = base_path.split(':', 2)
106+
# Return path and combined tag@digest
107+
return [base_path, "#{tag}@#{digest}"]
108+
end
107109

108-
# Return path and digest if no tag present
109-
return [base_path, digest]
110-
end
110+
# Return path and digest if no tag present
111+
return [base_path, digest]
112+
end
111113

112-
# No digest present, check for tag
113-
base_path, tag = base_path.split(':', 2)
114+
# No digest present, check for tag
115+
base_path, tag = base_path.split(':', 2)
114116

115-
# If tag is present but looks like a path segment (contains '/'), treat as no tag
116-
return [base_path, 'latest'] if tag&.include?('/')
117+
# If tag is present but looks like a path segment (contains '/'), treat as no tag
118+
return [base_path, 'latest'] if tag&.include?('/')
117119

118-
# Return path and tag (or nil if no tag)
119-
[base_path, tag]
120+
# Return path and tag (or nil if no tag)
121+
[base_path, tag]
122+
end
120123
end
121124
end

0 commit comments

Comments
 (0)