The approach that I had used, which was based on some of the other answers, recently break, so I want to describe more fully how we go about discovering the URLs and doing the actual validation.
NuGet.org provides a service index that provides the list of base URLs as indexed by type. This service index is available at https://api.nuget.org/v3/index.json.
It returns data in the following structure (truncated for brevity):
PS> Invoke-RESTmethod -uri 'https://api.nuget.org/v3/index.json'
version resources
------- ---------
3.0.0 {@{@id=https://azuresearch-usnc.nuget.org/query; ...
In other words, the service index provides a set of available API versions and a corresponding set of resources (i.e., endpoints/queryable APIs). Those resources correspond to URLs that have very specific capabilities and which should all be documented. at the time of this writing, we only have version 3.0.0 as an option, so let's examine those resources we can see what those endpoints look like, filtering the output to endpoints related to package registration and metadata:
PS> (Invoke-RESTmethod -uri 'https://api.nuget.org/v3/index.json' | `
? { $_.version -eq '3.0.0' }).resources | `
? { $_.'@type' -like '*Registration*' } | `
select-object -Property '@id','@type'
@id @type
--- -----
https://api.nuget.org/v3/registration4/ RegistrationsBaseUrl
https://api.nuget.org/v3/registration4/ RegistrationsBaseUrl/3.0.0-rc
https://api.nuget.org/v3/registration4/ RegistrationsBaseUrl/3.0.0-beta
https://api.nuget.org/v3/registration4-gz/ RegistrationsBaseUrl/3.4.0
https://api.nuget.org/v3/registration4-gz-semver2/ RegistrationsBaseUrl/3.6.0
https://api.nuget.org/v3/registration4-gz-semver2/ RegistrationsBaseUrl/Versioned
One useful property that I left off the output is that a comment property exists that provides a useful description of the endpoint. For example, for RegistrationsBaseUrl we have the following comment:
Base URL of Azure storage where NuGet package registration info is stored
From the above, we can see that our base URL will be one of the URLs above on the left. Checking the docs for @type RegistrationsBaseUrl:
These registrations are not compressed (meaning they use an implied Content-Encoding: identity). SemVer 2.0.0 packages are excluded from this hive.
For my needs, I want to include SemVer 2.0.0, so I want to use a different endpoint. Again checking the docs:
These registrations are compressed using Content-Encoding: gzip. SemVer 2.0.0 packages are included in this hive.
So, per the earlier query results I want the following url:
https://api.nuget.org/v3/registration4-gz-semver2/
In reading through the documentation we learn that we're interested in the Registration Page for the package that we're trying to query. The URL syntax will be:
$BASEURL/<PackageName>/<PackageVersion>.json
Using Newtonsoft.Json as a sample package and expanding:
https://api.nuget.org/v3/registration4-gz-semver2/newtonsoft.json/12.0.3.json
Now that we know how we get the URL, and the fact that it can change over time and should be dynamically retrieved, let's write some PowerShell that will determine whether a NuGet package has been published to a given source:
param (
[Parameter(Mandatory=$true)]
[string]$Id,
[Parameter(Mandatory=$true)]
[string]$Version,
[Parameter(Mandatory=$false)]
[string]$source = "https://api.nuget.org/v3/index.json"
)
$resources = (invoke-restmethod -uri $source | ? { $_.version -eq '3.0.0' }).resources
$baseUrl = ($resources | ? { $_.'@type' -eq 'RegistrationsBaseUrl/3.6.0' }).'@id'
try
{
$packageName = $Id.ToLowerInvariant()
$packageVersion = $Version.ToLower()
# Use supported HEAD method for performance
Invoke-RestMethod -uri "$($baseUrl)$($packageName)/$($packageVersion).json" -Method HEAD > $null 2>&1
# method didn't throw so the NuGet package exists
$true
}
catch
{
# method threw, so the NuGet package doesn't exist
$false
}
Its use would look like the following:
PS> Get-NuGetPackageExists.ps1 -Id Newtonsoft.Json -Version 10.0.2
True
nuget list -source <mynugetserver> -Prerelease -AllVersionslist. Can you share what is your current solution? May be you can post it as an answer... 10x