Skip to content

Commit cc82088

Browse files
committed
Add simulate error endpoints to Pages, Api, and V2 curated feed controllers (#6842)
Progress on #6601
1 parent 91a4d51 commit cc82088

9 files changed

Lines changed: 183 additions & 0 deletions

File tree

src/NuGetGallery/App_Start/NuGetODataV2CuratedFeedConfig.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Linq;
6+
using System.Net.Http;
67
using System.Web.Http;
78
using System.Web.Http.OData.Batch;
89
using System.Web.Http.OData.Builder;
@@ -11,6 +12,7 @@
1112
using Microsoft.Data.Edm;
1213
using Microsoft.Data.Edm.Csdl;
1314
using Microsoft.Data.OData;
15+
using NuGetGallery.Controllers;
1416
using NuGetGallery.OData;
1517
using NuGetGallery.OData.Conventions;
1618
using NuGetGallery.OData.Routing;
@@ -68,6 +70,9 @@ public static IEdmModel GetEdmModel()
6870
findPackagesAction.Parameter<string>("id");
6971
findPackagesAction.ReturnsCollectionFromEntitySet<V2FeedPackage>("Packages");
7072

73+
var simulateErrorAction = builder.Action(nameof(ODataV2CuratedFeedController.SimulateError));
74+
simulateErrorAction.Parameter<string>("type");
75+
7176
var model = builder.GetEdmModel();
7277
model.SetEdmVersion(new Version(1, 0));
7378
model.SetEdmxVersion(new Version(1, 0));

src/NuGetGallery/App_Start/Routes.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ public static void RegisterUIRoutes(RouteCollection routes)
104104
"pages/contributors",
105105
new { controller = "Pages", action = "Contributors" });
106106

107+
routes.MapRoute(
108+
RouteName.PagesSimulateError,
109+
"pages/simulate-error",
110+
new { controller = "Pages", action = nameof(PagesController.SimulateError) });
111+
107112
routes.MapRoute(
108113
RouteName.Policies,
109114
"policies/{action}",
@@ -737,6 +742,11 @@ public static void RegisterApiV2Routes(RouteCollection routes)
737742
RouteName.DownloadNuGetExe,
738743
"nuget.exe",
739744
new { controller = "Api", action = "GetNuGetExeApi" });
745+
746+
routes.MapRoute(
747+
RouteName.ApiSimulateError,
748+
"api/simulate-error",
749+
new { controller = "Api", action = nameof(ApiController.SimulateError) });
740750
}
741751
}
742752
}

src/NuGetGallery/Controllers/ApiController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,12 @@ public ActionResult HealthProbe()
275275
return new HttpStatusCodeWithBodyResult(HttpStatusCode.OK, "Gallery is Available");
276276
}
277277

278+
[HttpGet]
279+
public virtual ActionResult SimulateError(SimulatedErrorType type = SimulatedErrorType.Exception)
280+
{
281+
return type.MapToMvcResult();
282+
}
283+
278284
[HttpPost]
279285
[ApiAuthorize]
280286
[ApiScopeRequired(NuGetScopes.PackagePush, NuGetScopes.PackagePushVersion)]

src/NuGetGallery/Controllers/ODataV2CuratedFeedController.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
using System;
55
using System.Linq;
6+
using System.Net;
7+
using System.Net.Http;
68
using System.Threading.Tasks;
79
using System.Web.Http;
810
using System.Web.Http.OData;
@@ -69,6 +71,20 @@ public IHttpActionResult Get(
6971
return TrackedQueryResult(options, queryable, MaxPageSize, customQuery: true);
7072
}
7173

74+
[HttpGet]
75+
[CacheOutput(NoCache = true)]
76+
public virtual HttpResponseMessage SimulateError(
77+
string curatedFeedName,
78+
[FromUri] string type = "Exception")
79+
{
80+
if (!Enum.TryParse<SimulatedErrorType>(type, out var parsedType))
81+
{
82+
parsedType = SimulatedErrorType.Exception;
83+
}
84+
85+
return parsedType.MapToWebApiResult();
86+
}
87+
7288
// /api/v2/curated-feed/curatedFeedName/Packages/$count?semVerLevel=
7389
[HttpGet]
7490
[CacheOutput(NoCache = true)]

