From 168202290847d63adc515f18577fc5129d72394f Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Thu, 14 Mar 2019 16:38:10 -0700 Subject: [PATCH 1/2] Use new ServerCommon to sign packages in a shared way (#77) --- build.ps1 | 7 +++---- build/sign.proj | 24 ------------------------ 2 files changed, 3 insertions(+), 28 deletions(-) delete mode 100644 build/sign.proj diff --git a/build.ps1 b/build.ps1 index 32d1a880..1bdc698e 100644 --- a/build.ps1 +++ b/build.ps1 @@ -9,7 +9,7 @@ param ( [string]$SemanticVersion = '1.0.0-zlocal', [string]$Branch, [string]$CommitSHA, - [string]$BuildBranch = 'ed30a6392ef7c342ca46b20f7b9c964ab9ad5881' + [string]$BuildBranch = '2d8feecabe3aeaed7f5b4d50b9be78c94faf39ec' ) $msBuildVersion = 15; @@ -91,9 +91,8 @@ Invoke-BuildStep 'Creating artifacts' { } ` -ev +BuildErrors -Invoke-BuildStep 'Signing the packages' { - $ProjectPath = Join-Path $PSScriptRoot "build\sign.proj" - Build-Solution $Configuration $BuildNumber -MSBuildVersion "$msBuildVersion" $ProjectPath ` +Invoke-BuildStep 'Signing the packages' { + Sign-Packages -Configuration $Configuration -BuildNumber $BuildNumber -MSBuildVersion $msBuildVersion ` } ` -ev +BuildErrors diff --git a/build/sign.proj b/build/sign.proj deleted file mode 100644 index 7f0a3c74..00000000 --- a/build/sign.proj +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\ - $(RepositoryRootDirectory)artifacts\sign\obj\ - $(RepositoryRootDirectory) - GetOutputNupkgs - - - - - - NuGet - - - - - - - - - \ No newline at end of file From 6366df2eb478691b7a38ac9d835c7b84a0d104d7 Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Wed, 20 Mar 2019 08:49:06 -0700 Subject: [PATCH 2/2] Don't enable the legacy push route by default (#78) This only affects the NuGetV2WebApiEnabler.UseNuGetV2WebApiFeed API. NuGet.Server still enables the legacy push route by default since it already assumes there is only one feed in the application. Address https://github.com/NuGet/NuGetGallery/issues/7008 --- src/NuGet.Server.V2/NuGetV2WebApiEnabler.cs | 54 ++++++++++++-- .../App_Start/NuGetODataConfig.cs | 7 +- .../App_Start/NuGetODataConfig.cs.pp | 11 ++- test/NuGet.Server.Tests/IntegrationTests.cs | 71 +++++++++++++++---- .../TestablePackagesODataController.cs | 3 + 5 files changed, 121 insertions(+), 25 deletions(-) diff --git a/src/NuGet.Server.V2/NuGetV2WebApiEnabler.cs b/src/NuGet.Server.V2/NuGetV2WebApiEnabler.cs index 9915b74f..f24a5af5 100644 --- a/src/NuGet.Server.V2/NuGetV2WebApiEnabler.cs +++ b/src/NuGet.Server.V2/NuGetV2WebApiEnabler.cs @@ -1,5 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + using System; using System.Linq; using System.Net.Http; @@ -19,10 +20,46 @@ namespace NuGet.Server.V2 { public static class NuGetV2WebApiEnabler { + /// + /// Enables the NuGet V2 protocol routes on this . Note that this method does + /// not activate the legacy push URL, api/v2/package. To activate the legacy push route, use the + /// method overload. + /// + /// The HTTP configuration associated with your web app. + /// The route name prefix, to allow multiple feeds per web app. + /// The base URL for the routes, to allow multiple feeds per web app. + /// The name of the OData controller containing the actions. + /// The provided, for chaining purposes. public static HttpConfiguration UseNuGetV2WebApiFeed(this HttpConfiguration config, string routeName, - string routeUrlRoot, + string routeUrlRoot, string oDatacontrollerName) + { + return config.UseNuGetV2WebApiFeed( + routeName, + routeUrlRoot, + oDatacontrollerName, + enableLegacyPushRoute: false); + } + + /// + /// Enables the NuGet V2 protocol routes on this . + /// + /// The HTTP configuration associated with your web app. + /// The route name prefix, to allow multiple feeds per web app. + /// The base URL for the routes, to allow multiple feeds per web app. + /// The name of the OData controller containing the actions. + /// + /// Whether or not to enable the legacy push URL, api/v2/package. Note that this route does not + /// use the prefix or and therefore should only + /// be enabled once (i.e. on a single controller). + /// + /// The provided, for chaining purposes. + public static HttpConfiguration UseNuGetV2WebApiFeed(this HttpConfiguration config, + string routeName, + string routeUrlRoot, + string oDatacontrollerName, + bool enableLegacyPushRoute) { // Insert conventions to make NuGet-compatible OData feed possible var conventions = ODataRoutingConventions.CreateDefault(); @@ -53,12 +90,15 @@ public static HttpConfiguration UseNuGetV2WebApiFeed(this HttpConfiguration conf constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Delete) } ); - config.Routes.MapHttpRoute( - name: "apiv2package_upload", - routeTemplate: "api/v2/package", - defaults: new { controller = oDatacontrollerName, action = "UploadPackage" }, - constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Put) } - ); + if (enableLegacyPushRoute) + { + config.Routes.MapHttpRoute( + name: "apiv2package_upload", + routeTemplate: "api/v2/package", + defaults: new { controller = oDatacontrollerName, action = "UploadPackage" }, + constraints: new { httpMethod = new HttpMethodConstraint(HttpMethod.Put) } + ); + } config.Routes.MapODataServiceRoute(routeName, routeUrlRoot, oDataModel, new CountODataPathHandler(), conventions); return config; diff --git a/src/NuGet.Server/App_Start/NuGetODataConfig.cs b/src/NuGet.Server/App_Start/NuGetODataConfig.cs index d0a7cf91..2d1a0565 100644 --- a/src/NuGet.Server/App_Start/NuGetODataConfig.cs +++ b/src/NuGet.Server/App_Start/NuGetODataConfig.cs @@ -28,7 +28,12 @@ public static void Start() public static void Initialize(HttpConfiguration config, string controllerName) { - NuGetV2WebApiEnabler.UseNuGetV2WebApiFeed(config, "NuGetDefault", "nuget", controllerName); + NuGetV2WebApiEnabler.UseNuGetV2WebApiFeed( + config, + "NuGetDefault", + "nuget", + controllerName, + enableLegacyPushRoute: true); config.Services.Replace(typeof(IExceptionLogger), new TraceExceptionLogger()); diff --git a/src/NuGet.Server/App_Start/NuGetODataConfig.cs.pp b/src/NuGet.Server/App_Start/NuGetODataConfig.cs.pp index d4788aea..ac6dfec3 100644 --- a/src/NuGet.Server/App_Start/NuGetODataConfig.cs.pp +++ b/src/NuGet.Server/App_Start/NuGetODataConfig.cs.pp @@ -11,14 +11,19 @@ namespace $rootnamespace$.App_Start { public static class NuGetODataConfig - { + { public static void Start() - { + { ServiceResolver.SetServiceResolver(new DefaultServiceResolver()); var config = GlobalConfiguration.Configuration; - NuGetV2WebApiEnabler.UseNuGetV2WebApiFeed(config, "NuGetDefault", "nuget", "PackagesOData"); + NuGetV2WebApiEnabler.UseNuGetV2WebApiFeed( + config, + "NuGetDefault", + "nuget", + "PackagesOData", + enableLegacyPushRoute: true); config.Services.Replace(typeof(IExceptionLogger), new TraceExceptionLogger()); diff --git a/test/NuGet.Server.Tests/IntegrationTests.cs b/test/NuGet.Server.Tests/IntegrationTests.cs index d681fe96..7eca773e 100644 --- a/test/NuGet.Server.Tests/IntegrationTests.cs +++ b/test/NuGet.Server.Tests/IntegrationTests.cs @@ -19,6 +19,7 @@ using NuGet.Server.Core.Logging; using NuGet.Server.Core.Tests; using NuGet.Server.Core.Tests.Infrastructure; +using NuGet.Server.V2; using Xunit; using Xunit.Abstractions; using ISystemDependencyResolver = System.Web.Http.Dependencies.IDependencyResolver; @@ -162,6 +163,51 @@ public async Task PushPackageThenReadPackages() } } + [Fact] + public async Task CanSupportMultipleSetsOfRoutes() + { + // Arrange + using (var tc = new TestContext(_output)) + { + // Enable another set of routes. + NuGetV2WebApiEnabler.UseNuGetV2WebApiFeed( + tc.Config, + "NuGetDefault2", + "nuget2", + TestablePackagesODataController.Name); + + string apiKey = "foobar"; + tc.SetApiKey(apiKey); + + var packagePath = Path.Combine(tc.TemporaryDirectory, "package.nupkg"); + TestData.CopyResourceToPath(TestData.PackageResource, packagePath); + + // Act & Assert + // 1. Push to the legacy route. + await tc.PushPackageAsync(apiKey, packagePath, "/api/v2/package"); + + // 2. Make a request to the first set of routes. + using (var request = new HttpRequestMessage(HttpMethod.Get, "/nuget/Packages()")) + using (var response = await tc.Client.SendAsync(request)) + { + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + + Assert.Contains(TestData.PackageId, content); + } + + // 3. Make a request to the second set of routes. + using (var request = new HttpRequestMessage(HttpMethod.Get, "/nuget2/Packages()")) + using (var response = await tc.Client.SendAsync(request)) + { + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var content = await response.Content.ReadAsStringAsync(); + + Assert.Contains(TestData.PackageId, content); + } + } + } + /// /// Added due to https://github.com/NuGet/NuGetGallery/issues/6960. There was a concurrency issue when pushing /// packages that could lead to unnecessary cache rebuilds. @@ -354,7 +400,6 @@ public static IEnumerable EndpointsSupportingProjection private sealed class TestContext : IDisposable { private readonly HttpServer _server; - private readonly HttpConfiguration _config; public TestContext(ITestOutputHelper output) { @@ -371,13 +416,13 @@ public TestContext(ITestOutputHelper output) ServiceResolver = new DefaultServiceResolver(PackagesDirectory, Settings, Logger); - _config = new HttpConfiguration(); - _config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; - _config.DependencyResolver = new DependencyResolverAdapter(ServiceResolver); + Config = new HttpConfiguration(); + Config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; + Config.DependencyResolver = new DependencyResolverAdapter(ServiceResolver); - NuGetODataConfig.Initialize(_config, "TestablePackagesOData"); + NuGetODataConfig.Initialize(Config, TestablePackagesODataController.Name); - _server = new HttpServer(_config); + _server = new HttpServer(Config); Client = new SystemHttpClient(_server); Client.BaseAddress = new Uri("http://localhost/"); } @@ -388,6 +433,7 @@ public TestContext(ITestOutputHelper output) public TemporaryDirectory TemporaryDirectory { get; } public TemporaryDirectory PackagesDirectory { get; } public NameValueCollection Settings { get; } + public HttpConfiguration Config { get; } public SystemHttpClient Client { get; } public void SetApiKey(string apiKey) @@ -416,9 +462,9 @@ public MultipartContent GetFileUploadContent(params string[] paths) return content; } - public async Task PushPackageAsync(string apiKey, string packagePath) + public async Task PushPackageAsync(string apiKey, string packagePath, string pushUrl = "/nuget") { - using (var request = new HttpRequestMessage(HttpMethod.Put, "/nuget") + using (var request = new HttpRequestMessage(HttpMethod.Put, pushUrl) { Headers = { @@ -426,12 +472,9 @@ public async Task PushPackageAsync(string apiKey, string packagePath) }, Content = GetFileUploadContent(packagePath) }) + using (var response = await Client.SendAsync(request)) { - using (request) - using (var response = await Client.SendAsync(request)) - { - Assert.Equal(HttpStatusCode.Created, response.StatusCode); - } + Assert.Equal(HttpStatusCode.Created, response.StatusCode); } } @@ -439,7 +482,7 @@ public void Dispose() { Client.Dispose(); _server.Dispose(); - _config.Dispose(); + Config.Dispose(); ServiceResolver.Dispose(); PackagesDirectory.Dispose(); TemporaryDirectory.Dispose(); diff --git a/test/NuGet.Server.Tests/TestablePackagesODataController.cs b/test/NuGet.Server.Tests/TestablePackagesODataController.cs index a4b6a107..c2bd8b3d 100644 --- a/test/NuGet.Server.Tests/TestablePackagesODataController.cs +++ b/test/NuGet.Server.Tests/TestablePackagesODataController.cs @@ -7,6 +7,9 @@ namespace NuGet.Server.Tests { public class TestablePackagesODataController : PackagesODataController { + public static readonly string Name = nameof(TestablePackagesODataController) + .Substring(0, nameof(TestablePackagesODataController).Length - "Controller".Length); + public TestablePackagesODataController(IServiceResolver serviceResolver) : base(serviceResolver) {