5

I'm using CDK typescript lambda stack, connected to an API Gateway. Everything works just fine when I'm sending the following response:

const res = await request<ResponseModel>(req);
return {
    statusCode: res.status,
    headers: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': true
    },
    body: JSON.stringify(res.data)
};

However, I've tried to set the headers with a common const, and the result is a failure:

// common-headers.ts
export const CommonResponseHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Credentials': true
};

//function.ts
import { CommonResponseHeaders } from '../../common/common-headers';

const res = await request<ResponseModel>(req);
return {
    statusCode: res.status,
    headers: CommonResponseHeaders,
    body: JSON.stringify(res.data)
};

//stack.ts
const function = {
    name: 'myFunction',
    runtime: Runtime.NODEJS_14_X,
    entry: path.join(__dirname, './function.ts'),
    vpcSubnets: {
      subnetType: SubnetType.PRIVATE_WITH_EGRESS
    },
    handler: 'handler',
    environment: {
      ...SomeDefaultVariables
    }
  }
const lambda = new NodejsFunction(this, function.name, function);
const functionUrl = lambda.addFunctionUrl({
authType: FunctionUrlAuthType.NONE,
cors: {
  allowedOrigins: ['*'],
}
});
new CfnOutput(this, `${function.name}-FunctionUrl`, {
value: functionUrl.url,
});

Invalid lambda response received: Invalid API Gateway Response Keys: {'trace', 'errorType', 'errorMessage'} in {'errorType': 'TypeError', 'errorMessage': "Cannot read property 'trim' of undefined", 'trace': ["TypeError: Cannot read property 'trim' of undefined", ' at Object. (/var/task/index.js:10924:40)', ' at Module._compile (internal/modules/cjs/loader.js:1085:14)', ' at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)', ' at Module.load (internal/modules/cjs/loader.js:950:32)', ' at Function.Module._load (internal/modules/cjs/loader.js:790:12)', '
at Module.require (internal/modules/cjs/loader.js:974:19)', ' at require (internal/modules/cjs/helpers.js:101:18)', ' at _tryRequireFile (/var/runtime/UserFunction.js:72:32)', ' at _tryRequire (/var/runtime/UserFunction.js:160:20)', ' at _loadUserApp (/var/runtime/UserFunction.js:219:12)']}

Help would be much appreciated!

noamyg
  • 2,747
  • 1
  • 23
  • 44
  • Is `common-headers` bundled properly in the Lambda code artefact? What construct are you using for the Lambda function resource? – fedonev Jan 19 '23 at 08:44
  • @fedonev I'm having trouble answering your questions so I guess that I miss some basic understandings of how the CDK really works. I'm using `CfnOutput` construct. How would I bundle my file into the lambda? I thought that importing it would be enough (just as I'm importing modules such as axios) – noamyg Jan 19 '23 at 11:29
  • No worries, let me rephrase: Q1: Do you see `common-headers.js` bundled in the Lambda function code? (hypothesis: no) Q2: How are you defining your Lambda Function? (please add some minimal CDK code to the question) – fedonev Jan 19 '23 at 15:20
  • @fedonev I don't see the `common-headers.js` file but the code itself gets bundeled into `index.js`. I'll update my question – noamyg Jan 19 '23 at 15:43
  • 1
    I don't see anything wrong in your setup. I am all out of ideas, sorry. – fedonev Jan 19 '23 at 16:53
  • What happens if you removed the dot '.' in this line entry: path.join(__dirname, './function.ts'), ==>'/function.ts' – Mahmoud Nasr Jan 22 '23 at 15:20
  • @MahmoudNasr nothing changed, same error – noamyg Jan 23 '23 at 02:51
  • make sure the file path is right such as ../function.ts check the file level, these combinations – Mahmoud Nasr Jan 23 '23 at 10:34
  • Wouldn't the deployment fail as the file path is incorrect...? – noamyg Jan 23 '23 at 15:16
  • Did you follow the trace? What code do you see at `/var/task/index.js:10924:40`? – smcjones Jan 27 '23 at 15:59
  • Try this: import { CommonResponseHeaders } from '../../common/common-headers.js'; – Cloudkollektiv Jan 28 '23 at 03:13

2 Answers2

0

There is a mismatch between the headers your code returns and what API Gateway expects. Looking at your code example, if your response succeeds, it returns the correct headers. According to the AWS documentation, the Lambda function must return output of the following format:

{
    statusCode: "...",            // a valid HTTP status code
    headers: { 
        custom-header: "..."      // any API-specific custom header
    },
    body: "...",                  // a JSON string.
    isBase64Encoded:  true|false  // for binary support
}

So something else in your project is causing this error, and this error is not handled properly. If you encounter an error, you should return a 4xx or 5xx status code in the format described above. However, since your example is pretty small, I suppose this will not throw any errors. It is probably caused by the CDK framework in which your code is loaded. Specifically, I would look at the following things:

  1. There is a related issue about AWS amplify, where someone misspelled approot, where it should have been appRoot. He got exactly the same error complaining about the trim function.

  2. You must configure your TypeScript transpilation settings to match the Node.js runtime that you plan to use. Check out this documentation from AWS for more information on runtimes.

  3. When using NodeJS 14.x, you should double-check if your imports match the requirements for that specific version. A mistake is easily made when copying code from somewhere else. I suggest you carefully read this post, it describes that in your case local files should be imported as follows (although that might seem weird):

     // Actual file is ../../common/common-headers.ts
     import { CommonResponseHeaders } from '../../common/common-headers.js';
    
Cloudkollektiv
  • 11,852
  • 3
  • 44
  • 71
0

It's causing issue because it couldn't able to detect your imports properly.

Did you correctly imported common-headers.ts file so your CommonResponseHeaders?

You should try to specify paths in another file named config.json where you could do something like this:

Just make sure you add the common-headers.ts file path in include.

{
    "compilerOptions": {
        ...
    },
    "include": [
        "./src/**/*",
        "./common/**/*"
    ]
}

Now try to deploy using CDK, this should include your common-headers.ts properly and will fix your issue.

Note: Still not working? Maybe check your import statement and see if you correctly importing CommonResponseHeaders from common-headers.ts file or not

Myth
  • 338
  • 7
  • Thanks @Myth, that change didn't work. Regarding the `import` note, I'm also importing other stuff that work as expected so I don't think this is an import statement issue. – noamyg Jan 29 '23 at 18:46
  • Yes it is probably the node.js runtime version of the lambda, which doesn’t support the import, that is why I proposed to check all this. But it is difficult to figure this out without having all those details. Later versions of node.js and transpiler support more/different import options. The lambda only runs under version node.js 14. – Cloudkollektiv Jan 29 '23 at 18:49
  • So again, it might seem to work locally. It breaks when running in a lambda. – Cloudkollektiv Jan 29 '23 at 18:53
  • Hmm I think then your CommonResponseHeaders is not able to bundle properly with lambda but I'm not sure, maybe try to see logs of lambda func or print the variable CommonResponseHeaders before returning so can you can make sure it's an object and have expected values once. Other then this Idk bro, Sorry – Myth Jan 30 '23 at 05:26