关于 lambda:使用凭据发出 CORS 预检请求

Issue CORS preflight request with credentials

我正在使用无服务器 yml 模板将我的函数部署到 aws。以下代码段显示了端点之一的配置,

1
2
3
4
5
6
7
8
9
10
functions:
  publish:
    handler: lambda.publish
    events:
      - http:
          method: post
          path: publish
          cors:
            origin: ${self:custom.origin.${self:custom.stage}}
            allowCredentials: true

这是我的提取请求,

1
2
3
4
5
6
7
8
fetch(`${SOME_DOMAIN}/publish`, {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    })

我正在像这样在我的 lambda 中处理响应头,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const ALLOWED_ORIGINS = [
  'http://localhost:3001',
  'https://staging.company.com.au',
  'https://blaze-staging.company.com.au',
  'https://www.company.com.au',
  'https://blaze.company.com.au',
  'https://direct.company.com.au',
]

const origin = event.headers.origin
let headers

if (ALLOWED_ORIGINS.includes(origin)) {
  headers = {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': origin,
    'Access-Control-Allow-Credentials': true,
  }
} else {
  headers = {
    'Access-Control-Allow-Origin': 'http://localhost:3001',
  }
}

const response = {
  statusCode: 200,
  headers,
  body: JSON.stringify({ message: 'Successfully published the message.' }),
}

callback(null, response)

我无法设置飞行前请求,因为我无法设置多个来源。如何解决这个问题?设置 mode: 'no-cors'
在请求上实际上是允许来自任何域的请求。非常感谢任何帮助。

飞行前请求将显示以下错误:

Failed to load https://o9a0130i2r.execute-api.us-east-1.amazonaws.com/development/publish:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://direct.company.com' is therefore not allowed
access. The response had HTTP status code 403. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.


向处理 post 请求的同一个 lambda 添加一个额外的端点。

类似这样的serverless.yml

1
2
3
4
5
6
  options:
    handler: lambda.options
    events:
      - http:
          method: options
          path: publish

您可以将您的来源添加到允许的来源列表中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
export const options = async (event, context, callback) => {
  const ALLOWED_ORIGINS = [
    'http://localhost:3001',
  ]

  const origin = event.headers.origin || event.headers.Origin
  let response

  if (ALLOWED_ORIGINS.includes(origin)) {
    response = {
      statusCode: 200,
      headers: {
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Allow-Origin': origin,
        'Access-Control-Allow-Credentials': true,
      },
      body: JSON.stringify({ message: 'Success' }),
    }
  } else {
    response = {
      statusCode: 403,
      headers: {
        'Access-Control-Allow-Origin': '*',
      },
      body: JSON.stringify({ message: {
        error: 'Missing Authentication token',
        origin: `Request origin is ${origin}`,
      },
      }),
    }
  }

  callback(null, response)
  return
}

现在,当浏览器发出选项请求时,我们会处理它并返回 200,如果它来自允许的来源或错误。您可以根据需要自定义错误信息。