Ever wondered how package managers work?
NuGet is the package manager for the .NET ecosystem that has served billions of downloads worldwide. Let's take a look under the hood and see what happens when you install a package on Visual Studio.
Table of contents
Package Source
If you open Visual Studio's options, you'll see the following under the Package Sources
section:
Visual Studio uses this package source to discover and download packages. The default source is nuget.org, which has the following package source URL: https://api.nuget.org/v3/index.json
.
If you open that URL in your browser, you'll see:
{
"version": "3.0.0",
"resources": [
{
"@id": "https://azuresearch-usnc.nuget.org/query",
"@type": "SearchQueryService",
"comment": "Query endpoint of NuGet Search service (primary)"
},
...
],
...
}
This is the service index, which lists all the resources that the server supports. Each resource has the following properties:
-
@type
- Used to identify the resource -
@id
- The resource's URL
For example, the search resource used to discover packages has the type SearchQueryService
and can be found at the URL https://azuresearch-usnc.nuget.org/query
.
⚠ Don't hard-code
azuresearch-usnc.nuget.org
in your app! NuGet servers can move their resources at any time - you should always discover resource URLs using the service index.
Discover packages
You can use Visual Studio's Package Manager UI to find packages:
This is powered by the source's search resource. If you search for json
, this will trigger the following request: https://azuresearch-usnc.nuget.org/query?includePrerelease=true&semVerLevel=2.0.0&q=json
.
If you open that URL in your browser, you'll see:
{
...
"totalHits": 3818,
"data": [
{
...
"id": "Newtonsoft.Json",
"version": "12.0.3",
"description": "Json.NET is a popular high-performance JSON",
"totalDownloads": 506643420,
...
},
...
]
}
This is the metadata for the latest version of each package relevant to json
.
Inspect package details
Now that you've discovered some packages, you can select one to view more details:
This is powered by the package metadata resource. For example, you can find the package metadata for the package Newtonsoft.Json
at this URL: https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json
If you open that URL in your browser, you'll see:
{
...
"items": [
{
"items": [
{
...
"catalogEntry": {
"id": "Newtonsoft.Json",
"version": "3.5.8",
"description": "Json.NET is a popular high-performance JSON framework for .NET",
"packageContent": "https://api.nuget.org/v3-flatcontainer/newtonsoft.json/3.5.8/newtonsoft.json.3.5.8.nupkg",
...
},
"packageContent": "https://api.nuget.org/v3-flatcontainer/newtonsoft.json/3.5.8/newtonsoft.json.3.5.8.nupkg",
},
...
]
}
],
...
}
This resource contains the metadata for all versions of Newtonsoft.Json
.
Install packages
If you press the Install
button for the package Microsoft.Extension.Logging
, this will kick off the following chain reaction:
- Download the package
- Inspect the package's dependencies
- For each dependency, find the best version of that dependency to install and repeat steps 1-3
All of this is powered by the package content resource.
Download the package
NuGet will download the package using this URL: http://api.nuget.org/v3-flatcontainer/microsoft.extensions.logging/3.1.4/microsoft.extensions.logging.3.1.4.nupkg
For each dependency, find the best version to install
A package can depend on other packages, and these dependencies can themselves have their own dependencies. As a result, NuGet needs to build a graph of all the dependencies using its dependency resolution algorithm. To do this, NuGet needs to know the list of versions for each dependency.
For example, the package Microsoft.Extensions.Logging
depends on Microsoft.Extensions.Logging.Abstractions
, so NuGet will lookup versions here: https://api.nuget.org/v3-flatcontainer/microsoft.extensions.logging.abstractions/index.json
.
If you open that in your browser, you'll see:
{
"versions": [
"1.0.0-rc1-final",
"1.0.0-rc2-final",
...
"3.1.4"
]
}
These are all the versions of the Microsoft.Extensions.Logging.Abstractions
package. NuGet will choose one of these to install.
⚠ The NuGet client could use the package metadata resource from the previous section to find packages' versions. However, performance is critical here! This endpoint returns just the right information to install the right package.
Conclusion
Congratulations, you've learned how the NuGet protocol works! If you want even more information, I recommend the following resources:
- NuGet's protocol documentation - This is the definitive guide on the NuGet API
- NuGet's client SDK - Use this to write an app that interacts with NuGet servers
If you want to run your own NuGet server, check out my side project on GitHub! 😇
loic-sharma / BaGet
A lightweight NuGet and symbol server
In future posts, I'll deep dive into nuget.org's implementation of the NuGet protocol, so stay tuned! Feel free to comment if you have any feedback or questions!
Top comments (0)