NuGet Package Source Discovery (PSD) allows for NuGet-based clients tools to discover the feeds that are hosted by a user or organization by using the blog or website URL.
NuGet Package Source Discovery is an attempt to remove friction from the following scenarios:
- An individual user may have several NuGet feeds spread across the Internet. Some may be on NuGet.org (including curated feeds), some on MyGet and maybe some on my corporate network. How do I easily point my Visual Studio to all my feeds accross different machines? And how do I maintain this configuration?
- An organization may have several feeds internally as well as one on MyGet and some CI packages on TeamCity. How can this organization tell his developers what feeds they can/should use?
- An organization may have a NuGet server containing multiple feeds. How will developers in this organization get a list of available feeds and services?
For all scenarios, a simple feed discovery mechanism could facilitate this. Such feed discovery mechanism could be any URL out there (even multiple per host).
As an example, we've implemented the above. Open Visual Studio and open any solution. Then issue the following in the Package Manager Console:
Install-Package DiscoverPackageSources
Discover-PackageSources -Url "http://www.myget.org/gallery"
Close and re-open Visual Studio and check your package sources. The URL has been verified for a PSD manifest URL and the manifest has been parsed. Matching feeds have been installed into the NuGet.config file, in this case all feeds listed in the MyGet gallery.
A PSD request is an HTTP GET to a URL with optional authentication and an optional NuGet-ApiKey HTTP Header. There are no filtering or searching options at this time.
The response will be an XML document following the Really Simple Discovery (RSD) RFC as described on https://github.com/danielberlinger/rsd. Since not all required metadata can be obtained from the RSD format, the Dublin Core schema is present in the PSD response as well.
Vendors and open source projects are allowed to add their own schema to the PSD discovery document however the manifest described below should be respected at all times.
An example manifest could be:
<?xml version="1.0" encoding="utf-8"?>
<rsd version="1.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<service>
<engineName>MyGet</engineName>
<engineLink>http://www.myget.org</engineLink>
<dc:identifier>http://www.myget.org/F/googleanalyticstracker</dc:identifier>
<dc:creator>maartenba</dc:creator>
<dc:owner>maartenba</dc:owner>
<dc:title>Staging feed for GoogleAnalyticsTracker</dc:title>
<dc:description>Staging feed for GoogleAnalyticsTracker</dc:description>
<homePageLink>http://www.myget.org/gallery/googleanalyticstracker</homePageLink>
<apis>
<api name="nuget-v2-packages" preferred="true" apiLink="http://www.myget.org/F/googleanalyticstracker/api/v2" blogID="" />
<api name="nuget-v2-push" preferred="true" apiLink="http://www.myget.org/F/googleanalyticstracker/api/v2/package" blogID="">
<settings>
<setting name="apiKey">abcdefghijkl</setting>
</settings>
</api>
<api name="nuget-v1-packages" preferred="false" apiLink="http://www.myget.org/F/googleanalyticstracker/api/v1" blogID="" />
</apis>
</service>
</rsd>
The following table describes the elements in the data format:
Element | Description |
---|---|
engineName | Optional: the software on which the feed is running |
engineLink | Optional: the URL to the website of the software on which the feed is running |
dc:identifier | Required - a globally unique URN/URL identifying he feed |
dc:owner | Optional: the owner of the feed |
dc:creator | Optional: the creator of the feed |
dc:title | Required - feed name |
dc:description | Optional: feed description |
homePageLink | Optional: link to an HTML representation of the feed |
apis | Required - a list of endpoints for the feed |
name |
Required - the feed protocol used Proposed values:
|
preferred | Required - is this the preferred endpoint to communicate with the feed? |
apiLink | Required - the GET URL |
blogID | Required - for compatibility with RSD spec, not used: leave BLANK |
The <api />
element can contain zero, one or more <setting name="key">value</setting>
elements specifying settings such as requireAuthentication
, apiKey
and vendor-specific settings.
Feed uniqueness must be global. urn:<guid>
or the feed URL can be valid identifiers.
All feeds should contain an Id.
All feeds that the requesting user has read access to should be returned. If the user is anonymous, feeds that require authentication should be omitted.
If the user is logged in, either controlled by basic authentication or using the NuGet-ApiKey
HttpHeader, the server should return every feed the user has access to as well as feed specific settings such as API keys and so on. The PSD client can use these specifics to preconfigure the NuGet.config file on the user's machine.
The client should respect the following flow of discovering feeds:
-
If no PSD is given, the client should assume
http://nuget.<currentdomain>
as the PSD server. -
The PSD URL is accessed and downloaded. It can contain:
-
HTML containing a tag such as
<link rel="nuget" type="application/rsd+xml" title="GoogleAnalyticsTracker feed on MyGet" href="http://myget.org/discovery/feed/googleanalyticstracker"/>
This URL should be followed and the PSD manifest parsed. Note that multiple tags may exist and should all be parsed.
-
HTML containing a tag such as
<link rel="nuget" type="application/atom+xml" title="WebMatrix Package Source" href="http://nuget.org/api/v2/curated-feeds/WebMatrix/Packages"/>
This URL should be treated as a NuGet feed and added as-is, using the title attribute as the feed's title in NuGet package source list. No further metadata can be discovered for this feed. Note that multiple tags may exist.
-
-
If the URL directly points to a NuGet Package Source Discovery Manifest, we can immediately parse it.
The client should support entry of a complete PSD URL <protocol>://<host name>:<port>/<path>
but require only that the host name be entered. When less than a full URL is entered, the client should verify if the host returns a PSD manifest or contains a <link rel="nuget"/>
tag.
URLs specified in <link rel="nuget"/>
tags can be absolute or relative.
Depending on security, consuming an PSD manifest using the NuGet-ApiKey
header or using basic authentication may yield additional endpoints and API settings. For example, MyGet produces the following manifest on an anonymous call to https://www.myget.org/Discovery/Feed/googleanalyticstracker:
<rsd version="1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://archipelago.phrasewise.com/rsd">
<service>
<engineName>MyGet</engineName>
<engineLink>http://www.myget.org/</engineLink>
<dc:identifier>http://www.myget.org/F/googleanalyticstracker/</dc:identifier>
<dc:owner>maartenba</dc:owner>
<dc:creator>maartenba</dc:creator>
<dc:title>Staging feed for GoogleAnalyticsTracker</dc:title>
<dc:description>Staging feed for GoogleAnalyticsTracker</dc:description>
<homePageLink>http://www.myget.org/Feed/Details/googleanalyticstracker/</homePageLink>
<apis>
<api name="nuget-v2-packages" blogID="" preferred="true" apiLink="http://www.myget.org/F/googleanalyticstracker/" />
<api name="nuget-v1-packages" blogID="" preferred="false" apiLink="http://www.myget.org/F/googleanalyticstracker/api/v1/" />
</apis>
</service>
</rsd>
The authenticated version of https://www.myget.org/Discovery/Feed/googleanalyticstracker yields:
<rsd version="1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://archipelago.phrasewise.com/rsd">
<service>
<engineName>MyGet</engineName>
<engineLink>http://www.myget.org/</engineLink>
<dc:identifier>http://www.myget.org/F/googleanalyticstracker/</dc:identifier>
<dc:owner>maartenba</dc:owner>
<dc:creator>maartenba</dc:creator>
<dc:title>Staging feed for GoogleAnalyticsTracker</dc:title>
<dc:description>Staging feed for GoogleAnalyticsTracker</dc:description>
<homePageLink>http://www.myget.org/Feed/Details/googleanalyticstracker/</homePageLink>
<apis>
<api name="nuget-v2-packages" blogID="" preferred="true" apiLink="http://www.myget.org/F/googleanalyticstracker/" />
<api name="nuget-v1-packages" blogID="" preferred="false" apiLink="http://www.myget.org/F/googleanalyticstracker/api/v1/" />
<api name="nuget-v2-push" blogID="" preferred="true" apiLink="http://www.myget.org/F/googleanalyticstracker/">
<settings>
<setting name="apiKey">530c14a6-6ce5-47d0-8f14-9daab627aa38</setting>
</settings>
</api>
<api name="symbols-v1-push" blogID="" preferred="true" apiLink="http://nuget.gw.symbolsource.org/MyGet/googleanalyticstracker">
<settings>
<setting name="apiKey">abcdefghijklmnop</setting>
</settings>
</api>
</apis>
</service>
</rsd>
Example Client / Consumer implementations can be found in the PackageSourceDiscovery repository.
Note that these sample implementations support:
- Querying HTML containing
<link rel="nuget"/>
- Querying RSD manifests
- Querying NuGet feeds
- Querying NuGet Feed Discovery (NFD) manifests
Also check our Wiki for details on clients implementing this spec already.
This repository, including the PSD spec and clients, are licensed under the Apache v2.0 license.
Another package source discovery specification exists, NuGet Feed Discovery (NFD). NFD differs from PSD in that both specs have a different intent.
- NFD is a convention-based API endpoint for listing feeds on a server
- PSD is a means of discovering feeds from any URL given
If you want more information, read up on NuGet Feed Discovery (NFD).