AWS .Net Core SDK Simple Email Service Suppression List Not Working - amazon-web-services

I am trying to retrieve the SES account-level suppression list using AWS SDK in .Net Core:
Below is my code:
public class SimpleEmailServiceUtility : ISimpleEmailServiceUtility
{
private readonly IAmazonSimpleEmailServiceV2 _client;
public SimpleEmailServiceUtility(IAmazonSimpleEmailServiceV2 client)
{
_client = client;
}
public async Task<ListSuppressedDestinationsResponse> GetSuppressionList()
{
ListSuppressedDestinationsRequest request = new ListSuppressedDestinationsRequest();
request.PageSize = 10;
ListSuppressedDestinationsResponse response = new ListSuppressedDestinationsResponse();
try
{
response = await _client.ListSuppressedDestinationsAsync(request);
}
catch (Exception ex)
{
Console.WriteLine("ListSuppressedDestinationsAsync failed with exception: " + ex.Message);
}
return response;
}
}
But it doesn't seem to be working. The request takes too long and then returns empty response or below error if I remove try/catch:
An unhandled exception occurred while processing the request.
TaskCanceledException: A task was canceled.
System.Threading.Tasks.TaskCompletionSourceWithCancellation<T>.WaitWithCancellationAsync(CancellationToken cancellationToken)
TimeoutException: A task was canceled.
Amazon.Runtime.HttpWebRequestMessage.GetResponseAsync(CancellationToken cancellationToken)
Can anyone please guide if I am missing something?
Thank you!

I have tested your code and everything works correctly.
using Amazon;
using Amazon.SimpleEmailV2;
using Amazon.SimpleEmailV2.Model;
internal class Program
{
private async static Task Main(string[] args)
{
var client = new AmazonSimpleEmailServiceV2Client("accessKeyId", "secrectAccessKey", RegionEndpoint.USEast1);
var utility = new SimpleEmailServiceUtility(client);
var result = await utility.GetSuppressionList();
}
}
<PackageReference Include="AWSSDK.SimpleEmailV2" Version="3.7.1.127" />
Things that you can check:
Try again, maybe it was a temporary problem.
Try with the latest version that I am using(if not already)
How far are you from the region that you try to get the list? Try making the same request from an EC2 instance in that region.

Finally found the issue, I was using awsConfig.DefaultClientConfig.UseHttp = true;' in startup` which was causing the issue. Removing it fixed the issue and everything seems to be working fine now.

Related

Data is not reaching to the websocket clients in AWS API Gateway websocket

I have created an lambda function to which I am not able to send the data to the web socket clients. However there is NO error is coming.
Till yesterday code was working. Dont know what happend now it stopped working.
public string FunctionHandler(string input, ILambdaContext context)
{
try
{
string SK = "xxxxxx";
string AK = "xxxx";
var stream = new MemoryStream(UTF8Encoding.UTF8.GetBytes(input));
var apiClient = new AmazonApiGatewayManagementApiClient(AK,SK,new AmazonApiGatewayManagementApiConfig
{ ServiceURL = $"https://xxxxxx.execute-api.us-east-1.amazonaws.com/Test" });
apiClient.PostToConnectionAsync(new Amazon.ApiGatewayManagementApi.Model.PostToConnectionRequest
{
ConnectionId = "​fdCqPfd0oAMCJmg=",
Data = stream
});
return input.ToUpper();
}
catch(Exception ex)
{
return ex.ToString();
}
}
I gather you're using .NET AmazonApiGatewayManagementApiClient. You're missing the await keyword for apiClient.PostToConnectionAsync():
await apiClient.PostToConnectionAsync(...);
Otherwise you're calling PostToConnectionAsync() without waiting for completion and your Lambda might complete and exit before your request is run and you'll never know about it. (See asynchronous concepts for details)
Alternatively, don't use async method:
apiClient.PostToConnection(...);

Why won't unit tests connect to a websocket

