public void TestGetIdException()
        {
            var lambdaFunction = new LambdaEntryPoint();

            var request = GetTestRequest("./SampleRequests/ValuesController-V2-GetNegativeId.json");
            var context = new TestLambdaContext
            {
                FunctionName       = "ServerlessFunction",
                InvokedFunctionArn = "arn:aws:lambda:us-east-2:123456789012:function:my-function:1",
            };

            APIGatewayHttpApiV2ProxyResponse response = null;
            var spans = BackendMock.CollectSpans(
                async() => response = await lambdaFunction.FunctionHandlerAsync(request, context));

            // Check response.
            Assert.Equal(500, response.StatusCode);

            // Check trace.
            Assert.Single(spans);

            var span = spans.First();

            Assert.Equal("api/Values/{id}", span.Name);
            Assert.True(span.Tags.TryGetValue("error", out var errorValue));
            Assert.Equal("true", errorValue);
            Assert.True(span.Tags.TryGetValue("sfx.error.kind", out var actualErrorKind));
            Assert.Equal(typeof(ArgumentOutOfRangeException).FullName, actualErrorKind);
        }
        public void TestGet()
        {
            var lambdaFunction = new LambdaEntryPoint();

            var request = GetTestRequest("./SampleRequests/ValuesController-V2-Get.json");
            var context = new TestLambdaContext
            {
                FunctionName       = "ServerlessFunction",
                InvokedFunctionArn = "arn:aws:lambda:us-east-2:123456789012:function:my-function:1",
            };

            APIGatewayHttpApiV2ProxyResponse response = null;
            var spans = BackendMock.CollectSpans(
                async() => response = await lambdaFunction.FunctionHandlerAsync(request, context));

            // Check response.
            Assert.Equal(200, response.StatusCode);
            Assert.Equal("[\"value1\",\"value2\"]", response.Body);
            Assert.True(response.Headers.ContainsKey("Content-Type"));
            Assert.Equal("application/json; charset=utf-8", response.Headers["Content-Type"]);

            // Check trace.
            Assert.Single(spans);
            var span = spans.First();

            Assert.Equal("api/Values", span.Name);
            Assert.True(span.Tags.TryGetValue("span.kind", out var spanKind));
            Assert.Equal("server", spanKind);
            Assert.True(span.Tags.TryGetValue("http.method", out var httpMethod));
            Assert.Equal("GET", httpMethod);
        }
        public async Task<APIGatewayHttpApiV2ProxyResponse> InvokeAPIGatewayHttpApiV2ProxyAsync(
            Func<APIGatewayHttpApiV2ProxyRequest, ILambdaContext, Task<APIGatewayHttpApiV2ProxyResponse>> asyncHandler,
            APIGatewayHttpApiV2ProxyRequest request,
            ILambdaContext context,
            string operationName = null,
            IDictionary<string, string> tags = null)
        {
            using (var tracker = new TelemetryTracker(context, operationName, tags, request.Headers))
            {
                try
                {
                    APIGatewayHttpApiV2ProxyResponse apiGatewayProxyResponse = await asyncHandler(request, context);
                    if (!apiGatewayProxyResponse.IsSuccessStatusCode())
                    {
                        tracker.SetErrorCounter();

                        // Preserve the legacy logging.
                        LambdaLogger.Log($"[ERR] Invoking lambda function. Http status code: {apiGatewayProxyResponse.StatusCode}. Response body: {apiGatewayProxyResponse.Body}{Environment.NewLine}");
                    }

                    return apiGatewayProxyResponse;
                }
                catch (Exception e)
                {
                    tracker.SetException(e);
                    throw;
                }
            }
        }
