# frozen_string_literal: true
module Spandx
module Dotnet
# https://api.nuget.org/v3-flatcontainer/#{name}/#{version}/#{name}.nuspec
# https://api.nuget.org/v3-flatcontainer/#{package.name}/index.json
# https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource
class NugetGateway < ::Spandx::Core::Gateway
def initialize(http: Spandx.http)
@http = http
end
def licenses_for(dependency)
extract_licenses_from(nuspec_for(dependency.name, dependency.version))
end
def matches?(dependency)
dependency.package_manager == :nuget
end
def each(start_page: 0)
each_page(start_page: start_page) do |page_json|
items_from(page_json).each do |item|
yield(fetch_json(item['@id']), page_number_from(page_json['@id']))
end
end
end
private
attr_reader :http
def each_page(start_page:)
url = 'https://api.nuget.org/v3/catalog0/index.json'
items_from(fetch_json(url))
.find_all { |page| page_number_from(page['@id']) >= start_page }
.each { |page| yield fetch_json(page['@id']) }
end
def nuspec_url_for(name, version)
"https://api.nuget.org/v3-flatcontainer/#{name}/#{version}/#{name}.nuspec"
end
def nuspec_for(name, version)
fetch_xml(nuspec_url_for(name, version))
end
def from_xml(xml)
Nokogiri::XML(xml).tap(&:remove_namespaces!)
end
# TODO: Fix parsing https://github.com/NuGet/Home/wiki/Packaging-License-within-the-nupkg#license
def extract_licenses_from(document)
licenses = document.search('//package/metadata/license')
if licenses.any?
licenses.map(&:text)
else
document
.search('//package/metadata/licenseUrl')
.map { |node| download_license(node.text) }
.compact
end
end
def download_license(url)
response = http.get(url)
http.ok?(response) ? response.body : url
end
def fetch_json(url)
response = http.get(url)
http.ok?(response) ? Oj.load(response.body) : {}
end
def fetch_xml(url)
response = http.get(url)
http.ok?(response) ? from_xml(response.body) : from_xml('')
end
def items_from(page)
page.fetch('items', []).sort_by { |x| x['commitTimeStamp'] }
end
def page_number_from(url)
url.match(/page(?\d+)\.json/)[:page_number].to_i
end
end
end
end