Class: Fetchers::Url

Inherits:
Object
  • Object
show all
Defined in:
lib/fetchers/url.rb

Direct Known Subclasses

Compliance::Fetcher, Supermarket::Fetcher

Constant Summary collapse

MIME_TYPES =
{
  'application/x-zip-compressed' => '.zip',
  'application/zip' => '.zip',
  'application/x-gzip' => '.tar.gz',
  'application/gzip' => '.tar.gz',
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, opts) ⇒ Url

Returns a new instance of Url.



95
96
97
98
# File 'lib/fetchers/url.rb', line 95

def initialize(url, opts)
  @target = url
  @archive = self.class.download_archive(url, opts)
end

Instance Attribute Details

#archiveObject (readonly)

Returns the value of attribute archive.



93
94
95
# File 'lib/fetchers/url.rb', line 93

def archive
  @archive
end

#filesObject (readonly)

Returns the value of attribute files.



14
15
16
# File 'lib/fetchers/url.rb', line 14

def files
  @files
end

Class Method Details

.download_archive(url, opts) ⇒ Object

download url into archive using opts, returns File object and content-type from HTTP headers



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/fetchers/url.rb', line 68

def self.download_archive(url, opts)
  remote = open(
    url,
    http_basic_authentication: [opts['user'] || '', opts['password'] || ''],
  )

  content_type = remote.meta['content-type']
  file_type = MIME_TYPES[content_type] ||
              throw(RuntimeError, 'Failed to resolve URL target, its '\
              "metadata did not match ZIP or TAR: #{content_type}")

  # fall back to tar
  if file_type.nil?
    fail "Could not determine file type for content type #{content_type}."
  end

  # download content
  archive = Tempfile.new(['inspec-dl-', file_type])
  archive.binmode
  archive.write(remote.read)
  archive.rewind
  archive.close
  archive
end

.resolve(target, opts = {}) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/fetchers/url.rb', line 16

def self.resolve(target, opts = {})
  uri = URI.parse(target)
  return nil if uri.nil? or uri.scheme.nil?
  return nil unless %{ http https }.include? uri.scheme
  target = transform(target)
  # fetch this url and hand it off
  res = new(target, opts)
  resolve_next(res.archive.path, res)
rescue URI::Error => _e
  nil
end

.transform(target) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/fetchers/url.rb', line 46

def self.transform(target)
  # support for default github url
  m = %r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w-]+)(\.git)?(/)?$}.match(target)
  return "https://github.com/#{m[:user]}/#{m[:repo]}/archive/master.tar.gz" if m

  # support for branch and commit urls
  m = %r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w-]+)/tree/(?<commit>[\w\.]+)(/)?$}.match(target)
  return "https://github.com/#{m[:user]}/#{m[:repo]}/archive/#{m[:commit]}.tar.gz" if m

  # if we could not find a match, return the original value
  target
end