Skip to content

Commit

Permalink
Merge pull request #17 from martincostello/Remove-Workarounds
Browse files Browse the repository at this point in the history
Remove workarounds for Amazon.Lambda.RuntimeSupport
  • Loading branch information
martincostello authored Nov 6, 2019
2 parents 862b44f + d9808fe commit f7f62cf
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 60 deletions.
23 changes: 4 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ Here's an example of how to do this with a simple Lambda function that takes an
```csharp
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Lambda.RuntimeSupport;
Expand All @@ -51,17 +50,7 @@ namespace MyFunctions
var serializer = new JsonSerializer();

using var handlerWrapper = HandlerWrapper.GetHandlerWrapper<int[], int[]>(ReverseAsync, serializer);
using var bootstrap = new LambdaBootstrap(handlerWrapper);

if (httpClient != null)
{
// Use reflection to assign the HttpClient to the LambdaBootstrap instance
var client = new RuntimeApiClient(httpClient);
var type = bootstrap.GetType();
var property = type.GetProperty("Client", BindingFlags.Instance | BindingFlags.NonPublic);

property.SetValue(bootstrap, client);
}
using var bootstrap = new LambdaBootstrap(httpClient ?? new HttpClient(), handlerWrapper);

await bootstrap.RunAsync(cancellationToken);
}
Expand All @@ -74,10 +63,6 @@ namespace MyFunctions
}
```

Notice the use of reflection to set a new `RuntimeApiClient` instance using the specified `HttpClient` value onto the created instance of `LambdaBootstrap`. At the time of writing, this is the only way to configure things to use the Lambda test server to process requests.

> I've reached out to the AWS Lambda .NET team with a suggestion to provide a supported way to specify a custom `HttpClient` in a future version of the NuGet package here: https://github.com/aws/aws-lambda-dotnet/pull/540
Once you've done that, you can use `LambdaTestServer` in your tests with your function to verify how it processes requests.