Example #4
0
        /// <summary>
        /// A Lambda function that returns the blog identified by blogId
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task <APIGatewayHttpApiV2ProxyResponse> GetBlogAsync(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)
        {
            string blogId = null;

            if (request.PathParameters != null && request.PathParameters.ContainsKey(ID_QUERY_STRING_NAME))
            {
                blogId = request.PathParameters[ID_QUERY_STRING_NAME];
            }
            else if (request.QueryStringParameters != null && request.QueryStringParameters.ContainsKey(ID_QUERY_STRING_NAME))
            {
                blogId = request.QueryStringParameters[ID_QUERY_STRING_NAME];
            }

            if (string.IsNullOrEmpty(blogId))
            {
                return(new APIGatewayHttpApiV2ProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.BadRequest,
                    Body = $"Missing required parameter {ID_QUERY_STRING_NAME}"
                });
            }

            context.Logger.LogLine($"Getting the blog {blogId}");

            var response = new APIGatewayHttpApiV2ProxyResponse
            {
                StatusCode = (int)HttpStatusCode.OK,
                Body       = $"Fetched blog {blogId}",
                Headers    = new Dictionary <string, string> {
                    { "Content-Type", "application/json" }
                }
            };

            return(response);
        }
        public void TestGetId()
        {
            var lambdaFunction = new LambdaEntryPoint();

            var request = GetTestRequest("./SampleRequests/ValuesController-V2-GetId.json");
            var context = new TestLambdaContext
            {
                FunctionName       = "ServerlessFunction",
                InvokedFunctionArn = "arn:aws:lambda:us-east-2:123456789012:function:my-function:1",
            };

            APIGatewayHttpApiV2ProxyResponse response = null;
            IImmutableList <IMockSpan>       spans    = null;
            const string propagatedTraceId            = "0123456789abcef0";
            const string parentSpanId = "0123456789abcef0";

            try
            {
                TelemetryConfiguration.ContextPropagationEnabled = true;
                request.Headers = new Dictionary <string, string>
                {
                    { HttpHeaderNames.B3TraceId, propagatedTraceId },
                    { HttpHeaderNames.B3SpanId, parentSpanId },
                    { HttpHeaderNames.B3Sampled, "1" },
                };

                spans = BackendMock.CollectSpans(
                    async() => response = await lambdaFunction.FunctionHandlerAsync(request, context));
            }
            finally
            {
                TelemetryConfiguration.ContextPropagationEnabled = false;
            }

            // Check response.
            Assert.Equal(200, response.StatusCode);
            Assert.Equal("value_56", response.Body);
            Assert.True(response.Headers.ContainsKey("Content-Type"));
            Assert.Equal("text/plain; charset=utf-8", response.Headers["Content-Type"]);

            // Check trace.
            Assert.Single(spans);
            var span = spans.First();

            Assert.Equal("api/Values/{id}", span.Name);
            Assert.True(span.Tags.TryGetValue("span.kind", out var spanKind));
            Assert.Equal("server", spanKind);
            Assert.True(span.Tags.TryGetValue("http.method", out var httpMethod));
            Assert.Equal("GET", httpMethod);

            // Check context propagation.
            Assert.True(span.ParentId.HasValue);
            Assert.Equal(propagatedTraceId, span.TraceId.ToString("x16"));
            Assert.Equal(parentSpanId, span.ParentId.Value.ToString("x16"));
        }
        public async Task <APIGatewayHttpApiV2ProxyResponse> Handle(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)
        {
            var inner  = JsonConvert.DeserializeObject <S3Event>(request.Body);
            var result = await FunctionHandler(inner, context);

            var response = new APIGatewayHttpApiV2ProxyResponse
            {
                Body = JsonConvert.SerializeObject(result)
            };

            return(response);
        }
        public async Task <APIGatewayHttpApiV2ProxyResponse> Handle(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)
        {
            var json   = UTF8Encoding.UTF8.GetBytes(request.Body);
            var inner  = JsonSerializer.Deserialize <S3Event>(json);
            var result = await FunctionHandler(inner, context);

            var response = new APIGatewayHttpApiV2ProxyResponse
            {
                Body = JsonSerializer.Serialize(result)
            };

            return(response);
        }
Example #8
0
 internal static bool IsSuccessStatusCode(this APIGatewayHttpApiV2ProxyResponse response)
 {
     return(response.StatusCode >= 200 && response.StatusCode <= 299);
 }
Example #9
0
        public async Task <APIGatewayHttpApiV2ProxyResponse> InboundParse(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)
        {
            APIGatewayHttpApiV2ProxyResponse response;

            var getParameterResponse = await _ssmClient.GetParameterAsync(new GetParameterRequest
            {
                Name           = AuthenticationKeyParameterName,
                WithDecryption = true
            });

            var authenticationKey = getParameterResponse?.Parameter?.Value;

            string authenticationKeyPresented = null;

            request.QueryStringParameters?.TryGetValue(AuthenticationQueryParameterKey, out authenticationKeyPresented);

            if (string.IsNullOrEmpty(authenticationKeyPresented) || string.IsNullOrEmpty(authenticationKey) ||
                authenticationKeyPresented != authenticationKey)
            {
                context.Logger.LogLine($"Failed to authenticate.");

                return(new APIGatewayHttpApiV2ProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.Unauthorized
                });
            }

            try
            {
                context.Logger.LogLine("Request Headers:");
                foreach (var header in request.Headers)
                {
                    context.Logger.LogLine($"{header.Key}: {header.Value}");
                }
                context.Logger.LogLine($"Request IsBase64Encoded:\n{request.IsBase64Encoded}");
                context.Logger.LogLine($"Request Body:\n{request.Body}");

                var requestBody = new MemoryStream(Convert.FromBase64String(request.Body));

                var parser       = new WebhookParser();
                var inboundEmail = parser.ParseInboundEmailWebhook(requestBody);
                context.Logger.LogLine($"InboundEmail Subject:\n{inboundEmail.Subject}");
                context.Logger.LogLine($"InboundEmail To:\n{inboundEmail.To[0].Email}");
                context.Logger.LogLine($"InboundEmail From:\n{inboundEmail.From.Email}");
                context.Logger.LogLine($"InboundEmail DKIM:\n{inboundEmail.Dkim}");
                context.Logger.LogLine($"InboundEmail SPF:\n{inboundEmail.Spf}");

                context.Logger.LogLine($"InboundEmail Envelope.From:\n{inboundEmail.Envelope.From}");

                response = new APIGatewayHttpApiV2ProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.OK,
                    Body       = "Success",
                    Headers    = new Dictionary <string, string> {
                        { "Content-Type", "text/plain" }
                    }
                };
            }
            catch (Exception ex)
            {
                var exception = ex.ToString();
                context.Logger.LogLine($"Exception occurred:\n{exception}");

                response = new APIGatewayHttpApiV2ProxyResponse
                {
                    StatusCode = (int)HttpStatusCode.OK,
                    Body       = ex.Message,
                    Headers    = new Dictionary <string, string> {
                        { "Content-Type", "text/plain" }
                    }
                };
            }

            return(response);
        }