Skip to content
This repository was archived by the owner on Oct 18, 2018. It is now read-only.

Commit eecaac3

Browse files
committed
Fix gaps in final commit for #258 (c9ab0b4)
- #275 - register `DefaultWebHookMetadataProvider` in DI - register `IWebHookFilterMetadata` implementations in DI - fix parameter reversal and overuse of `Resources.VerifyMethod_BadMethod` - add first functional tests - part of #180 - add functional test infrastructure - update `DropboxCoreReceiver` to meet new requirements e.g. add test-only secret key nits: - correct names of resources - let VS remove a few UTF8 BOMs
1 parent 71f1c14 commit eecaac3

16 files changed

+177
-34
lines changed

WebHooks.sln

+8-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.WebHoo
9494
EndProject
9595
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TrelloCoreReceiver", "samples\TrelloCoreReceiver\TrelloCoreReceiver.csproj", "{E9E37253-3FE1-44A4-A9E7-A2B6C54EECFE}"
9696
EndProject
97+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.WebHooks.FunctionalTest", "test\Microsoft.AspNetCore.WebHooks.FunctionalTest\Microsoft.AspNetCore.WebHooks.FunctionalTest.csproj", "{F42E56B7-60D4-481A-8585-04015B2B501E}"
98+
EndProject
9799
Global
98100
GlobalSection(SolutionConfigurationPlatforms) = preSolution
99101
Debug|Any CPU = Debug|Any CPU
@@ -232,6 +234,10 @@ Global
232234
{E9E37253-3FE1-44A4-A9E7-A2B6C54EECFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
233235
{E9E37253-3FE1-44A4-A9E7-A2B6C54EECFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
234236
{E9E37253-3FE1-44A4-A9E7-A2B6C54EECFE}.Release|Any CPU.Build.0 = Release|Any CPU
237+
{F42E56B7-60D4-481A-8585-04015B2B501E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
238+
{F42E56B7-60D4-481A-8585-04015B2B501E}.Debug|Any CPU.Build.0 = Debug|Any CPU
239+
{F42E56B7-60D4-481A-8585-04015B2B501E}.Release|Any CPU.ActiveCfg = Release|Any CPU
240+
{F42E56B7-60D4-481A-8585-04015B2B501E}.Release|Any CPU.Build.0 = Release|Any CPU
235241
EndGlobalSection
236242
GlobalSection(SolutionProperties) = preSolution
237243
HideSolutionNode = FALSE
@@ -270,9 +276,10 @@ Global
270276
{3EE810BD-AE8A-43F8-AC80-F490C0E2B3D8} = {9575CB90-BC4B-43BB-8AEA-82C53FDA4187}
271277
{91E02D64-BA6E-473C-A250-D1051A50DDAB} = {9575CB90-BC4B-43BB-8AEA-82C53FDA4187}
272278
{E9E37253-3FE1-44A4-A9E7-A2B6C54EECFE} = {E957C8D9-B4A0-488B-838F-BAB4DE080A76}
279+
{F42E56B7-60D4-481A-8585-04015B2B501E} = {9575CB90-BC4B-43BB-8AEA-82C53FDA4187}
273280
EndGlobalSection
274281
GlobalSection(ExtensibilityGlobals) = postSolution
275-
EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8;packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45
276282
SolutionGuid = {12CE6238-F847-4984-8622-1ED46072150A}
283+
EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8;packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45
277284
EndGlobalSection
278285
EndGlobal

build/dependencies.props

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project>
1+
<Project>
22
<PropertyGroup>
33
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
44
</PropertyGroup>
@@ -8,6 +8,7 @@
88
<MicrosoftAspNetCoreMvcCorePackageVersion>2.1.0-preview3-32233</MicrosoftAspNetCoreMvcCorePackageVersion>
99
<MicrosoftAspNetCoreMvcFormattersJsonPackageVersion>2.1.0-preview3-32233</MicrosoftAspNetCoreMvcFormattersJsonPackageVersion>
1010
<MicrosoftAspNetCoreMvcFormattersXmlPackageVersion>2.1.0-preview3-32233</MicrosoftAspNetCoreMvcFormattersXmlPackageVersion>
11+
<MicrosoftAspNetCoreMvcTestingPackageVersion>2.1.0-preview3-32233</MicrosoftAspNetCoreMvcTestingPackageVersion>
1112
<MicrosoftAspNetCorePackageVersion>2.1.0-preview3-32233</MicrosoftAspNetCorePackageVersion>
1213
<MicrosoftAspNetCoreStaticFilesPackageVersion>2.1.0-preview3-32233</MicrosoftAspNetCoreStaticFilesPackageVersion>
1314
<MicrosoftAspNetCoreTestingPackageVersion>2.1.0-preview3-32233</MicrosoftAspNetCoreTestingPackageVersion>

samples/Directory.Build.props

+5
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33

44
<PropertyGroup>
55
<IsPackable>false</IsPackable>
6+
7+
<DeveloperBuildTestWebsiteTfms Condition=" '$(DeveloperBuildTestWebsiteTfms)' == '' ">netcoreapp2.1</DeveloperBuildTestWebsiteTfms>
8+
<StandardTestWebsiteTfms>$(DeveloperBuildTestWebsiteTfms)</StandardTestWebsiteTfms>
9+
<StandardTestWebsiteTfms Condition=" '$(DeveloperBuild)' != 'true' ">netcoreapp2.1</StandardTestWebsiteTfms>
10+
<StandardTestWebsiteTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestWebsiteTfms);net461</StandardTestWebsiteTfms>
611
</PropertyGroup>
712
</Project>

samples/DropboxCoreReceiver/DropboxCoreReceiver.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22
<PropertyGroup>
3-
<TargetFramework>netcoreapp2.0</TargetFramework>
3+
<TargetFrameworks>$(StandardTestWebsiteTfms)</TargetFrameworks>
44
</PropertyGroup>
55

66
<ItemGroup>
+4-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.AspNetCore;
1+
using Microsoft.AspNetCore;
22
using Microsoft.AspNetCore.Hosting;
33

44
namespace DropboxCoreReceiver
@@ -7,12 +7,11 @@ public class Program
77
{
88
public static void Main(string[] args)
99
{
10-
BuildWebHost(args).Run();
10+
CreateWebHostBuilder(args).Build().Run();
1111
}
1212

13-
public static IWebHost BuildWebHost(string[] args) =>
13+
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
1414
WebHost.CreateDefaultBuilder(args)
15-
.UseStartup<Startup>()
16-
.Build();
15+
.UseStartup<Startup>();
1716
}
1817
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"WebHooks:Dropbox:SecretKey:default": "012345678901234"
3+
}

src/Microsoft.AspNetCore.WebHooks.Receivers/ApplicationModels/WebHookActionModelPropertyProvider.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ protected void EnsureValidBodyTypeMetadata(
380380
{
381381
var message = string.Format(
382382
CultureInfo.CurrentCulture,
383-
Resources.MetadataProvider_MissingMetadata,
383+
Resources.PropertyProvider_MissingMetadata,
384384
receiverName,
385385
typeof(IWebHookBodyTypeMetadataService));
386386
throw new InvalidOperationException(message);
@@ -410,7 +410,7 @@ protected void EnsureValidEventMetadata(IWebHookEventMetadata eventMetadata, str
410410
// IWebHookEventMetadata is mandatory when performing action selection using event names.
411411
var message = string.Format(
412412
CultureInfo.CurrentCulture,
413-
Resources.MetadataProvider_MissingMetadataServices,
413+
Resources.PropertyProvider_MissingMetadataServices,
414414
receiverName,
415415
typeof(IWebHookEventSelectorMetadata),
416416
typeof(IWebHookEventMetadata));
@@ -449,7 +449,7 @@ protected void EnsureValidEventFromBodyMetadata(
449449
{
450450
var message = string.Format(
451451
CultureInfo.CurrentCulture,
452-
Resources.MetadataProvider_ConflictingMetadataServices,
452+
Resources.PropertyProvider_ConflictingMetadataServices,
453453
receiverWithConflictingMetadata.ReceiverName,
454454
typeof(IWebHookEventFromBodyMetadata),
455455
typeof(IWebHookEventMetadata));
@@ -484,7 +484,7 @@ protected void EnsureUniqueRegistrations<TService>(IReadOnlyList<TService> servi
484484
{
485485
var message = string.Format(
486486
CultureInfo.CurrentCulture,
487-
Resources.MetadataProvider_DuplicateMetadata,
487+
Resources.PropertyProvider_DuplicateMetadata,
488488
duplicateMetadataGroup.Key, // ReceiverName
489489
typeof(TService));
490490
throw new InvalidOperationException(message);

src/Microsoft.AspNetCore.WebHooks.Receivers/Extensions/WebHookServiceCollectionSetup.cs

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.AspNetCore.WebHooks;
88
using Microsoft.AspNetCore.WebHooks.ApplicationModels;
99
using Microsoft.AspNetCore.WebHooks.Filters;
10+
using Microsoft.AspNetCore.WebHooks.Metadata;
1011
using Microsoft.Extensions.DependencyInjection.Extensions;
1112

1213
namespace Microsoft.Extensions.DependencyInjection
@@ -27,6 +28,8 @@ public static void AddWebHookServices(IServiceCollection services)
2728
throw new ArgumentNullException(nameof(services));
2829
}
2930

31+
services.TryAddSingleton<WebHookMetadataProvider, DefaultWebHookMetadataProvider>();
32+
3033
services.TryAddEnumerable(
3134
ServiceDescriptor.Transient<IApplicationModelProvider, WebHookActionModelFilterProvider>());
3235
services.TryAddEnumerable(

src/Microsoft.AspNetCore.WebHooks.Receivers/Filters/WebHookVerifyMethodFilter.cs

+25-9
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,19 @@ public void OnResourceExecuting(ResourceExecutingContext context)
8181
}
8282

8383
var request = context.HttpContext.Request;
84-
if (request.Body == null ||
85-
!request.ContentLength.HasValue ||
86-
request.ContentLength.Value == 0L ||
87-
!HttpMethods.IsPost(request.Method))
84+
if (!HttpMethods.IsPost(request.Method))
8885
{
8986
// Log about the issue and short-circuit remainder of the pipeline.
9087
context.RouteData.TryGetWebHookReceiverName(out var receiverName);
9188
context.Result = CreateBadMethodResult(request.Method, receiverName);
9289
}
90+
else if (request.Body == null ||
91+
!request.ContentLength.HasValue ||
92+
request.ContentLength.Value == 0L)
93+
{
94+
context.RouteData.TryGetWebHookReceiverName(out var receiverName);
95+
context.Result = CreateBadBodyResult(receiverName);
96+
}
9397
}
9498

9599
/// <inheritdoc />
@@ -98,19 +102,31 @@ public void OnResourceExecuted(ResourceExecutedContext context)
98102
// No-op
99103
}
100104

101-
private IActionResult CreateBadMethodResult(string methodName, string receiverName)
105+
private IActionResult CreateBadBodyResult(string receiverName)
102106
{
103107
_logger.LogWarning(
104108
0,
105-
"The HTTP '{RequestMethod}' method is not supported by the '{ReceiverName}' WebHook receiver.",
106-
methodName,
109+
"The '{ReceiverName}' WebHook receiver does not support an empty request body.",
107110
receiverName);
108111

112+
var message = string.Format(CultureInfo.CurrentCulture, Resources.VerifyMethod_BadBody, receiverName);
113+
114+
return new BadRequestObjectResult(message);
115+
}
116+
117+
private IActionResult CreateBadMethodResult(string methodName, string receiverName)
118+
{
119+
_logger.LogWarning(
120+
0,
121+
"The '{ReceiverName}' WebHook receiver does not support the HTTP '{RequestMethod}' method.",
122+
receiverName,
123+
methodName);
124+
109125
var message = string.Format(
110126
CultureInfo.CurrentCulture,
111127
Resources.VerifyMethod_BadMethod,
112-
methodName,
113-
receiverName);
128+
receiverName,
129+
methodName);
114130
var badMethod = new BadRequestObjectResult(message)
115131
{
116132
StatusCode = StatusCodes.Status405MethodNotAllowed

src/Microsoft.AspNetCore.WebHooks.Receivers/Metadata/WebHookMetadata.cs

+5
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ public static void Register<TService>(IServiceCollection services)
7676
services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IWebHookEventMetadata), type));
7777
}
7878

79+
if (typeof(IWebHookFilterMetadata).IsAssignableFrom(type))
80+
{
81+
services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IWebHookFilterMetadata), type));
82+
}
83+
7984
if (typeof(IWebHookGetHeadRequestMetadata).IsAssignableFrom(type))
8085
{
8186
services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IWebHookGetHeadRequestMetadata), type));