UPDATE: I've uploaded a repo - https://github.com/mrpmorris/CannotIntegrationTestWebApp/blob/master/TestProject1/UnitTest1.cs
I have a web server that serves both HTTPS and WebSocket requests. When I run the app I am able to connect and make requests from postman for both HTTPS://localhost:8080 and WSS://localhost:8080/game-server
using Gambit.ApplicationLayer;
using Gambit.GameServer.Configuration;
using Gambit.GameServer.UseCases;
namespace Gambit.GameServer;
public class Program
{
public static async Task Main(string[] args)
{
WebApplication app = BuildApp(args);
await RunAppAsync(app);
}
public static WebApplication BuildApp(string[] args, Action<WebApplicationBuilder>? configure = null)
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
IServiceCollection services = builder.Services;
IConfiguration configuration = builder.Configuration;
IWebHostEnvironment environment = builder.Environment;
services.AddControllers();
services.AddLogging(opts =>
{
opts.ClearProviders();
opts.AddConfiguration(configuration.GetSection("Logging"));
opts.AddDebug();
opts.AddEventSourceLogger();
#if DEBUG
if (environment.IsDevelopment())
opts.AddConsole();
#endif
});
services.Configure<GameServerOptions>(configuration.GetSection("GameServer"));
services.AddApplicationServices(configuration);
configure?.Invoke(builder);
WebApplication app = builder.Build();
return app;
}
public static async Task RunAppAsync(WebApplication app)
{
app.MapGet("/", () => "Gambit.Server.API is running");
app.AddUserUseCases();
app.AddGameUseCases();
app.MapControllers();
app.UseWebSockets();
await app.RunAsync();
}
}
When I run my unit tests I use the same code to create and run the server (once per test run) my tests are able to make HTTPS requests but not connect via a WebSocket. When I try, I get a 404 error. I experience the same in PostMan.
static IntegrationTestsServer()
{
ConfigureMocks();
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "IntegrationTesting");
var app = Program.BuildApp(Array.Empty<string>(), builder =>
{
builder.WebHost.UseSetting("urls", "https://localhost:8080");
});
Configuration = app.Services.GetRequiredService<IConfiguration>();
GameServerOptions = app.Services.GetRequiredService<IOptions<GameServerOptions>>();
var dbContextOptions = app.Services.GetRequiredService<DbContextOptions<ApplicationDbContext>>();
using var dbContext = new ApplicationDbContext(dbContextOptions);
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();
HttpClient = new HttpClient { BaseAddress = new Uri("https://localhost:8080") };
_ = Program.RunAppAsync(app);
}
I can even perform a successful HttpClient.GetAsync("https://localhost:8080") immediately before the ClientWebSocket fails
System.Net.WebSockets.WebSocketException : The server returned status code '404' when status code '101' was expected.
Does anyone have any ideas why this might be?
Set ApplicationName in the WebApplicationOptions sent to WebApplication.CreateBuilder
WebApplication.CreateBuilder
(
new WebApplicationOptions
{
ApplicationName = typeof(Gambit.GameServer.Program).Assembly.GetName().Name // <==
}
);
Now it will be able to find your manifest file when running from a test.
See the following blog post for more of the back story on how I figured it out.
https://thefreezeteam.com/posts/StevenTCramer/2022/08/25/runwebserverintest

aws lambda function using serverless template of asp.net core

