在某些情況下,您可能想要實作自己的 NuGet 套件來源。 有許多 現有的實作 可讓您以各種方式裝載自己的摘要,但官方 NuGet 用戶端軟體和套件摘要之間的通訊協定記載可讓您從頭開始建置自己的摘要實作。
通訊協定會隨著時間而演進,本指南是針對想要或已經實作 NuGet 套件伺服器的人。
自 2015 年 NuGet V3 協定的初始版本推出以來,NuGet 已發展為能提供開發人員更豐富的體驗,這要求套件存放庫需執行額外工作,以向使用者提供更多價值,而不只是從託管的套件中提取元數據,並以多種形式傳遞這些元數據。 例如,搜尋和套件元數據端點包含的不僅僅是 nupkg 的 nuspec 檔案中找到的元數據。
請注意,本指南著重於 NuGet V3 通訊協定,因為 V2 通訊協定基本上未記載,而且自 2015 年以來,NuGet 用戶端和伺服器通訊的建議通訊協定是 V3 通訊協定。 如需詳細資訊,請參閱通訊協定版本控制。
Chronology
為了協助現有 NuGet 存放庫的作者掌握 NuGet 的最新功能,以下是文件其餘部分所提及相關功能的時序。
| Year | Feature |
|---|---|
| 2013 |
“如何在 nuget.org 上管理套件擁有者” 的部落格文章,釐清網站上顯示的擁有者是那些有權限上傳新版本的帳戶,因此網站會忽略套件中的元數據owners。 |
| 2017 |
已新增 verified 至 SearchQueryService 回應。 |
| 語意版本設定 2.0.0 支援 | |
| 2018 | 內嵌授權 |
| 2019 | 內嵌圖示 |
套件棄用於 RegistrationBaseUrl (套件元資料資源) |
|
| 2020 |
RegistrationsBaseUrl 中的套件弱點資訊(套件元數據資源) |
已新增 packageTypes 查詢參數至 SearchQueryService 要求 |
|
| 2021 | 嵌入式說明檔 |
| 2023 |
預先驗證已驗證的要求 VulnerabilityInfo 資源 |
| 2025 | 啟用嵌入式自述文件下載 |
擁有者欄位
請考慮兩個 套件描述檔 (.nuspec) 欄位,分別是 <authors> 及 <owners>。
封裝第三方內容的套件作者通常會將第三方名稱放在 <authors> 欄位中。
欄位 <owners> 的目的是表示誰在存放庫上發佈套件,因此在封裝問題或問題時應該連絡誰。
這在 2013 年的部落格文章中說明,因此 <owners> 檔案中的 .nuspec 欄位被視為不建議使用。
如果套件的指令清單包含此元數據,則應該忽略它。
請勿在.nuspec或<owners>的 JSON 回應中,從owners檔案的欄位返回屬性的值。
如果您的存放庫具有針對每個套件的權限,建議您在owner的元數據中報告有權發佈新版本的帳戶,以便搜尋和封裝元數據資源的 JSON 回應。
verified 搜尋回應欄位
當新的欄位設定為 verified時,Visual Studio 的套件管理員 UI 會顯示true結果中套件旁的藍色複選標記。
NuGet.org 使用此功能與套件前置詞數據(伺服器端數據,不是 NuGet API 的一部分)搭配,讓該複選標記僅在套件上傳者的帳戶擁有相應的套件時顯示給客戶。
例如,只有在 nuget.org microsoft.*擁有套件時,才會驗證任何具有前置詞的套件。在實作保留前置詞之前,上傳套件標識符開頭microsoft.為的套件的任何人員,都不會有此已驗證的複選標記。
NuGet.org 也允許前綴詞可以不是獨有的,因此任何人都可以上傳使用Contoso.ToolWithPlugins.Community.*作為前綴的套件,但不會取得已驗證標記。
語意版本設定 2.0.0 支援
NuGet 支援 與 Semantic Version 之間的 System.Version 混合式,但在 2017 年已新增語意版本 2.0.0 的支援。
因此,將版本傳回至低於 3.6.0 之用戶端版本的 NuGet API 資源不得傳回使用 Semantic 2.0.0 功能與 Semantic Versioning 1.0.0 不相容的套件。
這兩個版本之間最重要的差異是發行前標籤和元資料字串。
語意版本設定 1.0.0 規格會[0-9A-Za-z-]針對發行前版本標籤中只允許的字元,提供作為範例正則表達式字串,而且不支援元數據字串。
語意版本設定 2.0.0 規格可讓發行前版本標識碼以.字元分隔(並禁止數值標識元具有前置零),並允許在 之後+新增建置元數據。
在 套件元數據資源(RegistrationsBaseUrl)中,低於 3.6.0 的資源版本只能傳回符合 .NET 的語意版本設定 1.0.0 的套件。
這表示只有符合語意版本 2.0.0 的套件版本對這些用戶端版本來說是不可見的。
同樣地, 搜尋查詢服務 (SearchQueryService) 和 自動完成服務 (SearchAutocompleteService) 也新增 &semVerLevel={version} 了查詢參數。
當semVerLevel缺失時,假設其值為1.0.0。
如同套件元數據資源一樣,當 semVerLevel 的值低於 2.0.0 時,版本僅與 Semantic Versioning 2.0.0 相容的套件不得被傳回。
內嵌檔案
套件 圖示、 授權和 自述檔 可以內嵌在套件中(且建議使用)。
這些檔案需要一個 URL 端點,這可以是擷取後放置在靜態檔案伺服器上的 URL,或者是根據要求從 .nupkg 動態擷取檔案的 URL,如此一來就能夠在不下載整個 nupkg 的情況下檢視這些檔案。
如果您的套件存放庫提供套件瀏覽和檢視套件詳細數據,您可以使用 URL 來顯示客戶網站上的內嵌內容。
最後,套件元數據資源和搜尋資源必須包含 JSON 回應的iconUrl、 licenseUrl和/或 readmeUrl 屬性中的託管 URL。
套件(.nupkg 檔案)不得修改,因為用戶端功能(鎖定檔案和已簽署的套件)會在套件遭到竄改時偵測修改。
請注意,授權可以是SPDX運算式或內嵌檔案(但不能同時包含兩者)。
在搜尋和套件元數據結果中表示時,使用授權表達式的套件可以將licenseUrl設置為URL編碼的授權表達式,並附加至https://licenses.nuget.org/的結尾。
例如: https://licenses.nuget.org/Apache-2.0 。
NuGet.org 伺服器團隊在 licenses.nuget.org 上有其他文件。
已知的弱點和淘汰數據
套件元資料資源 (RegistrationsBaseUrl)
套件元數據資源可以包含棄用和漏洞資訊。 這可讓客戶在 Visual Studio 的套件管理員使用者介面或其他 IDE 中瀏覽套件,以收到重要安全性或維護問題的通知。
如果您的套件存放庫從另一個存放庫引用套件,為了在您自己的摘要中複製套件,我們建議您定期檢查原始來源是否有棄用或漏洞資訊,並將這些元數據複製到您自己的存放庫中。
如果您的套件存放庫是特別從 nuget.org 來源,只要保留上次檢查的狀態(「數據指標」),您就可以使用Catalog資源有效率地檢查您是否有任何套件更新,而不需要從上游摘要下載大量的套件元數據 JSON 檔案。
有 一個指南,附有範例代碼,說明如何使用目錄資源,幫助您開始上手。
已知的弱點資料庫 (VulnerabilityInfo)
為了在套件還原期間提供高效能弱點掃描,NuGet 會從VulnerabilityInfo資源下載已知弱點的完整清單。
Nuget.org 提供 GitHub Advisories 資料庫中所有 GitHub 檢閱諮詢的弱點數據,其中包含未裝載於 nuget.org 上的套件。
如果您的套件存放庫載有第一方套件,並且您想要透過私有 feed 將弱點資訊提供給客戶,但尚未揭露任何套件弱點,您應該提供弱點索引,包含一或多個弱點頁面,其內容為空的 JSON 陣列([])。
重複使用 nuget.org 的弱點數據
NuGet 不需要 服務索引中的資源或 弱點索引必須位於與服務索引本身相同的伺服器上。 不過,有些公司選擇通過防火牆封鎖 nuget.org,或於非連線的網路上設有內部部署的來源的原因有幾個。 若要避免連線問題,建議您從您自己的 Web 應用程式提供弱點數據,讓 NuGet 用戶端只對已安裝摘要的主機進行 HTTP 連線。
✔️ 請快取或代理您自己的 Web 應用程式中的易受攻擊的頁面
❌ 請勿在服務索引或弱點索引中公告 api.nuget.org,而不需要設定即可關閉此功能。
packageTypes 搜尋查詢
.NET CLI 允許使用 dotnet tool search 命令搜尋 .NET 工具套件。
這是藉由將查詢參數新增 &packageTypes={value} 至 搜尋查詢資源來實作,該資源會從封裝的 .nuspec 檔案 <packageTypes> 欄位讀取值。
已驗證訂閱源的 URL 結構
如 NuGet API 概觀中所述,所有 NuGet 伺服器通訊的起始 URL 是 服務索引。
本檔包含 NuGet 用戶端將查詢之所有其他資源的 URL。
從 NuGet 6.7 起(Visual Studio 和 MSBuild 17.7 和 .NET SDK 7.0.400),NuGet 會使用 。NET 的 HttpClientHandler.PreAuthenticate,只有在後續 URL 位於先前已驗證之 URL 的相同虛擬目錄或子目錄中時,才會避免匿名 HTTP 要求。
這可大幅減少傳送至伺服器的未驗證 HTTP 要求數目,因此會減少您的伺服器工作負載。
以下是一些範例:
| URL | 會預先驗證嗎? |
|---|---|
| https://pkgs.contoso.com/nuget/v3/feed/index.json | N/A,這是服務索引。 |
| https://pkgs.contoso.com/nuget/v3/search | 否,不在與服務索引相同的或子目錄中。 |
| https://search.pkgs.contoso.com/nuget/v3/feed/ | 否,不在與服務索引相同的主機名上。 |
| https://pkgs.contoso.com/nuget/v3/feed/search | 是,在與服務索引相同的目錄中。 |
| https://pkgs.contoso.com/nuget/v3/registration/ | 否,不在服務索引的子目錄中。 |
| https://pkgs.contoso.com/nuget/v3/feed/registration/ | 是,在服務索引的子目錄中。 |
| https://pkgs.contoso.com/nuget/v3/{guid}/registration/ | 請參閱下方 |
在最後一個範例中,伺服器可能有一個規範名稱(在此範例中為 GUID),並且擁有一個或多個別名。
如果服務索引請求是在非標準 URL(在我們的範例 feed中為「易記」名稱)上進行驗證,則否,任何在標準 URL 下的資源請求都不會遵循 HttpClientHandler 的 PreAuthenticate 規則。
不過,如果非標準 URL 是標準 URL 的 HTTP 重新導向, https://pkgs.contoso.com/nuget/v3/{guid}/index.json則此 URL 將會用於 HttpClientHandler認證快取中。
在此情況下,由於重新導向,服務索引的每個要求都會有額外的延遲。
雖然 NuGet 的 V3 API 設計成在靜態檔伺服器上運作,但搜尋資源是一律需要動態 Web 服務來處理要求的例外狀況。
如果您希望在不同的伺服器上托管搜尋,或者任何其他 NuGet API 資源,以受益於 HttpClientHandler 的 PreAuthenticate,您需要使用反向代理來確保服務索引中的所有面向客戶的 URL 都遵循「相同或子目錄」規則。
啟用內嵌 README 檔案下載
已記載 新資源 來建構 URL,可用來下載指定套件的自述檔。 這可讓與 VS 中的套件管理 UI 一樣,讓客戶端顯示使用者先前尚未安裝的套件內嵌自述檔。 用戶端會建構此 URL 並嘗試下載自述檔,並使用要求的回應來判斷自述檔是否可用。 這表示伺服器應該預期在用戶流覽 PM UI 時,對建構端點提出多個要求。