Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<PackageVersion Include="AutoFixture.AutoNSubstitute" Version="4.18.1" />
<PackageVersion Include="AutoFixture.Xunit3" Version="4.19.0" />
<PackageVersion Include="BenchmarkDotNet" Version="0.15.6" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<!-- Source Gen Libraries -->
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
Expand Down
1 change: 1 addition & 0 deletions src/AwsLambda.Host/AwsLambda.Host.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Http" />
</ItemGroup>
<ItemGroup>
<None Include="build\AwsLambda.Host.targets" Pack="true" PackagePath="build" Visible="true" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace AwsLambda.Host.Builder.Extensions;

/// <summary>
/// Extension methods for configuring the Lambda bootstrap HTTP client in an
/// <see cref="IServiceCollection" />.
/// </summary>
public static class LambdaHttpClientServiceCollectionExtensions
{
extension(IServiceCollection services)
{
Comment thread
j-d-ha marked this conversation as resolved.
/// <summary>Adds a custom HTTP client instance for the Lambda bootstrap runtime API.</summary>
/// <typeparam name="T">The type of <see cref="HttpClient" /> to register.</typeparam>
/// <param name="client">The pre-configured <see cref="HttpClient" /> instance.</param>
/// <returns>The <see cref="IServiceCollection" /> for chaining.</returns>
/// <remarks>
/// Registers a keyed singleton <see cref="HttpClient" /> that will be used by the Lambda
/// bootstrap to communicate with the Lambda runtime API. This overload is useful for testing
/// scenarios where you want to inject a mock or fake HTTP client.
/// </remarks>
public IServiceCollection AddLambdaBootstrapHttpClient<T>(T client)

Check warning on line 23 in src/AwsLambda.Host/Builder/Extensions/LambdaHttpClientServiceCollectionExtensions.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make 'AddLambdaBootstrapHttpClient' a static method.

See more on https://sonarcloud.io/project/issues?id=j-d-ha_aws-lambda-host&issues=AZr0CErqFDjduF-gE86-&open=AZr0CErqFDjduF-gE86-&pullRequest=219
where T : HttpClient
{
ArgumentNullException.ThrowIfNull(services);

services.AddKeyedSingleton<HttpClient>(typeof(ILambdaBootstrapOrchestrator), client);

return services;
}

/// <summary>
/// Adds a factory for creating a custom HTTP client for the Lambda bootstrap runtime API.
/// </summary>
/// <param name="factory">
/// A factory function that creates the <see cref="HttpClient" /> instance. The function
/// receives the <see cref="IServiceProvider" /> and service key.
/// </param>
/// <returns>The <see cref="IServiceCollection" /> for chaining.</returns>
/// <remarks>
/// <para>
/// Registers a keyed singleton <see cref="HttpClient" /> factory that will be used by the
/// Lambda bootstrap to communicate with the Lambda runtime API. This overload provides
/// access to the dependency injection container, allowing you to resolve other services
/// when constructing the HTTP client.
/// </para>
/// </remarks>
public IServiceCollection AddLambdaBootstrapHttpClient(

Check warning on line 49 in src/AwsLambda.Host/Builder/Extensions/LambdaHttpClientServiceCollectionExtensions.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make 'AddLambdaBootstrapHttpClient' a static method.

See more on https://sonarcloud.io/project/issues?id=j-d-ha_aws-lambda-host&issues=AZr0CErqFDjduF-gE86_&open=AZr0CErqFDjduF-gE86_&pullRequest=219
Func<IServiceProvider, object?, HttpClient> factory
)
{
ArgumentNullException.ThrowIfNull(services);

services.AddKeyedSingleton<HttpClient>(typeof(ILambdaBootstrapOrchestrator), factory);

return services;
}

/// <summary>
/// Attempts to add a custom HTTP client instance for the Lambda bootstrap runtime API if one is
/// not already registered.
/// </summary>
/// <typeparam name="T">The type of <see cref="HttpClient" /> to register.</typeparam>
/// <param name="client">The pre-configured <see cref="HttpClient" /> instance.</param>
/// <remarks>
/// Registers a keyed singleton <see cref="HttpClient" /> that will be used by the Lambda
/// bootstrap to communicate with the Lambda runtime API, but only if a keyed HTTP client has
/// not already been registered. This overload is useful for testing scenarios where you want
/// to inject a mock or fake HTTP client without overwriting user-supplied configurations.
/// </remarks>
public void TryAddLambdaBootstrapHttpClient<T>(T client)

Check warning on line 72 in src/AwsLambda.Host/Builder/Extensions/LambdaHttpClientServiceCollectionExtensions.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make 'TryAddLambdaBootstrapHttpClient' a static method.

See more on https://sonarcloud.io/project/issues?id=j-d-ha_aws-lambda-host&issues=AZr0CErqFDjduF-gE87B&open=AZr0CErqFDjduF-gE87B&pullRequest=219
where T : HttpClient
{
ArgumentNullException.ThrowIfNull(services);

services.TryAddKeyedSingleton<HttpClient>(typeof(ILambdaBootstrapOrchestrator), client);
}

/// <summary>
/// Attempts to add a factory for creating a custom HTTP client for the Lambda bootstrap runtime
/// API if one is not already registered.
/// </summary>
/// <param name="factory">
/// A factory function that creates the <see cref="HttpClient" /> instance. The function
/// receives the <see cref="IServiceProvider" /> and service key.
/// </param>
/// <remarks>
/// <para>
/// Registers a keyed singleton <see cref="HttpClient" /> factory that will be used by the
/// Lambda bootstrap to communicate with the Lambda runtime API, but only if a keyed HTTP
/// client has not already been registered.
/// </para>
/// </remarks>
public void TryAddLambdaBootstrapHttpClient(

Check warning on line 95 in src/AwsLambda.Host/Builder/Extensions/LambdaHttpClientServiceCollectionExtensions.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make 'TryAddLambdaBootstrapHttpClient' a static method.

See more on https://sonarcloud.io/project/issues?id=j-d-ha_aws-lambda-host&issues=AZr0CErqFDjduF-gE87A&open=AZr0CErqFDjduF-gE87A&pullRequest=219
Func<IServiceProvider, object?, HttpClient> factory
)
{
ArgumentNullException.ThrowIfNull(services);

services.TryAddKeyedSingleton<HttpClient>(
typeof(ILambdaBootstrapOrchestrator),
factory
);
}
}
}
13 changes: 11 additions & 2 deletions src/AwsLambda.Host/Core/Options/LambdaHostOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Amazon.Lambda.RuntimeSupport.Bootstrap;
using AwsLambda.Host.Builder.Extensions;

