我们开发了一个 AWS lambda 函数,然后我们使用 AWS API gateway服务将它上线。

我们已经测试 API 并验证它是否按照我们的预期工作,看起来真的很棒。

现在我们准备好将 API 端点发送到我们的前端并从网站调用它。

一旦我们这样做了,我们就发现了一些这样的 CORS 错误:

错误信息:
Access to XMLHttpRequest at ‘https://xxx.execute-api.us-east-1.amazonaws.com/prod/’ from origin ‘https://www.datasciencebyexample.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

CORS 错误代表跨域资源共享 (CORS) 错误。默认情况下,服务器端和 Web 端不能从不同的域通话。
所以我们需要从双方放宽这个要求。

在 AWS API 网关上启用 CORS

首先,在服务器端,我们需要确保来自服务器端的reaponser header,应具有包含“Access-Control-Allow-Origin”键的信息,以告知允许哪个domain调用 API。我们可以把特定的域值作为值,或者’*'代表所有站点都允许。请注意,此标头由 API 端提供,而不是从前端提供。

使用 AWS API 网关,可以在这里查看官方指南,
https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html,或者只需按照以下步骤操作:

  1. 通过 https://console.aws.amazon.com/apigateway 登录 API Gateway 控制台。
  2. 在 API Gateway 控制台中,在 APIs 下选择一个 API。
  3. 在资源下选择一个资源。这将为资源上的所有方法启用 CORS。或者,您可以在资源下选择一种方法来仅为该方法启用 CORS。
  4. 从操作下拉菜单中选择启用 CORS。
    并选择启用 CORS
  5. 在启用 CORS 表单中,不需要更改任何内容,只需使用默认建议即可,基本上它们是:
  1. 在 Access-Control-Allow-Headers 输入字段中,输入客户端在实际请求资源时必须提交的以逗号分隔的标头列表的静态字符串。使用控制台提供的 Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token 标头列表或指定您自己的标头。
  2. 使用控制台提供的 ‘*’ 值作为 Access-Control-Allow-Origin 标头值以允许来自所有域的访问请求,或者为来自指定域的所有访问请求指定一个命名域。

选择启用 CORS 并替换现有的 CORS 标头。

  1. 最后一点,记得重新部署API,否则可能不会生效。

这是上述步骤中描述的屏幕截图:

gateway集成spring security gateway集成openapi cors问题_服务器

gateway集成spring security gateway集成openapi cors问题_API_02

我们可以通过在 python 中使用 requests 库调用 API 来检查 CORS 设置是否有效,并从响应中打印出标头:

使用 javascript fetch 调用 API

在验证标头具有响应标头中的“Access-Control-Allow-Origin”键和值后,我们确定 CORS 已全部设置在服务器端。
在前端调用端点,我们不需要做太多的工作,只要找到你喜欢的方法。

下面是在 javascript 中使用 fetch 调用 POST 端点的示例:

function CORSexample(input) {
 
    // call api
    // POST request using fetch()
	fetch("https://xxx.execute-api.us-east-1.amazonaws.com/prod/", {
		method: "POST",
		// Adding body or contents to send
		body: JSON.stringify({
			"data":{"query":input}
		}),
		 
		// Adding headers to the request if necessary
		headers: {
			"Content-type": "application/json; charset=UTF-8"
		}
	})
	 
	// Converting result to JSON
	.then(response => response.json())
	 
	.then(function(result)
	  {
	   console.log(result)
	   // in some oder jquery version, one has to parse the json to be object
	   // it's not necessary in new versions, just try it or not
	   //var result = $.parseJSON(result)
	  
	   // continue other custome stuff you have 
		
		}
	  
	}).catch(error => console.error('Error:', error)); 
  
  
  
}