I don't have enough knowledge of aws but my company asked me to do a job which I guess is what AWS Lambda does perfectly. The requirement is I have to create a service that has an endpoint that needs to be called twice a day. The approach I followed is I created a serverless web API through visual studio and created API gateway endpoint for each endpoint. Then added a trigger through cloud watch events to run it twice a day but whenever the function is triggered I get this error.
Object reference not set to an instance of an object.: NullReferenceException
at Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction.MarshallRequest(InvokeFeatures features, APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
at Amazon.Lambda.AspNetCoreServer.AbstractAspNetCoreFunction`2.FunctionHandlerAsync(TREQUEST request, ILambdaContext lambdaContext)
at lambda_method(Closure , Stream , Stream , LambdaContextInternal )
I have the same issue and could fix it recently.
If you use Lambda with ASP.NET Core, you should have LambdaEntryPoint class to handle all the requests.
Try to override MarshallRequest method in this class, add logging and see what you have in apiGatewayRequest parameter. The code can look something like this:
protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
{
LambdaLogger.Log($"Request path: {apiGatewayRequest.Path}");
LambdaLogger.Log($"Request path parameters: {apiGatewayRequest.PathParameters}");
LambdaLogger.Log($"Request body: {apiGatewayRequest.Body}");
LambdaLogger.Log($"Request request context: {apiGatewayRequest.RequestContext}");
base.MarshallRequest(features, apiGatewayRequest, lambdaContext);
}
In my case, all these values were nulls. The reason for it was in using Amazon EventBridge for keeping Lambda online to avoid a cold start. If you also use EventBridge, try to configure the request there properly. If not, you can try to update MarshalRequest the following way:
protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
{
if(apiGatewayRequest.RequestContext == null) //Or other property
{
return;
}
base.MarshallRequest(features, apiGatewayRequest, lambdaContext);
}
A few days ago I had the same problem. Grigory Zhadko’s answer helped me a lot by knowing which method I should overwrite. LambdaEntryPoint requires for any other process to instantiate an ApiGatewayProxiRequest object manually (for example, eventBridge). The configuration I implemented to fix the problem is as follows.
protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
{
var endpoint = "my/endpoint";
if (apiGatewayRequest != null && apiGatewayRequest?.RequestContext == null)
{
apiGatewayRequest.Path = $"/{endpoint}";
apiGatewayRequest.Resource = $"/{endpoint}";
apiGatewayRequest.HttpMethod = "ANY METHOD";
apiGatewayRequest.RequestContext = new APIGatewayProxyRequest.ProxyRequestContext
{
Path = $"/path/{endpoint}", // your path request
Identity = new APIGatewayProxyRequest.RequestIdentity
{
ClientCert = new APIGatewayProxyRequest.ProxyRequestClientCert
{
Validity = new APIGatewayProxyRequest.ClientCertValidity()
}
},
ResourcePath = $"/{basePath}{eventEntpoint}",
HttpMethod = "ANY METHOD",
Authorizer = new APIGatewayCustomAuthorizerContext()
};
}
base.MarshallRequest(features, apiGatewayRequest, lambdaContext);
}

SpringBootTest - Test exception when request is invalid

I developed an API using web-flux which is working fine when I make request using POSTMAN. My code is:
Controller:
#PostMapping("/post", produces = ["application/xml"])
fun post(#Valid request: RequestData): Mono<Response> {
return Mono.just(request)
...
...
...
}
dto:
data class RequestData(
#get:NotBlank
#get:Email
val email: String = "",
)
So whenever I pass invalid email via POSTMAN, I'm catching the exception like below and its working:
#ExceptionHandler
fun bindingExceptionHandler(e: WebExchangeBindException) = "Custom Error Message"
But now when I write UT(#WebFluxTest) for this case (Invalid emaid), It failed.
#Test
fun testWhenInvalidEmail() {
// Request body
val email = "invalidemail"
val request = LinkedMultiValueMap<String, String>()
request.add("email", email)
webTestClient.post().uri("/post")
.body(BodyInserters.fromFormData(request))
.exchange()
.expectStatus().isOk
}
When I debug this, I found that my exceptionHandler not coming into picture when request coming through unit test. I'm using application/x-www-form-urlencoded content type in POST request.
Please let me know where I'm doing wrong.
I followed this question as well but didn't work.
As mentioned on another related question, this has been fixed in Spring Boot 2.1.0.
Also, you shouldn't have to build WebTestClient yourself but instead inject it in your test class (see reference documentation about that):
#RunWith(SpringRunner.class)
#WebFluxTest(MyValidationController.class)
public class MyValidationControllerTests {
#Autowired
private WebTestClient webClient;
#Test
public void testWhenInvalidEmail() {
//...
}
}

Jersey filter giving server error

I am using jersey filter.
In My code logic in AuthenticationFilter.java, if the authorization header is empty, then return the access denied error message.
First time I am hitting the application through rest client tool using the URL without attaching the header
http://localhost:8080/JerseyDemos2/rest/pocservice
Get the status 401 with error message "you cannot access this resource". This is right.
When i tried to hit second time thorugh rest client tool, and server return the exception message.
I deployed my application in tomcat 7.x both windows and linux
Why it give the error when we hit the second time.
How to resolve this
#Provider
public class AuthenticationFilter implements javax.ws.rs.container.ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
private static final String AUTHORIZATION_PROPERTY = "Authorization";
private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource").build();
#Override
public void filter(ContainerRequestContext requestContext) {
// Get request headers
final MultivaluedMap<String, String> headers = requestContext.getHeaders();
// Fetch authorization header
final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
// If no authorization information present; block access
if (authorization == null || authorization.isEmpty()) {
requestContext.abortWith(ACCESS_DENIED);
return;
}
}
} }
Error message:
Dec 19, 2016 6:26:18 PM org.glassfish.jersey.server.ServerRuntime$Responder writeResponse
SEVERE: An I/O error has occurred while writing a response message entity to the container output stream.
java.lang.IllegalStateException: The output stream has already been closed.
at org.glassfish.jersey.message.internal.CommittingOutputStream.setStreamProvider(CommittingOutputStream.java:147)
at org.glassfish.jersey.message.internal.OutboundMessageContext.setStreamProvider(OutboundMessageContext.java:803)
......
Please help me
Thanks in advance.
I Removed static variable
private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource").build();
and i declared local variable. now its working fine.
#Provider
public class AuthenticationFilter implements javax.ws.rs.container.ContainerRequestFilter {
#Context
private ResourceInfo resourceInfo;
private static final String AUTHORIZATION_PROPERTY = "Authorization";
#Override
public void filter(ContainerRequestContext requestContext) {
Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("You cannot access this resource").build();
// Get request headers
final MultivaluedMap<String, String> headers = requestContext.getHeaders();
// Fetch authorization header
final List<String> authorization = headers.get(AUTHORIZATION_PROPERTY);
// If no authorization information present; block access
if (authorization == null || authorization.isEmpty()) {
requestContext.abortWith(ACCESS_DENIED);
return;
}
}
} }
You're trying to write in a response that was written before. The full log shows where is it happening. Upload the log and the code where the httpresponse is used/modified.