src/NuGetGallery/Controllers/PagesController.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,11 @@ public virtual async Task<ActionResult> Privacy()
148148
}
149149
return View();
150150
}
151+
152+
[HttpGet]
153+
public virtual ActionResult SimulateError(SimulatedErrorType type = SimulatedErrorType.Exception)
154+
{
155+
return type.MapToMvcResult();
156+
}
151157
}
152158
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Net;
6+
using System.Net.Http;
7+
using System.Web;
8+
using System.Web.Http;
9+
using System.Web.Mvc;
10+
11+
namespace NuGetGallery
12+
{
13+
public static class SimulatedErrorTypeExtensions
14+
{
15+
public static HttpResponseMessage MapToWebApiResult(this SimulatedErrorType type)
16+
{
17+
var message = type.GetMessage();
18+
switch (type)
19+
{
20+
case SimulatedErrorType.Result400:
21+
return new HttpResponseMessage(HttpStatusCode.BadRequest)
22+
{
23+
ReasonPhrase = message,
24+
};
25+
case SimulatedErrorType.Result404:
26+
return new HttpResponseMessage(HttpStatusCode.NotFound)
27+
{
28+
ReasonPhrase = message,
29+
};
30+
case SimulatedErrorType.Result500:
31+
return new HttpResponseMessage(HttpStatusCode.InternalServerError)
32+
{
33+
ReasonPhrase = message,
34+
};
35+
case SimulatedErrorType.Result503:
36+
return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
37+
{
38+
ReasonPhrase = message,
39+
};
40+
default:
41+
throw type.MapToException();
42+
}
43+
}
44+
45+
public static ActionResult MapToMvcResult(this SimulatedErrorType type)
46+
{
47+
var message = type.GetMessage();
48+
switch (type)
49+
{
50+
case SimulatedErrorType.Result400:
51+
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
52+
case SimulatedErrorType.Result404:
53+
return new HttpStatusCodeResult(HttpStatusCode.NotFound, message);
54+
case SimulatedErrorType.Result500:
55+
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError, message);
56+
case SimulatedErrorType.Result503:
57+
return new HttpStatusCodeResult(HttpStatusCode.ServiceUnavailable, message);
58+
default:
59+
throw type.MapToException();
60+
}
61+
}
62+
public static string GetMessage(this SimulatedErrorType type)
63+
{
64+
return $"{nameof(SimulatedErrorType)} {type}";
65+
}
66+
67+
public static Exception MapToException(this SimulatedErrorType type)
68+
{
69+
var message = type.GetMessage();
70+
switch (type)
71+
{
72+
case SimulatedErrorType.HttpException400:
73+
return new HttpException(400, message);
74+
case SimulatedErrorType.HttpException404:
75+
return new HttpException(404, message);
76+
case SimulatedErrorType.HttpException500:
77+
return new HttpException(500, message);
78+
case SimulatedErrorType.HttpException503:
79+
return new HttpException(503, message);
80+
case SimulatedErrorType.HttpResponseException400:
81+
return new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest)
82+
{
83+
ReasonPhrase = message,
84+
});
85+
case SimulatedErrorType.HttpResponseException404:
86+
return new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound)
87+
{
88+
ReasonPhrase = message,
89+
});
90+
case SimulatedErrorType.HttpResponseException500:
91+
return new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
92+
{
93+
ReasonPhrase = message,
94+
});
95+
case SimulatedErrorType.HttpResponseException503:
96+
return new HttpResponseException(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable)
97+
{
98+
ReasonPhrase = message,
99+
});
100+
case SimulatedErrorType.Exception:
101+
return new Exception(message);
102+
case SimulatedErrorType.UserSafeException:
103+
return new UserSafeException(message);
104+
case SimulatedErrorType.ReadOnlyMode:
105+
return new ReadOnlyModeException(message);
106+
default:
107+
return new Exception("Unknown simulated error type.");
108+
}
109+
}
110+
}
111+
}

src/NuGetGallery/NuGetGallery.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@
274274
<Compile Include="Extensions\RouteExtensions.cs" />
275275
<Compile Include="Extensions\ScopeExtensions.cs" />
276276
<Compile Include="Extensions\CredentialExtensions.cs" />
277+
<Compile Include="Extensions\SimulatedErrorTypeExtensions.cs" />
277278
<Compile Include="Extensions\UserExtensions.cs" />
278279
<Compile Include="Filters\ApiScopeRequiredAttribute.cs" />
279280
<Compile Include="Filters\UIAuthorizeAttribute.cs" />
@@ -417,6 +418,7 @@
417418
<Compile Include="Migrations\201711021733062_ApiKeyOwnerScope.Designer.cs">
418419
<DependentUpon>201711021733062_ApiKeyOwnerScope.cs</DependentUpon>
419420
</Compile>
421+
<Compile Include="RequestModels\SimulatedErrorType.cs" />
420422
<Compile Include="Security\AutomaticOverwriteRequiredSignerPolicy.cs" />
421423
<Compile Include="Security\ControlRequiredSignerPolicy.cs" />
422424
<Compile Include="Security\MicrosoftTeamSubscription.cs" />
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace NuGetGallery
5+
{
6+
public enum SimulatedErrorType
7+
{
8+
Result400,
9+
Result404,
10+
Result500,
11+
Result503,
12+
HttpException400,
13+
HttpException404,
14+
HttpException500,
15+
HttpException503,
16+
HttpResponseException400,
17+
HttpResponseException404,
18+
HttpResponseException500,
19+
HttpResponseException503,
20+
Exception,
21+
UserSafeException,
22+
ReadOnlyMode,
23+
}
24+
}

src/NuGetGallery/RouteName.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,8 @@ public static class RouteName
100100
public const string GetOrganizationCertificates = "GetOrganizationCertificates";
101101
public const string SetRequiredSigner = "SetRequiredSigner";
102102
public const string License = "License";
103+
public const string ApiV2CuratedSimulateError = "api-v2curated-simulate-error";
104+
public const string PagesSimulateError = "PagesSimulateError";
105+
public const string ApiSimulateError = "ApiSimulateError";
103106
}
104107
}

0 commit comments

Comments
 (0)