Protocol::URLSourceProtocolURLAbsolute

class Absolute

Represents an absolute URL with scheme and/or authority. Examples: "https://example.com/path", "//cdn.example.com/lib.js", "http://localhost/"

Definitions

def initialize(scheme, authority, path = "/", query = nil, fragment = nil)

Initialize a new absolute URL.

Signature

parameter scheme String

The URL scheme (e.g., "https", "http").

parameter authority String

The authority component (e.g., "example.com", "user@host:port").

parameter path String

The path component (defaults to "/").

parameter query String, nil

The query string.

parameter fragment String, nil

The fragment identifier.

Implementation

def initialize(scheme, authority, path = "/", query = nil, fragment = nil)
	@scheme = scheme
	@authority = authority
	
	# Initialize the parent Relative class with the path component
	super(path, query, fragment)
end

attr :scheme

Signature

attribute String

The URL scheme.

attr :authority

Signature

attribute String

The authority component.

def scheme?

Check if the URL has a non-empty scheme.

Signature

returns Boolean

True if a scheme is present and non-empty.

Implementation

def scheme?
	@scheme and !@scheme.empty?
end

def authority?

Check if the URL has a non-empty authority.

Signature

returns Boolean

True if an authority is present and non-empty.

Implementation

def authority?
	@authority and !@authority.empty?
end

def +(other)

Combine this absolute URL with a relative reference according to RFC 3986 Section 5.

Example: Resolve a relative path.

base = Absolute.new("https", "example.com", "/documents/reports/")
relative = Relative.new("summary.pdf")
result = base + relative
result.to_s  # => "https://example.com/documents/reports/summary.pdf"

Example: Navigate to parent directory.

base = Absolute.new("https", "example.com", "/documents/reports/2024/")
relative = Relative.new("../../archive/")
result = base + relative
result.to_s  # => "https://example.com/documents/archive/"

Signature

parameter other String, Relative, Reference, Absolute

The reference to resolve.

returns Absolute, String

The resolved absolute URL.

Implementation

def +(other)
	case other
	when Absolute
		# If other is already absolute with a scheme, return it as-is:
		return other if other.scheme
		# Protocol-relative URL: inherit scheme from base:
		return Absolute.new(@scheme, other.authority, other.path, other.query, other.fragment)
	when Relative
		# Already a Relative, use directly.
	when String
		other = URL[other]
		# If parsing resulted in an Absolute URL, handle it:
		if other.is_a?(Absolute)
			return other if other.scheme
			# Protocol-relative URL: inherit scheme from base:
			return Absolute.new(@scheme, other.authority, other.path, other.query, other.fragment)
		end
	else
		raise ArgumentError, "Cannot combine Absolute URL with #{other.class}"
	end
	
	# RFC 3986 Section 5.3: Component Recomposition
	# At this point, other is a Relative URL
	
	# Check for special cases first:
	if other.path.empty?
		# Empty path - could be query-only or fragment-only reference:
		if other.query
			# Query replacement: use base path with new query:
			Absolute.new(@scheme, @authority, @path, other.query, other.fragment)
		else
			# Fragment-only: keep everything from base, just change fragment:
			Absolute.new(@scheme, @authority, @path, @query, other.fragment || @fragment)
		end
	else
		# Relative path: merge with base path:
		path = Path.expand(@path, other.path)
		Absolute.new(@scheme, @authority, path, other.query, other.fragment)
	end
end

def append(buffer = String.new)

Append the absolute URL to the given buffer.

Implementation

def append(buffer = String.new)
	buffer << @scheme << ":" if @scheme
	buffer << "//" << @authority if @authority
	super(buffer)
end

def with(scheme: @scheme, authority: @authority, path: nil, query: @query, fragment: @fragment, pop: true)

Create a new Absolute URL with modified components.

Example: Change the scheme.

url = Absolute.new("http", "example.com", "/page")
secure = url.with(scheme: "https")
secure.to_s  # => "https://example.com/page"

Example: Update the query string.

url = Absolute.new("https", "example.com", "/search", "query=ruby")
updated = url.with(query: "query=python")
updated.to_s  # => "https://example.com/search?query=python"

Signature

parameter scheme String, nil

The scheme to use (nil to remove scheme).

parameter authority String, nil

The authority to use (nil to remove authority).

parameter path String, nil

The path to merge with the current path.

parameter query String, nil

The query string to use.

parameter fragment String, nil

The fragment to use.

parameter pop Boolean

Whether to pop the last path component before merging.

returns Absolute

A new Absolute URL with the modified components.

Implementation

def with(scheme: @scheme, authority: @authority, path: nil, query: @query, fragment: @fragment, pop: true)
	self.class.new(scheme, authority, Path.expand(@path, path, pop), query, fragment)
end

def to_ary

Convert the URL to an array representation.

Signature

returns Array

An array of [scheme, authority, path, query, fragment].

Implementation

def to_ary
	[@scheme, @authority, @path, @query, @fragment]
end

def <=>(other)

Compare this URL with another for sorting purposes.

Signature

parameter other Absolute

The URL to compare with.

returns Integer

-1, 0, or 1 based on component-wise comparison.

Implementation

def <=>(other)
	to_ary <=> other.to_ary
end

def to_s

Convert the URL to its string representation.

Signature

returns String

The formatted absolute URL string.

Implementation

def to_s
	append
end