Class: WSDL::Parser::Resolver Private

Inherits:
Object
  • Object
show all
Defined in:
lib/wsdl/parser/resolver.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Resolves WSDL and schema locations to their XML content.

This class handles two types of locations:

  • HTTP/HTTPS URLs: Fetches the content via HTTP GET
  • File paths: Reads the content from the local filesystem (with sandbox restrictions)

It also supports resolving relative paths against a base location, which is essential for handling WSDL imports and XSD includes that use relative schemaLocation attributes.

== Security

The resolver implements sandbox restrictions to prevent path traversal attacks. When a WSDL contains malicious schemaLocation attributes like ../../../../etc/passwd, the resolver blocks access to files outside the allowed directory tree.

File access is controlled by the sandbox_paths option:

  • When sandbox_paths is provided: file access is allowed within those directories
  • When sandbox_paths is nil: file access is disabled (URL-only mode)

Examples:

Resolving a URL (no file access needed)

resolver = Resolver.new(http_adapter)
xml = resolver.resolve('http://example.com/service?wsdl')

Resolving a local file with sandboxing

resolver = Resolver.new(http_adapter, sandbox_paths: ['/app/wsdl'])
xml = resolver.resolve('/app/wsdl/service.wsdl')

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(http, sandbox_paths: nil, limits: nil) ⇒ Resolver

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a new Resolver instance.

Parameters:

  • http (Object)

    an HTTP adapter instance that responds to get(url)

  • sandbox_paths (Array<String>, nil) (defaults to: nil)

    directories where file access is allowed. When nil, file access is disabled and all imports must use URLs.

  • limits (Limits, nil) (defaults to: nil)

    resource limits for DoS protection. If nil, uses WSDL.limits.



45
46
47
48
49
50
# File 'lib/wsdl/parser/resolver.rb', line 45

def initialize(http, sandbox_paths: nil, limits: nil)
  @http = http
  @sandbox_paths = normalize_sandbox_paths(sandbox_paths)
  @limits = limits || WSDL.limits
  @total_bytes_downloaded = 0
end

Instance Attribute Details

#limitsLimits (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the resource limits.

Returns:

  • (Limits)

    the limits instance



62
63
64
# File 'lib/wsdl/parser/resolver.rb', line 62

def limits
  @limits
end

#sandbox_pathsArray<String>? (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the sandbox paths (normalized to absolute paths).

Returns:

  • (Array<String>, nil)

    the allowed directories for file access



56
57
58
# File 'lib/wsdl/parser/resolver.rb', line 56

def sandbox_paths
  @sandbox_paths
end

#total_bytes_downloadedInteger (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the total bytes downloaded so far.

Returns:

  • (Integer)

    cumulative bytes downloaded



68
69
70
# File 'lib/wsdl/parser/resolver.rb', line 68

def total_bytes_downloaded
  @total_bytes_downloaded
end

Instance Method Details

#file_access_allowed?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks if file access is allowed in the current configuration.

Returns:

  • (Boolean)

    true if file access is allowed



131
132
133
# File 'lib/wsdl/parser/resolver.rb', line 131

def file_access_allowed?
  !@sandbox_paths.nil?
end

#relative_location?(location) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks if a location is relative (not absolute URL, not absolute path).

Parameters:

  • location (String)

    the location to check

Returns:

  • (Boolean)

    true if the location is relative



123
124
125
# File 'lib/wsdl/parser/resolver.rb', line 123

def relative_location?(location)
  Source.new(location).relative_file_path?
end

#resolve(location, base: nil) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolves a location to its XML content.

When a base location is provided and the location is relative, the location is resolved against the base before fetching.

Parameters:

  • location (String)

    a URL or file path

  • base (String, nil) (defaults to: nil)

    optional base location for resolving relative paths

Returns:

  • (String)

    the XML content

Raises:

  • (Errno::ENOENT)

    if the file path does not exist

  • (PathRestrictionError)

    if the file is outside the sandbox



81
82
83
84
# File 'lib/wsdl/parser/resolver.rb', line 81

def resolve(location, base: nil)
  absolute_location = resolve_location(location, base)
  fetch(absolute_location)
end

#resolve_location(location, base = nil) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolves a potentially relative location against a base location.

If the location is already absolute (URL or absolute file path), it is returned as-is. If it's relative and a base is provided, it's resolved against that base.

Parameters:

  • location (String)

    the location to resolve

  • base (String, nil) (defaults to: nil)

    the base location

Returns:

  • (String)

    the resolved absolute location



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/wsdl/parser/resolver.rb', line 96

def resolve_location(location, base = nil)
  location_source = Source.new(location)
  validate_location_source!(location_source)

  # Already absolute URL
  return location if location_source.url?

  # Already absolute file path
  return location if location_source.absolute_file_path?

  # At this point, location is a relative file path
  # If no base is provided, resolve against current working directory
  # (this handles the initial WSDL being a relative path like "path/to/service.wsdl")
  return File.expand_path(location) if base.nil?

  # Ensure base can anchor relative resolution.
  validate_base_for_relative!(location, base)

  # Resolve relative location against base
  resolve_relative(location, base)
end