You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复AWS Lambda函数中的'TypeError: Cannot read property 'origin' of undefined'错误

问题

测试AWS Lambda插入答案功能时,收到如下错误:

"errorType": "TypeError",
"errorMessage": "Cannot read property 'origin' of undefined",
"trace": [
  "TypeError: Cannot read property 'origin' of undefined",
  "    at responseHeaders (/var/task/index.js:32:26)",
  "    at /var/task/index.js:124:22",
  "    at processTicksAndRejections (internal/process/task_queues.js:95:5)"
]

相关Lambda代码如下:

/**********************************************************************
 *  Upsert Answer item into table
 **********************************************************************/

/* POST test
  {
    "resource": "/",
    "path": "/",
    "httpMethod": "POST",
    "body": "{\"answer\":\"This is my super important answer\",\"questionSlug\":\"this-is-my-super-important-answer\"}"
  }

  PUT test - make sure to change the ID to one in your database before running or this method will create a new record
  {
    "resource": "/",
    "path": "/",
    "httpMethod": "PUT",
    "body": "{\"answer\":\"This is my super important answer\",\"negativeVotes\":0,\"positiveVotes\":1,\"id\":\"5ec9957e3f64b70004e7599e\"}"
  }
*/

// we need access to the AWS SDK
var AWS = require("aws-sdk");

// we need uuid to generate unique ids
const { v4: uuidv4 } = require("uuid");

//  we need access to DynamoDB and choose the DocumentClient model
var docClient = new AWS.DynamoDB.DocumentClient();

const responseHeaders = (headers) => {
  const origin = headers.origin || headers.Origin;

  return {
    // HTTP headers to pass back to the client
    "Content-Type": "application/json",
    // the next headers support CORS
    "X-Requested-With": "*",
    "Access-Control-Allow-Headers":
      "Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with",
    "Access-Control-Allow-Origin": origin,
    "Access-Control-Allow-Methods": "OPTIONS,*",
    Vary: "Origin", // for proxies
    // the "has-cors" library used by the Angular application wants this set
    "Access-Control-Allow-Credentials": "true",
  };
};

exports.handler = async (event) => {
  // get the HTTP Method used
  var httpMethod = event.httpMethod;
  // get the HTTP body sent
  var payload = JSON.parse(event.body);

  // time to prepare the upsert
  const paramQuery = async () => {
    // define our query
    let params = {
      TableName: "Answer",
      Key: { id: "" },
      UpdateExpression: "set #qi = :qi, #a = :a, #nv = :nv, #pv = :pv",
      ExpressionAttributeNames: {
        // define the attributes used in the update expression
        "#qi": "questionId",
        "#a": "answer",
        "#nv": "negativeVotes",
        "#pv": "positiveVotes",
      },
      ExpressionAttributeValues: {
        // set default values
        ":qi": "",
        ":a": "",
        ":nv": 0,
        ":pv": 0,
      },
      // this tells DynamoDB to return the new records with all fields, not just the changed ones
      ReturnValues: "ALL_NEW",
    };

    // these three fields can be set during create or update
    //  set the answer if there is one
    if (payload.answer && payload.answer.trim())
      params.ExpressionAttributeValues[":a"] = payload.answer;

    //  set the category slug if there is one
    if (payload.questionId && payload.questionId.trim())
      params.ExpressionAttributeValues[":qi"] = payload.questionId;

    if (httpMethod == "PUT") {
      // PUTs are updates but the ID is passed as a path paremeter
      // lets get the path parameters
      let pathParameters = event.pathParameters;

      //  set the unique key of the item to be modified
      params.Key.id = pathParameters.id;

      // these two values are only changed - they are always defaulted during create
      //  set the negativeVotes
      params.ExpressionAttributeValues[":nv"] = payload.negativeVotes;

      //  set the positiveVotes
      params.ExpressionAttributeValues[":pv"] = payload.positiveVotes;
    } else {
      // POSTs are inserts
      // create and set the unique key. its a uuid without the '-'
      var id = uuidv4().replace(/\-/g, "");
      params.Key.id = id;
    }

    // uncomment the next line to see the parameters as sent to DynamoDB
    //console.log(JSON.stringify(params));

    // we create a promise to wrap the async DynamoDB execution
    return new Promise((resolve, reject) => {
      var queryParams = docClient.update(params).promise();
      queryParams
        .then(function (data) {
          resolve({
            statusCode: 200,
            body: JSON.stringify(data),
            // HTTP headers to pass back to the client
            headers: responseHeaders(event.headers),
          });
        })
        .catch(function (err) {
          reject(err);
        });
    });
  };
  // we await our promise here and return the result (see the resolve above)
  return await paramQuery();
};

尝试给origin添加引号后,错误依然存在。

原因与解决方案

错误原因

错误出在responseHeaders函数的const origin = headers.origin || headers.Origin;这一行——当调用Lambda的event.headers为undefined时(比如在Lambda控制台测试时未传入headers,或某些调用场景下请求未携带headers),直接访问headers.origin就会触发Cannot read property 'origin' of undefined的类型错误。

解决方案

修改responseHeaders函数,增加对headers的空值判断,并给origin设置默认值(比如*,允许所有跨域请求),避免空指针异常:

const responseHeaders = (headers) => {
  // 处理headers为空的情况,默认赋值为空对象
  headers = headers || {};
  // 优先取origin/Origin,不存在则用*兜底
  const origin = headers.origin || headers.Origin || '*';

  return {
    "Content-Type": "application/json",
    "X-Requested-With": "*",
    "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with",
    "Access-Control-Allow-Origin": origin,
    "Access-Control-Allow-Methods": "OPTIONS,*",
    Vary: "Origin",
    "Access-Control-Allow-Credentials": "true",
  };
};

如果你的Node.js版本支持ES2020+,也可以用可选链操作符简化写法:

const origin = headers?.origin || headers?.Origin || '*';

另外,在Lambda控制台测试时,建议在测试事件中补充headers字段,模拟真实请求场景:

{
  "resource": "/",
  "path": "/",
  "httpMethod": "POST",
  "headers": {
    "origin": "http://localhost:3000"
  },
  "body": "{\"answer\":\"This is my super important answer\",\"questionSlug\":\"this-is-my-super-important-answer\"}"
}

内容的提问来源于stack exchange,提问作者ShadowKnight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 13:09:56