Skip to content

Commit f3f7a1e

Browse files
committed
Fix bugs in LambdaSnapstartExecuteRequestsBeforeSnapshotHelper and add unit tests
1 parent bac5afb commit f3f7a1e

6 files changed

Lines changed: 141 additions & 11 deletions

File tree

Libraries/Libraries.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnapshotRestore.Registry",
135135
EndProject
136136
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SnapshotRestore.Registry.Tests", "test\SnapshotRestore.Registry.Tests\SnapshotRestore.Registry.Tests.csproj", "{A699E183-D0D4-4F26-A0A7-88DA5607F455}"
137137
EndProject
138+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Amazon.Lambda.AspNetCoreServer.Hosting.Tests", "test\Amazon.Lambda.AspNetCoreServer.Hosting.Tests\Amazon.Lambda.AspNetCoreServer.Hosting.Tests.csproj", "{D61CBB71-17AB-4EC2-8C6A-70E9D7C60526}"
139+
EndProject
138140
Global
139141
GlobalSection(SolutionConfigurationPlatforms) = preSolution
140142
Debug|Any CPU = Debug|Any CPU
@@ -369,6 +371,10 @@ Global
369371
{A699E183-D0D4-4F26-A0A7-88DA5607F455}.Debug|Any CPU.Build.0 = Debug|Any CPU
370372
{A699E183-D0D4-4F26-A0A7-88DA5607F455}.Release|Any CPU.ActiveCfg = Release|Any CPU
371373
{A699E183-D0D4-4F26-A0A7-88DA5607F455}.Release|Any CPU.Build.0 = Release|Any CPU
374+
{D61CBB71-17AB-4EC2-8C6A-70E9D7C60526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
375+
{D61CBB71-17AB-4EC2-8C6A-70E9D7C60526}.Debug|Any CPU.Build.0 = Debug|Any CPU
376+
{D61CBB71-17AB-4EC2-8C6A-70E9D7C60526}.Release|Any CPU.ActiveCfg = Release|Any CPU
377+
{D61CBB71-17AB-4EC2-8C6A-70E9D7C60526}.Release|Any CPU.Build.0 = Release|Any CPU
372378
EndGlobalSection
373379
GlobalSection(SolutionProperties) = preSolution
374380
HideSolutionNode = FALSE
@@ -435,6 +441,7 @@ Global
435441
{7300983D-8FCE-42EA-9B9E-B1C5347D15D8} = {1DE4EE60-45BA-4EF7-BE00-B9EB861E4C69}
436442
{7261A438-8C1D-47AD-98B0-7678F72E4382} = {AAB54E74-20B1-42ED-BC3D-CE9F7BC7FD12}
437443
{A699E183-D0D4-4F26-A0A7-88DA5607F455} = {1DE4EE60-45BA-4EF7-BE00-B9EB861E4C69}
444+
{D61CBB71-17AB-4EC2-8C6A-70E9D7C60526} = {1DE4EE60-45BA-4EF7-BE00-B9EB861E4C69}
438445
EndGlobalSection
439446
GlobalSection(ExtensibilityGlobals) = postSolution
440447
SolutionGuid = {503678A4-B8D1-4486-8915-405A3E9CF0EB}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Snapstart/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

Libraries/src/Amazon.Lambda.AspNetCoreServer.Hosting/Internal/LambdaSnapstartExecuteRequestsBeforeSnapshotHelper.cs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public static async Task ExecuteSnapstartInitRequests(string jsonRequest, int ti
132132

133133
private class LambdaSnapstartInitializerHttpMessageHandler : HttpMessageHandler
134134
{
135-
private LambdaEventSource _lambdaEventSource;
135+
private readonly LambdaEventSource _lambdaEventSource;
136136

137137
public static Uri BaseUri { get; } = new Uri("http://localhost");
138138

@@ -145,7 +145,7 @@ public LambdaSnapstartInitializerHttpMessageHandler(LambdaEventSource lambdaEven
145145

146146
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
147147
{
148-
if (null == request?.RequestUri)
148+
if (null == request.RequestUri)
149149
return new HttpResponseMessage(HttpStatusCode.OK);
150150

151151
var duckRequest = new
@@ -157,7 +157,7 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
157157
kvp => kvp.Value.FirstOrDefault(),
158158
StringComparer.OrdinalIgnoreCase),
159159
HttpMethod = request.Method.ToString(),
160-
Path = request.RequestUri?.MakeRelativeUri(BaseUri).ToString() ?? string.Empty,
160+
Path = "/" + BaseUri.MakeRelativeUri(request.RequestUri),
161161
RawQuery = request.RequestUri?.Query,
162162
Query = QueryHelpers.ParseNullableQuery(request.RequestUri?.Query)
163163
};
@@ -172,21 +172,33 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
172172
HttpMethod = duckRequest.HttpMethod,
173173
QueryStringParameters = duckRequest.Query?.ToDictionary(k => k.Key, v => v.Value.ToString())
174174
},
175-
LambdaEventSource.HttpApi => new APIGatewayProxyRequest
175+
LambdaEventSource.HttpApi => new APIGatewayHttpApiV2ProxyRequest
176176
{
177177
Body = duckRequest.Body,
178178
Headers = duckRequest.Headers,
179-
Path = duckRequest.Path,
180-
HttpMethod = duckRequest.HttpMethod,
181-
QueryStringParameters = duckRequest.Query?.ToDictionary(k => k.Key, v => v.Value.ToString())
179+
RawPath = duckRequest.Path,
180+
RequestContext = new APIGatewayHttpApiV2ProxyRequest.ProxyRequestContext
181+
{
182+
Http = new APIGatewayHttpApiV2ProxyRequest.HttpDescription
183+
{
184+
Method = duckRequest.HttpMethod,
185+
Path = duckRequest.Path
186+
}
187+
},
188+
QueryStringParameters = duckRequest.Query?.ToDictionary(k => k.Key, v => v.Value.ToString()),
189+
RawQueryString = duckRequest.RawQuery
182190
},
183-
LambdaEventSource.RestApi => new APIGatewayHttpApiV2ProxyRequest
191+
LambdaEventSource.RestApi => new APIGatewayProxyRequest
184192
{
185193
Body = duckRequest.Body,
186194
Headers = duckRequest.Headers,
187-
RawPath = duckRequest.Path,
188-
QueryStringParameters = duckRequest.Query?.ToDictionary(k => k.Key, v => v.Value.ToString()),
189-
RawQueryString = duckRequest.RawQuery
195+
Path = duckRequest.Path,
196+
HttpMethod = duckRequest.HttpMethod,
197+
RequestContext = new APIGatewayProxyRequest.ProxyRequestContext
198+
{
199+
HttpMethod = duckRequest.HttpMethod
200+
},
201+
QueryStringParameters = duckRequest.Query?.ToDictionary(k => k.Key, v => v.Value.ToString())
190202
},
191203
_ => throw new NotImplementedException(
192204
$"Unknown {nameof(LambdaEventSource)}: {Enum.GetName(_lambdaEventSource)}")
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
using Amazon.Lambda.AspNetCoreServer.Test;
6+
using Microsoft.AspNetCore.Builder;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Xunit;
9+
10+
namespace Amazon.Lambda.AspNetCoreServer.Hosting.Tests;
11+
12+
/// <summary>
13+
/// Tests for <see cref="ServiceCollectionExtensions.AddAWSLambdaBeforeSnapshotRequest"/>
14+
/// </summary>
15+
public class AddAWSLambdaBeforeSnapshotRequestTests
16+
{
17+
#if NET8_0_OR_GREATER
18+
[Theory]
19+
[InlineData(LambdaEventSource.HttpApi)]
20+
[InlineData(LambdaEventSource.RestApi)]
21+
[InlineData(LambdaEventSource.ApplicationLoadBalancer)]
22+
public async Task VerifyCallbackIsInvoked(LambdaEventSource hostingType)
23+
{
24+
using var e1 = new EnvironmentVariableHelper("AWS_LAMBDA_FUNCTION_NAME", nameof(VerifyCallbackIsInvoked));
25+
using var e2 = new EnvironmentVariableHelper("AWS_LAMBDA_INITIALIZATION_TYPE", "snap-start");
26+
27+
var callbackDidTheCallback = false;
28+
29+
var builder = WebApplication.CreateSlimBuilder(new string[0]);
30+
31+
builder.Services.AddAWSLambdaHosting(hostingType);
32+
// Initialize asp.net pipeline before Snapshot
33+
builder.Services.AddAWSLambdaBeforeSnapshotRequest(async httpClient =>
34+
{
35+
await httpClient.GetAsync($"/test");
36+
});
37+
38+
var app = builder.Build();
39+
40+
app.MapGet($"/test",
41+
() =>
42+
{
43+
callbackDidTheCallback = true;
44+
return "Success";
45+
});
46+
47+
var serverTask = app.RunAsync();
48+
49+
// let the server run for a max of 500 ms
50+
await Task.WhenAny(
51+
serverTask,
52+
Task.Delay(TimeSpan.FromMilliseconds(500)));
53+
54+
// shut down server
55+
await app.StopAsync();
56+
57+
Assert.True(callbackDidTheCallback);
58+
}
59+
#endif
60+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net8.0</TargetFrameworks>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
8+
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
9+
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
10+
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
11+
<NoWarn>1701;1702;1705;CS0618</NoWarn>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
16+
<PackageReference Include="xunit" Version="2.3.1" />
17+
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\src\Amazon.Lambda.AspNetCoreServer.Hosting\Amazon.Lambda.AspNetCoreServer.Hosting.csproj" />
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
26+
</ItemGroup>
27+
28+
</Project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System;
5+
6+
namespace Amazon.Lambda.AspNetCoreServer.Test;
7+
8+
public class EnvironmentVariableHelper : IDisposable
9+
{
10+
private string _name;
11+
private string? _oldValue;
12+
public EnvironmentVariableHelper(string name, string value)
13+
{
14+
_name = name;
15+
_oldValue = Environment.GetEnvironmentVariable(name);
16+
17+
Environment.SetEnvironmentVariable(name, value);
18+
}
19+
20+
public void Dispose() => Environment.SetEnvironmentVariable(_name, _oldValue);
21+
}

0 commit comments

Comments
 (0)