Amazon web services Cloudfront在重定向时抛出403

Amazon web services Cloudfront在重定向时抛出403,amazon-web-services,redirect,amazon-dynamodb,amazon-cloudfront,aws-lambda-edge,Amazon Web Services,Redirect,Amazon Dynamodb,Amazon Cloudfront,Aws Lambda Edge,我有一个Lambda边缘连接到应该处理重定向的originrequest事件。代码非常简单,它检查请求的URL是否在DynamoDB表中,如果在DynamoDB表中,则返回带有重定向URL的301响应。 这是我的Lambda边缘代码 const aws = require("aws-sdk"); const dynamoDB = new aws.DynamoDB.DocumentClient(); exports.handler = async (event, context, callback

我有一个Lambda边缘连接到应该处理重定向的originrequest事件。代码非常简单,它检查请求的URL是否在DynamoDB表中,如果在DynamoDB表中,则返回带有重定向URL的301响应。 这是我的Lambda边缘代码

const aws = require("aws-sdk");
const dynamoDB = new aws.DynamoDB.DocumentClient();
exports.handler = async (event, context, callback) => {
  const request = event.Records[0].cf.request;
  const uri = request.uri;

  let redirect = await getRedirect(uri);
  if (redirect) {
    const redirectResponse = createRedirect(redirect.To);
    callback(null, redirectResponse);
    return;
  }
  callback(null, request);
  return request;
};

function getRedirect(uri) {
  let params = {
    TableName: "Redirects",
    KeyConditionExpression: "#from = :from",
    ExpressionAttributeNames: {
      "#from": "From"
    },
    ExpressionAttributeValues: {
      ":from": uri
    }
  };
  return dynamoDB
    .query(params)
    .promise()
    .then(result => result.Items[0])
    .catch(reject => null);
}

function createRedirect(uri) {
  const response = {
    status: "302",
    statusDescription: "Found",
    headers: {
      "cache-control": [
        {
          key: "Cache-Control",
          value: "max-age=0"
        }
      ],
      location: [
        {
          key: "Location",
          value: uri
        }
      ]
    }
  };
  return response;
}

如果我使用测试事件测试Lambda函数,就会得到重定向响应。然而,当我尝试使用CloudFront获取重定向时,我得到一个403错误。因此,假设URL
/a
应该重定向到
/b
。如果我调用
cloudfront.url/a
,我会收到一条消息,告诉我对象已经被移动到
/b
(或者更好的是被自动重定向)。相反,我得到了403错误。Lambda是否有问题,或者我需要向CloudFront附加一些权限才能使重定向正常工作?

感谢Niobos的帮助,我找到了问题所在。问题出在DynamoDB地区。我的Lambda边函数在eu-central-1上运行,这是离我所在位置最近的边,但DynamoDB表在us-east-1中。所以我把代码改成了这个,一切都正常了:)


您能否提供应该导致重定向的HTTP请求的更详细输出(例如通过运行
curl cloudfront.url/a
)?你确定Lambda@Edge是否有效触发(例如,通过验证CloudWatch日志)?如果我对必须重定向的URL进行卷曲,我会得到以下
AccessDenied
accessdenied54c54423d45b705di/9weyfzv8fg3rsbg2jfnqdha11vbv8rluyfgkumtdnb8iv3vbcg6q7jk2s9fo2ckgklvlmrpu=
是,Lambda被命中,因为我可以看到使用正确的时间戳创建请求日志。在这种情况下,您的Lambda@Edge函数未返回重定向(
curl URL
不会自动跟随重定向)。您可以在
getRedirect()
函数中添加一些调试语句来找出原因
console.log()
将在CloudWatch日志中结束。有趣的是:在CloudWatch上,它说Lambda角色没有权限在DynamoDB上执行查询。但是,角色具有查询权限,而且正如我所说的,如果使用测试事件,它将执行查询。只有在CloudFront中,它才会以某种方式释放权限。编辑:我给了Lambda角色对DynamoDB的所有权限,但它没有改变。你能验证你是否进入了正确的区域吗?Lambda@Edge在CloudFront服务器的区域中运行,该区域不一定是DynamoDB表所在的区域。最好在中显式指定区域Lambda@Edge代码。
const aws = require("aws-sdk");
const dynamoDB = new aws.DynamoDB.DocumentClient({ region: "us-east-1" });
exports.handler = async (event, context, callback) => {
  const request = event.Records[0].cf.request;
  const uri = request.uri;

  let redirect = await getRedirect(uri);
  if (redirect) {
    const redirectResponse = createRedirect(redirect.To);
    callback(null, redirectResponse);
    return;
  }
  callback(null, request);
  return request;
};

function getRedirect(uri) {
  let params = {
    TableName: "Redirects",
    KeyConditionExpression: "#from = :from",
    ExpressionAttributeNames: {
      "#from": "From"
    },
    ExpressionAttributeValues: {
      ":from": uri
    }
  };
  return dynamoDB
    .query(params)
    .promise()
    .then(result => result.Items[0])
    .catch(reject => null);
}

function createRedirect(uri) {
  const response = {
    status: "302",
    statusDescription: "Found",
    headers: {
      "cache-control": [
        {
          key: "Cache-Control",
          value: "max-age=0"
        }
      ],
      location: [
        {
          key: "Location",
          value: uri
        }
      ]
    }
  };
  return response;
}