aws-lambda-dotnet icon indicating copy to clipboard operation
aws-lambda-dotnet copied to clipboard

The statusDescription header must contain the status code and reason phrase, separated by a single space -- ALB returning 502 from Lambda

Open Kralizek opened this issue 6 years ago • 12 comments

I've created a Lambda that check on a DynamoDB table the existence of a record matching host and request path and, if found, returns a redirect to the matching URL.

My Lambda returns this response but the ALB returns 502.

{
    "statusCode": 301,
    "statusDescription": null,
    "headers": {
        "Location": "https://www.my-target.co.uk/"
    },
    "multiValueHeaders": null,
    "body": "Redirecting to https://www.my-target.co.uk/",
    "isBase64Encoded": false
}

This is the log I find in CloudWatch for the Lambda function

START RequestId: 8b5a28f2-c56d-4418-a7b9-66ebe0ba2470 Version: $LATEST
[Information] EMG.ApplicationLoadBalancerRequestHandler: Received: GET / 
[Information] EMG.ApplicationLoadBalancerRequestHandler: Processing: my-test.net / 
[Information] EMG.RedirectManagers.RedirectTableRedirectManager: Fetching item: my-test.net / from table redirect-table 
[Information] EMG.ApplicationLoadBalancerRequestHandler: Found: https://www.target.co.uk/ Permanent 
END RequestId: 8b5a28f2-c56d-4418-a7b9-66ebe0ba2470
REPORT RequestId: 8b5a28f2-c56d-4418-a7b9-66ebe0ba2470	Duration: 69.59 ms	Billed Duration: 100 ms Memory Size: 128 MB	Max Memory Used: 39 MB	

This is the response I get

HTTP/1.1 502
status: 502
Server: awselb/2.0
Date: Thu, 15 Aug 2019 19:13:58 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
<html>
 <head><title>502 Bad Gateway</title></head>
 <body bgcolor="white">
 <center><h1>502 Bad Gateway</h1></center>
 </body>
 </html>

I couldn't find anything saying we can't return non-200 responses from Lambda, so I really have no idea...

Kralizek avatar Aug 15 '19 19:08 Kralizek

Hi @Kralizek, this probably isn't an issue with the .NET SDK, so I'm going to close out this issue. Please try reading some of our ALB troubleshooting documentation, asking a question on AWS Forums or Stack Overflow, or opening a Premium Support case.

klaytaybai avatar Aug 19 '19 18:08 klaytaybai

Thanks @klaytaybai

For future desperate souls, you can find the same question on StackOverflow here: https://stackoverflow.com/questions/57562352/aws-alb-returning-502-from-lambda-instead-of-custom-http-status

Kralizek avatar Aug 19 '19 18:08 Kralizek

Also, in the documentation it's clearly state that the statusDescription cannot be null and needs to contain the status and the reason separated by a space.

Here is the relevant documentation (emphasis mine): https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#respond-to-load-balancer

The response from your Lambda function must include the Base64 encoding status, status code, status description, and headers. You can omit the body. The statusDescription header must contain the status code and reason phrase, separated by a single space.

Kralizek avatar Aug 19 '19 19:08 Kralizek

Should we change the StatusDescription property in ApplicationLoadBalancerResponse to compute a status description if it hasn't been set but StatusCode has been set?

normj avatar Aug 20 '19 19:08 normj

That would be helpful, but where would you get the reason phrase from? I used ReasonPhrases.GetReasonPhrase(int) but I am not sure taking a dependency on Microsoft.AspNetCore.WebUtilities is worth it

Kralizek avatar Aug 20 '19 21:08 Kralizek

I was thinking of something like this:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(new ApplicationLoadBalancerResponse {StatusCode = 200 }.StatusDescription);
        Console.WriteLine(new ApplicationLoadBalancerResponse { StatusCode = 404 }.StatusDescription);
        Console.WriteLine(new ApplicationLoadBalancerResponse { StatusCode = 99999 }.StatusDescription);
    }
}


public class ApplicationLoadBalancerResponse
{
    public int StatusCode { get; set; }

    string _statusDescription = null;
    public string StatusDescription
    {
        get
        { 
            if(this._statusDescription == null && this.StatusCode != 0)
            {
                var statusName = (System.Net.HttpStatusCode)this.StatusCode;
                return $"{this.StatusCode} {statusName}";
            }

            return this._statusDescription;
        }
        set { this._statusDescription = value; }
    }
}

This results in the following:

200 OK
404 NotFound
99999 99999

normj avatar Aug 20 '19 21:08 normj

That looks pretty neat!

Kralizek avatar Aug 20 '19 22:08 Kralizek

Also... On a sidenote, would it be possible to make the dictionary containing the headers use a case insensitive comparer? While working on converting a lambda from API Gateway to ALB, I took me a while to understand why I couldn't find the "Host" header (API Gateway), then I saw that ALB returns all headers in lower case (which is pretty peculiar, since I have always seen the headers be written in Pascal casing).

Kralizek avatar Aug 20 '19 22:08 Kralizek

Reopening this as a feature request.

klaytaybai avatar Aug 20 '19 23:08 klaytaybai

Thanks @Kralizek for pointing out the SO post. I just wanted to add that that in my testing with .net core lambda behind ALB, adding a space to the StatusDescription had no effect on the outcome of the 502. I had to add a header to get it to work.

public virtual async Task<ApplicationLoadBalancerResponse> ProcessRequest(ApplicationLoadBalancerRequest request, ILambdaContext context)
        {
            Console.WriteLine("Executing function...");
            return await Task.FromResult( new ApplicationLoadBalancerResponse
            {
                StatusCode = 200,
                StatusDescription = "OK",
                Body = "all good",
                Headers = new Dictionary<string, string>
                {
                    { "x-test", "1234" }
                }
                
            });
        }

avvi00 avatar Nov 15 '19 00:11 avvi00

We have noticed this issue has not received attention in 1 year. We will close this issue for now. If you think this is in error, please feel free to comment and reopen the issue.

github-actions[bot] avatar Feb 19 '22 00:02 github-actions[bot]

@ashishdhingra are issues labeled as feature request also subject to expiration?

Kralizek avatar Feb 19 '22 00:02 Kralizek