namespace AwsLambda.Host.Options;

Expand All @@ -8,9 +9,17 @@
/// <summary>Gets or sets an optional custom HTTP client for the Lambda bootstrap.</summary>
/// <remarks>
/// When null, the bootstrap will create its own HTTP client for communicating with the Lambda
/// runtime API. Provide a custom client to control connection pooling, timeout settings, or other
/// HTTP-level behaviors.
/// runtime API. This property will be overridden by keyed service registrations from
/// <see cref="LambdaHttpClientServiceCollectionExtensions.AddLambdaBootstrapHttpClient" /> or
/// <see cref="LambdaHttpClientServiceCollectionExtensions.TryAddLambdaBootstrapHttpClient" />
/// extension methods.
/// </remarks>
[Obsolete(
"This property will be removed in version 2.0.0. Use "
+ "AddLambdaBootstrapHttpClient() or TryAddLambdaBootstrapHttpClient() extension methods "
+ "instead.",
false
)]

Check warning on line 22 in src/AwsLambda.Host/Core/Options/LambdaHostOptions.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=j-d-ha_aws-lambda-host&issues=AZr0CEojFDjduF-gE869&open=AZr0CEojFDjduF-gE869&pullRequest=219
public HttpClient? BootstrapHttpClient { get; set; } = null;

/// <summary>Gets or sets the options for configuring the Lambda bootstrap behavior.</summary>
Expand Down
18 changes: 15 additions & 3 deletions src/AwsLambda.Host/Runtime/LambdaBootstrapAdapter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Amazon.Lambda.Core;
using Amazon.Lambda.RuntimeSupport;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace AwsLambda.Host.Runtime;
Expand All @@ -10,12 +11,23 @@
/// </summary>
internal sealed class LambdaBootstrapAdapter : ILambdaBootstrapOrchestrator
{
private readonly HttpClient? _httpClient;
private readonly LambdaHostOptions _settings;

public LambdaBootstrapAdapter(IOptions<LambdaHostOptions> lambdaHostSettings)
public LambdaBootstrapAdapter(
IOptions<LambdaHostOptions> lambdaHostSettings,
[FromKeyedServices(typeof(ILambdaBootstrapOrchestrator))] HttpClient? httpClient = null
)
{
ArgumentNullException.ThrowIfNull(lambdaHostSettings);

// TODO: Remove this check once ILambdaBootstrapOrchestrator.BootstrapHttpClient is removed.

Check warning on line 24 in src/AwsLambda.Host/Runtime/LambdaBootstrapAdapter.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this 'TODO' comment.

See more on https://sonarcloud.io/project/issues?id=j-d-ha_aws-lambda-host&issues=AZr0CEr1FDjduF-gE87C&open=AZr0CEr1FDjduF-gE87C&pullRequest=219
// until ILambdaBootstrapOrchestrator.BootstrapHttpClient is removed, we need to check for
// it if the keyed service is NOT present.
#pragma warning disable CS0618 // Type or member is obsolete
_httpClient = httpClient ?? lambdaHostSettings.Value.BootstrapHttpClient;
#pragma warning restore CS0618 // Type or member is obsolete

_settings = lambdaHostSettings.Value;
}

Expand All @@ -32,10 +44,10 @@
using var wrappedHandler = HandlerWrapper.GetHandlerWrapper(handler);

// Create the bootstrap based on configuration.
using var bootstrap = _settings.BootstrapHttpClient is null
using var bootstrap = _httpClient is null
? new LambdaBootstrap(wrappedHandler, _settings.BootstrapOptions, convertedInitializer)
: new LambdaBootstrap(
_settings.BootstrapHttpClient,
_httpClient,
wrappedHandler,
_settings.BootstrapOptions,
convertedInitializer
Expand Down
Loading
Loading