Here's an example using xunit to verify that `ReverseFunction` works as intended:
Expand Down Expand Up @@ -340,7 +325,7 @@ Test Name: Function_Reverses_Numbers_With_Logging
Test Outcome: Passed
Result StandardOutput:
[2019-11-04 15:21:06Z] info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 GET http://localhost/2018-06-01/runtime/invocation/next
Request starting HTTP/1.1 GET http://localhost/2018-06-01/runtime/invocation/next
[2019-11-04 15:21:06Z] info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/{LambdaVersion}/runtime/invocation/next HTTP: GET'
[2019-11-04 15:21:06Z] info: MartinCostello.Testing.AwsLambdaTestServer.RuntimeHandler[0]
Expand All @@ -352,7 +337,7 @@ Result StandardOutput:
[2019-11-04 15:21:06Z] info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 71.9334ms 200 application/json
[2019-11-04 15:21:06Z] info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost/2018-06-01/runtime/invocation/7e1a283d-6268-4401-921c-0d0d67da1da4/response application/json
Request starting HTTP/1.1 POST http://localhost/2018-06-01/runtime/invocation/7e1a283d-6268-4401-921c-0d0d67da1da4/response application/json
[2019-11-04 15:21:06Z] info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/{LambdaVersion}/runtime/invocation/{AwsRequestId}/response HTTP: POST'
[2019-11-04 15:21:06Z] info: MartinCostello.Testing.AwsLambdaTestServer.RuntimeHandler[0]
Expand All @@ -362,7 +347,7 @@ Result StandardOutput:
[2019-11-04 15:21:06Z] info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/{LambdaVersion}/runtime/invocation/{AwsRequestId}/response HTTP: POST'
[2019-11-04 15:21:06Z] info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 26.6306ms 204
Request finished in 26.6306ms 204
```

## Feedback
Expand Down
8 changes: 3 additions & 5 deletions src/AwsLambdaTestServer/RuntimeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,9 @@ internal async Task HandleNextAsync(HttpContext httpContext)
"Stopped listening for additional requests for Lambda function with ARN {FunctionArn}.",
_options.FunctionArn);

// Send a dummy response to prevent the listen loop from erroring
request = new LambdaTestRequest(new[] { (byte)'{', (byte)'}' }, "xx-lambda-test-server-stopped-xx");

// This dummy request wasn't enqueued, so it needs manually adding
_responses.GetOrAdd(request.AwsRequestId, (_) => new ResponseContext(Channel.CreateBounded<LambdaTestResponse>(1)));
// Throw back into LambdaBootstrap, which will then stop processing.
// See https://github.com/aws/aws-lambda-dotnet/pull/540 for details of the change.
throw;
}

// Write the response for the Lambda runtime to pass to the function to invoke
Expand Down
13 changes: 1 addition & 12 deletions tests/AwsLambdaTestServer.Tests/FunctionRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.

using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Lambda.RuntimeSupport;
Expand All @@ -19,17 +18,7 @@ internal static async Task RunAsync<T>(HttpClient httpClient, CancellationToken
var serializer = new JsonSerializer();

using var handlerWrapper = HandlerWrapper.GetHandlerWrapper<MyRequest, MyResponse>(handler.SumAsync, serializer);
using var bootstrap = new LambdaBootstrap(handlerWrapper, handler.InitializeAsync);

if (httpClient != null)
{
// Replace the internal runtime API client with one using the specified HttpClient.
// See https://github.com/aws/aws-lambda-dotnet/blob/4f9142b95b376bd238bce6be43f4e1ec1f983592/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/LambdaBootstrap.cs#L41
var client = new RuntimeApiClient(httpClient);

var property = typeof(LambdaBootstrap).GetProperty("Client", BindingFlags.Instance | BindingFlags.NonPublic);
property.SetValue(bootstrap, client);
}
using var bootstrap = new LambdaBootstrap(httpClient, handlerWrapper, handler.InitializeAsync);

await bootstrap.RunAsync(cancellationToken);
}
Expand Down
15 changes: 3 additions & 12 deletions tests/AwsLambdaTestServer.Tests/LambdaTestServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -392,9 +391,11 @@ void Configure(IServiceCollection services)
public void Finalizer_Does_Not_Throw()
{
#pragma warning disable CA2000
#pragma warning disable IDE0067
// Act (no Assert)
_ = new LambdaTestServer();
#pragma warning restore CA2000
#pragma warning restore IDE0067
}

[Fact]
Expand Down Expand Up @@ -474,17 +475,7 @@ private static class CustomFunction
internal static async Task RunAsync(HttpClient httpClient, CancellationToken cancellationToken)
{
var handler = new CustomHandler();
using var bootstrap = new LambdaBootstrap(handler.InvokeAsync);

if (httpClient != null)
{
// Replace the internal runtime API client with one using the specified HttpClient.
// See https://github.com/aws/aws-lambda-dotnet/blob/4f9142b95b376bd238bce6be43f4e1ec1f983592/Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/LambdaBootstrap.cs#L41
var client = new RuntimeApiClient(httpClient);

var property = typeof(LambdaBootstrap).GetProperty("Client", BindingFlags.Instance | BindingFlags.NonPublic);
property.SetValue(bootstrap, client);
}
using var bootstrap = new LambdaBootstrap(httpClient, handler.InvokeAsync);

await bootstrap.RunAsync(cancellationToken);
}
Expand Down
13 changes: 1 addition & 12 deletions tests/AwsLambdaTestServer.Tests/ReverseFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Lambda.RuntimeSupport;
Expand All @@ -23,17 +22,7 @@ public static async Task RunAsync(
var serializer = new JsonSerializer();

using var handlerWrapper = HandlerWrapper.GetHandlerWrapper<int[], int[]>(ReverseAsync, serializer);
using var bootstrap = new LambdaBootstrap(handlerWrapper);

if (httpClient != null)
{
// Use reflection to assign the HttpClient to the LambdaBootstrap instance
var client = new RuntimeApiClient(httpClient);
var type = bootstrap.GetType();
var property = type.GetProperty("Client", BindingFlags.Instance | BindingFlags.NonPublic);

property.SetValue(bootstrap, client);
}
using var bootstrap = new LambdaBootstrap(httpClient ?? new HttpClient(), handlerWrapper);

await bootstrap.RunAsync(cancellationToken);
}
Expand Down

0 comments on commit f7f62cf

Please sign in to comment.