src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.Designer.cs

+17-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Microsoft.AspNetCore.WebHooks.Receivers/Properties/Resources.resx

+7-4
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,16 @@
135135
<data name="GetRequest_NoQueryParameter" xml:space="preserve">
136136
<value>A '{0}' WebHook verification request must contain a '{1}' query parameter.</value>
137137
</data>
138-
<data name="MetadataProvider_ConflictingMetadataServices" xml:space="preserve">
138+
<data name="PropertyProvider_ConflictingMetadataServices" xml:space="preserve">
139139
<value>Invalid metadata services found for the '{0}' WebHook receiver. Receivers must not provide both '{1}' and '{2}' services.</value>
140140
</data>
141-
<data name="MetadataProvider_DuplicateMetadata" xml:space="preserve">
141+
<data name="PropertyProvider_DuplicateMetadata" xml:space="preserve">
142142
<value>Invalid metadata services found for the '{0}' WebHook receiver. Receivers must not have more than one '{1}' registration.</value>
143143
</data>
144-
<data name="MetadataProvider_MissingMetadata" xml:space="preserve">
144+
<data name="PropertyProvider_MissingMetadata" xml:space="preserve">
145145
<value>Invalid metadata services found for the '{0}' WebHook receiver. Receiver must have an '{1}' implementation.</value>
146146
</data>
147-
<data name="MetadataProvider_MissingMetadataServices" xml:space="preserve">
147+
<data name="PropertyProvider_MissingMetadataServices" xml:space="preserve">
148148
<value>Invalid metadata services found for the '{0}' WebHook receiver. Receivers with attributes implementing '{1}' must also provide a '{2}' service.</value>
149149
</data>
150150
<data name="RequestReader_ModelBindingFailed" xml:space="preserve">
@@ -174,6 +174,9 @@
174174
<data name="VerifyCode_BadCode" xml:space="preserve">
175175
<value>The '{0}' query parameter provided in the HTTP request did not match the expected value.</value>
176176
</data>
177+
<data name="VerifyMethod_BadBody" xml:space="preserve">
178+
<value>The '{0}' WebHook receiver does not support an empty request body.</value>
179+
</data>
177180
<data name="VerifyMethod_BadMethod" xml:space="preserve">
178181
<value>The '{0}' WebHook receiver does not support the HTTP '{1}' method.</value>
179182
</data>

