Описание
Я работаю с AWS Lambda, НО без пакета Amazon.Lambda.AspNetCoreServer
все работает нормально, за исключением того факта, что я добавляю некоторые основные настраиваемые заголовки ответов, такие как тип содержимого JSON, и ничего не добавляется в окончательные заголовки ответов HTTP.
В моем конкретном случае я не использую Amazon.Lambda.AspNetCoreServer
, потому что я создаю шаблон бессерверной инфраструктуры.
- Это моя реализация функции Lambda: https://github.com/RichardSilveira/UserServerlessMicroservice/blob/master/src/userService/Functions/GetUserByIdFunction.cs
public class GetUserByIdFunction : FunctionBase
{
private IUserRepository _userRepository;
protected override void ConfigureServices(IServiceCollection serviceCollection)
{
var connString = Configuration["UserServiceDbContextConnectionString"];
// serviceCollection.AddDbContext<UserContext>(options => options.UseMySql(connString));
serviceCollection.AddDbContext<UserContext>(options => options.UseInMemoryDatabase(connString));//temporarily
serviceCollection.AddScoped<IUserRepository, UserRepository>();
}
protected override void Configure(IServiceProvider serviceProvider)
{
_userRepository = serviceProvider.GetService<IUserRepository>();
}
// Invoked by AWS Lambda at runtime
public GetUserByIdFunction()
{
}
public GetUserByIdFunction(
IConfiguration configuration,
IUserRepository userRepository)
{
// Constructor used by tests
_userRepository = userRepository;
}
public async Task<APIGatewayHttpApiV2ProxyResponse> Handle(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)
{
LogFunctionMetadata(request, context);
if (!RunningAsLocal) ConfigureDependencies();
var userId = Guid.Parse(request.PathParameters["userid"]);
var user = await _userRepository.GetByIdAsync(userId);
if (user == null) return NotFound();
return Ok(user);
}
}
- Моя реализация базы функций https://github.com/RichardSilveira/UserServerlessMicroservice/blob/master/src/userService/Functions/FunctionBase.cs
public abstract class FunctionBase
{
protected IConfiguration Configuration { get; private set; }
protected bool RunningAsLocal = false;
public FunctionBase() => Configuration = ConfigurationService.Instance.Configuration;
public FunctionBase(IConfiguration configuration)
{
Configuration = configuration;
RunningAsLocal = true;
}
protected void ConfigureDependencies()
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
Configure(serviceCollection.BuildServiceProvider());
}
protected abstract void ConfigureServices(IServiceCollection serviceCollection);
protected abstract void Configure(IServiceProvider serviceProvider);
protected void LogFunctionMetadata(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)
{
LambdaLogger.Log($"CONTEXT {Serialize(context.GetMainProperties())}");
LambdaLogger.Log($"EVENT: {Serialize(request.GetMainProperties())}");
}
protected APIGatewayHttpApiV2ProxyResponse Ok() =>
new APIGatewayHttpApiV2ProxyResponse()
{
StatusCode = (int) HttpStatusCode.OK,
Headers = new Dictionary<string, string>
{
{"Content-Type", "application/json"}
}
};
protected APIGatewayHttpApiV2ProxyResponse NotFound() =>
new APIGatewayHttpApiV2ProxyResponse()
{
StatusCode = (int) HttpStatusCode.NotFound,
Headers = new Dictionary<string, string>
{
{"Content-Type", "application/json"}
}
};
}
Единственная проблема заключается в том, что любой заголовок, добавленный к классу APIGatewayHttpApiV2ProxyResponse
, не добавляется к окончательному ответу HTTP, как ожидалось.
Примечание: я уже пробовал использовать SetHeaderValues
, например:
protected APIGatewayHttpApiV2ProxyResponse Ok(object body)
{
var response = new APIGatewayHttpApiV2ProxyResponse()
{
StatusCode = (int) HttpStatusCode.OK,
Body = Serialize(body)
};
response.SetHeaderValues("Content-Type", "application/json", false);
response.SetHeaderValues("Access-Control-Allow-Origin", "*", false);
response.SetHeaderValues("Access-Control-Allow-Credentials", "true", false);
return response;
}
Шаги размножения
git clone https://github.com/RichardSilveira/UserServerlessMicroservice
cd UserServerlessMicroservice
cd src/userService
npm i -g serverless
Примечание. Бессерверная структура создает уровень абстракции при облачной информации, это означает, что стек будет развернут в учетной записи AWS, вы можете легко удалить стек - за этот стек, который вы загружаете, плата не взимается.
provider:
name: aws
profile: default
runtime: dotnetcore3.1
stage: dev
region: sa-east-1
Вы можете указать имя профиля из файла учетных данных AWS на локальном компьютере в файле
serverless.yml
, добавивprofile: <name>
, например, в приведенном выше примере. Это необязательно, если вы ничего не сделаете, будет использоваться профиль по умолчанию.
build
sls deploy -v
Журналы
N/A
Среда
Я считаю, что лучше показать весь мой файл описания проекта.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<PackageId>aws-csharp</PackageId>
<RootNamespace>UserService</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.1.0" />
<PackageReference Include="Amazon.Lambda.Core" Version="1.1.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.0.1" />
<PackageReference Include="EventStore.Client" Version="20.6.0" />
<PackageReference Include="FluentValidation" Version="9.0.1" />
<PackageReference Include="MediatR" Version="8.1.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.6" />
<PackageReference Include="MySql.Data" Version="8.0.21" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.2" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.dev.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.local.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Есть предположения?
Заранее спасибо!