test/Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<PropertyGroup>
55
<DeveloperBuildTestTfms Condition=" '$(DeveloperBuildTestTfms)' == '' ">netcoreapp2.1</DeveloperBuildTestTfms>
66
<StandardTestTfms>$(DeveloperBuildTestTfms)</StandardTestTfms>
7-
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' ">netcoreapp2.1;netcoreapp2.0</StandardTestTfms>
7+
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' ">netcoreapp2.1</StandardTestTfms>
88
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestTfms);net461</StandardTestTfms>
99
</PropertyGroup>
1010

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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.Net;
5+
using System.Net.Http;
6+
using System.Threading.Tasks;
7+
using DropboxCoreReceiver;
8+
using Xunit;
9+
10+
namespace Microsoft.AspNetCore.WebHooks.FunctionalTest
11+
{
12+
public class DropboxSampleTest : IClassFixture<WebHookTestFixture<Startup>>
13+
{
14+
private readonly HttpClient _client;
15+
16+
public DropboxSampleTest(WebHookTestFixture<Startup> fixture)
17+
{
18+
_client = fixture.CreateClient();
19+
}
20+
21+
[Fact]
22+
public async Task HomePage_IsNotFound()
23+
{
24+
// Arrange & Act
25+
var response = await _client.GetAsync("/");
26+
27+
// Assert
28+
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
29+
}
30+
31+
[Fact]
32+
public async Task WebHookPage_Get_ReturnsChallenge()
33+
{
34+
// Arrange & Act
35+
var response = await _client.GetAsync("/api/webhooks/incoming/dropbox?challenge=012345678901234");
36+
37+
// Assert
38+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
39+
var responseText = await response.Content.ReadAsStringAsync();
40+
Assert.Equal("012345678901234", responseText);
41+
}
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<RootNamespace>Microsoft.AspNetCore.WebHooks.FunctionalTest</RootNamespace>
5+
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<ProjectReference Include="..\..\samples\DropboxCoreReceiver\DropboxCoreReceiver.csproj" />
10+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="$(MicrosoftAspNetCoreMvcTestingPackageVersion)" />
11+
</ItemGroup>
12+
13+
</Project>

0 commit comments

Comments
 (0)