简体   繁体   English

API Gateway CORS:没有“Access-Control-Allow-Origin”标头

[英]API Gateway CORS: no 'Access-Control-Allow-Origin' header

Although CORS has been set up through API Gateway and the Access-Control-Allow-Origin header is set, I still receive the following error when attempting to call the API from AJAX within Chrome:虽然已经通过 API Gateway 设置了 CORS 并设置了Access-Control-Allow-Origin标头,但在 Chrome 中尝试从 AJAX 调用 API 时仍然收到以下错误:

XMLHttpRequest cannot load http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY . XMLHttpRequest 无法加载http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY No 'Access-Control-Allow-Origin' header is present on the requested resource.请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'null' is therefore not allowed access.因此,Origin 'null' 不允许访问。 The response had HTTP status code 403.响应具有 HTTP 状态代码 403。

I attempted to GET the URL through Postman and it shows the above header is successfully passed:我试图通过Postman获取 URL,它显示上述标头已成功传递:

传递的标头

And from the OPTIONS reponse:从 OPTIONS 响应中:

响应标头

How can I call my API from the browser without reverting to JSON-P?如何从浏览器调用我的 API 而不恢复为 JSON-P?

I get the same problem.我遇到同样的问题。 I have used 10hrs to findout.我已经用了 10 小时来找出答案。

https://serverless.com/framework/docs/providers/aws/events/apigateway/ https://serverless.com/framework/docs/providers/aws/events/apigateway/

// handler.js

'use strict';

module.exports.hello = function(event, context, callback) {

const response = {
  statusCode: 200,
  headers: {
    "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
    "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS 
  },
  body: JSON.stringify({ "message": "Hello World!" })
};

callback(null, response);
};

If anyone else is running into this still - I was able to track down the root cause in my application.如果其他人仍然遇到这种情况 - 我能够在我的应用程序中找到根本原因。

If you are running API-Gateway with custom Authorizers - API-Gateway will send a 401 or 403 back before it actually hits your server.如果您使用自定义授权器运行 API-Gateway - API-Gateway 将在实际访问您的服务器之前发送 401 或 403。 By default - API-Gateway is NOT configured for CORS when returning 4xx from a custom authorizer.默认情况下 - 从自定义授权方返回 4xx 时,未为 CORS 配置 API 网关。

Also - if you happen to be getting a status code of 0 or 1 from a request running through API Gateway, this is probably your issue.另外 - 如果您碰巧从通过 API Gateway 运行的请求中获得01的状态代码,这可能是您的问题。

To fix - in the API Gateway configuration - go to "Gateway Responses", expand "Default 4XX" and add a CORS configuration header there.要修复 - 在 API 网关配置中 - 转到“网关响应”,展开“默认 4XX”并在那里添加 CORS 配置标头。 ie IE

Access-Control-Allow-Origin: '*'

Make sure to re-deploy your gateway - and voila!确保重新部署您的网关- 瞧!

If you have tried everything regarding this issue to no avail, you'll end up where I did.如果您已经尝试了有关此问题的所有方法,但都无济于事,那么您最终会得到我所做的。 It turns out, Amazon's existing CORS setup directions work just fine... just make sure you remember to redeploy !事实证明,亚马逊现有的 CORS 设置指导工作得很好……只要确保你记得重新部署 The CORS editing wizard, even with all its nice little green checkmarks, does not make live updates to your API. CORS 编辑向导,即使有所有漂亮的小绿色复选标记,也不会对您的 API 进行实时更新。 Perhaps obvious, but it stumped me for half a day.也许很明显,但它难倒了我半天。

在此处输入图片说明

1) I needed to do the same as @riseres and some other changes.This are my response headers: 1)我需要做与@riseres 和其他一些更改相同的事情。这是我的响应标头:

headers: {
            'Access-Control-Allow-Origin' : '*',
            'Access-Control-Allow-Headers':'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
            'Access-Control-Allow-Credentials' : true,
            'Content-Type': 'application/json'
        }

2) And 2和

According to this documentation:根据此文档:

http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

When you use proxy for lambda functions on API Gateway config, the post or get methods have no added headers, only the options does.当您在 API Gateway 配置上为 lambda 函数使用代理时,post 或 get 方法没有添加标头,只有选项添加。 You must do it manually in the response(server or lambda response).您必须在响应(服务器或 lambda 响应)中手动执行此操作。

3) And 3) 和

Beside that, I needed to disable the 'API Key Required' option in my API gateway post method.除此之外,我需要在我的 API 网关 post 方法中禁用“API Key Required”选项。

Got my sample working: I just inserted 'Access-Control-Allow-Origin': '*', inside headers:{} in the generated nodejs Lambda function.让我的示例工作:我刚刚在生成的 nodejs Lambda 函数中插入了'Access-Control-Allow-Origin': '*', inside headers:{} I made no changes to the Lambda-generated API layer.没有对 Lambda 生成的 API 层进行任何更改。

Here's my NodeJS:这是我的 NodeJS:

'use strict';
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
exports.handler = ( event, context, callback ) => {
    const done = ( err, res ) => callback( null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
        headers:{ 'Access-Control-Allow-Origin' : '*' },
    });
    switch( event.httpMethod ) {
        ...
    }
};

Here's my AJAX call这是我的 AJAX 调用

$.ajax({
    url: 'https://x.execute-api.x-x-x.amazonaws.com/prod/fnXx?TableName=x',
    type: 'GET',
    beforeSend: function(){ $( '#loader' ).show();},
    success: function( res ) { alert( JSON.stringify(res) ); },
    error:function(e){ alert('Lambda returned error\n\n' + e.responseText); },
    complete:function(){ $('#loader').hide(); }
});

I just added headers to my lambda function response and it worked like a charm我刚刚在我的 lambda 函数响应中添加了标头,它就像一个魅力

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hey it works'),
        headers:{ 'Access-Control-Allow-Origin' : '*' }
    };
    return response;
};

For Googlers:对于 Google 员工:

Here is why:原因如下:

  • Simple request, or, GET / POST with no cookies do not trigger preflight简单的请求,或者,没有 cookie 的GET / POST不会触发预检
  • When you configure CORS for a path, API Gateway will only create an OPTIONS method for that path, then send Allow-Origin headers using mock responses when user calls OPTIONS , but GET / POST will not get Allow-Origin automatically为路径配置 CORS 时,API Gateway 只会为该路径创建OPTIONS方法,然后在用户调用OPTIONS时使用模拟响应发送Allow-Origin标头,但GET / POST不会自动获取Allow-Origin
  • If you try to send simple requests with CORS mode on, you will get an error because that response has no Allow-Origin header如果您尝试在开启 CORS 模式的情况下发送简单请求,您将收到错误消息,因为该响应没有Allow-Origin标头
  • You may adhere to best practice, simple requests are not meant to send response to user, send authentication/cookie along with your requests to make it "not simple" and preflight will trigger您可以遵循最佳实践,简单的请求并不意味着向用户发送响应,将身份验证/cookie 与您的请求一起发送以使其“不简单”并且预检将触发
  • Still, you will have to send CORS headers by yourself for the request following OPTIONS尽管如此,您仍必须为以下OPTIONS的请求自行发送 CORS 标头

To sum it up:把它们加起来:

  • Only harmless OPTIONS will be generated by API Gateway automatically API Gateway 只会自动生成无害的OPTIONS
  • OPTIONS are only used by browser as a precautious measure to check possibility of CORS on a path OPTIONS仅被浏览器用作检查路径上 CORS可能性的预防措施
  • Whether CORS is accepted depend on the actual method eg GET / POST是否接受CORS 取决于实际方法,例如GET / POST
  • You have to manually send appropriate headers in your response您必须在响应中手动发送适当的标头

For me, the answer that FINALLY WORKED, was the comment from James Shapiro from Alex R's answer (second most upvoted).对我来说,最终有效的答案是 James Shapiro 的评论来自 Alex R 的答案(第二高投票)。 I got into this API Gateway problem in the first place, by trying to get a static webpage hosted in S3 to use lambda to process the contact-us page and send an email.我首先遇到了这个 API 网关问题,尝试获取托管在 S3 中的静态网页以使用 lambda 处理联系我们页面并发送电子邮件。 Simply checking [ ] Default 4XX fixed the error message.只需检查 [ ] Default 4XX 即可修复错误消息。

在此处输入图片说明

I found a simple solution within我在里面找到了一个简单的解决方案

API Gateway > Select your API endpoint > Select the method (in my case it was the POST) API 网关 > 选择您的 API 端点 > 选择方法(在我的情况下是 POST)

Now there is a dropdown ACTIONS > Enable CORS .. select it.现在有一个下拉操作 > 启用 CORS .. 选择它。

Now select the dropdown ACTIONS again > Deploy API (re-deploy it)现在再次选择下拉 ACTIONS > Deploy API(重新部署它)

在此处输入图片说明

It worked !有效 !

I got mine working after I realised that the lambda authoriser was failing and for some unknown reason that was being translated into a CORS error.在我意识到 lambda 授权器失败并且由于某种未知原因被转换为 CORS 错误后,我开始工作。 A simple fix to my authoriser (and some authoriser tests that I should have added in the first place) and it worked.对我的授权人的简单修复(以及我应该首先添加的一些授权人测试)并且它起作用了。 For me the API Gateway action 'Enable CORS' was required.对我来说,API 网关操作“启用 CORS”是必需的。 This added all the headers and other settings I needed in my API.这在我的 API 中添加了我需要的所有标头和其他设置。

After Change your Function or Code Follow these two steps.更改您的功能或代码后 请按照以下两个步骤操作。

First Enable CORS Then Deploy API every time.首先启用 CORS,然后每次都部署 API

在为POSTOPTIONS启用 CORS 后部署代码对我有用。

I am running aws-serverless-express , and in my case needed to edit simple-proxy-api.yaml .我正在运行aws-serverless-express ,在我的情况下需要编辑simple-proxy-api.yaml

Before CORS was configured to https://example.com , I just swapped in my site's name and redeployed via npm run setup , and it updated my existing lambda/stack.在将 CORS 配置为https://example.com之前,我只是交换了我的站点名称并通过npm run setup重新部署,它更新了我现有的 lambda/stack。

#...
/:
#...
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...
/{proxy+}:
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...

就我而言,由于我使用 AWS_IAM 作为 API 网关的授权方法,我需要授予我的 IAM 角色访问端点的权限。

For me, as I was using pretty standard React fetch calls, this could have been fixed using some of the AWS Console and Lambda fixes above, but my Lambda returned the right headers (I was also using Proxy mode) and I needed to package my application up into a SAM Template, so I could not spend my time clicking around the console.对我来说,因为我使用的是非常标准的 React fetch 调用,所以这可以使用上面的一些 AWS 控制台和 Lambda 修复来修复,但是我的 Lambda 返回了正确的标头(我也使用了代理模式),我需要打包我的应用程序升级到 SAM 模板,所以我不能花时间在控制台上单击。

I noticed that all of the CORS stuff worked fine UNTIL I put Cognito Auth onto my application.我注意到所有 CORS 的东西都运行良好,直到我将 Cognito Auth 放到我的应用程序中。 I just basically went very slow doing a SAM package / SAM deploy with more and more configurations until it broke and it broke as soon as I added Auth to my API Gateway.我只是在使用越来越多的配置进行 SAM 包/SAM 部署时速度非常慢,直到它坏了,只要我将 Auth 添加到我的 API 网关,它就坏了。 I spent a whole day clicking around wonderful discussions like this one, looking for an easy fix, but then ended up having to actually read about what CORS was doing.我花了一整天的时间点击像这样的精彩讨论,寻找一个简单的解决方法,但最终不得不实际阅读 CORS 正在做什么。 I'll save you the reading and give you another easy fix (at least for me).我将为您节省阅读时间,并为您提供另一个简单的解决方案(至少对我而言)。

Here is an example of an API Gateway template that finally worked (YAML):以下是最终有效的 API 网关模板示例 (YAML):

Resources:
  MySearchApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: 'Dev'
      Cors:
        AllowMethods: "'OPTIONS, GET'"
        AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
        AllowOrigin: "'*'"
      Auth:
        DefaultAuthorizer: MyCognitoSearchAuth
        Authorizers:
          MyCognitoSearchAuth:
            UserPoolArn: "<my hardcoded user pool ARN>"
            AuthType: "COGNITO_USER_POOLS"
        AddDefaultAuthorizerToCorsPreflight: False

Note the AddDefaultAuthorizerToCorsPreflight at the bottom.注意底部的 AddDefaultAuthorizerToCorsPreflight。 This defaults to True if you DON'T have it in your template, as as far as I can tell from my reading.根据我的阅读,如果您的模板中没有它,则默认为 True。 And, when True, it sort of blocks the normal OPTIONS behavior to announce what the Resource supports in terms of Allowed Origins.并且,当为 True 时,它​​会阻止正常的 OPTIONS 行为来宣布资源在允许的来源方面支持什么。 Once I explicitly added it and set it to False, all of my issues were resolved.一旦我明确添加它并将其设置为 False,我的所有问题都解决了。

The implication is that if you are having this issue and want to diagnose it more completely, you should visit your Resources in API Gateway and check to see if your OPTIONS method contains some form of Authentication.这意味着如果您遇到此问题并想要更完整地诊断它,您应该访问 API Gateway 中的资源并检查您的 OPTIONS 方法是否包含某种形式的身份验证。 Your GET or POST needs Auth, but if your OPTIONS has Auth enabled on it, then you might find yourself in this situation.您的 GET 或 POST 需要身份验证,但如果您的 OPTIONS 启用了身份验证,那么您可能会发现自己处于这种情况。 If you are clicking around the AWS console, then try removing from OPTIONS, re-deploy, then test.如果您在 AWS 控制台周围单击,请尝试从 OPTIONS 中删除,重新部署,然后进行测试。 If you are using SAM CLI, then try my fix above.如果您使用的是 SAM CLI,请尝试我上面的修复。

Make sure you're calling the right path.确保您调用的是正确的路径。

Hitting a non-existing path, may cause CORS related errors, for whatever reason.无论出于何种原因,命中不存在的路径都可能导致 CORS 相关错误。 Probably due to the fact that the 404 doesn't include CORS headers in its response.可能是因为404在其响应中不包含 CORS 标头。

Thanks to @jackko's comment on the initial question.感谢@jackko 对最初问题的评论。 This was my problem.这是我的问题。 Sounds silly but can happen to anyone.听起来很傻,但可能发生在任何人身上。

For Python , as @riseres mentioned, after importing json, etc...对于Python ,正如@riseres 所提到的,在导入 json 等之后......

// lambda handler

def hello(event, context, callback):
response = {
  statusCode: 200,
  headers: {
    "Access-Control-Allow-Origin" : "*", # Required for CORS support, to work, also you should instead specify the proper origin if credentials are mandatory
    "Access-Control-Allow-Credentials" : True # Required for cookies, authorization headers with HTTPS 
  },
  body: json.dumps({ "message": "Hello World!" })
}

callback(null, response);
}

Another root cause of this problem might be a difference between HTTP/1.1 and HTTP/2.此问题的另一个根本原因可能是 HTTP/1.1 和 HTTP/2 之间的差异。

Symptom: Some users, not all of them, reported to get a CORS error when using our Software.症状:部分用户(并非全部)在使用我们的软件时报告出现 CORS 错误。

Problem: The Access-Control-Allow-Origin header was missing sometimes .问题:有时缺少Access-Control-Allow-Origin标头。

Context: We had a Lambda in place, dedicated to handling OPTIONS request and replying with the corresponding CORS headers, such as Access-Control-Allow-Origin matching a whitelisted Origin .上下文:我们有一个 Lambda,专门用于处理OPTIONS请求并使用相应的 CORS 标头进行回复,例如Access-Control-Allow-Origin匹配列入白名单的Origin

Solution: The API Gateway seems to transform all headers to lower-case for HTTP/2 calls, but maintains capitalization for HTTP/1.1.解决方案: API 网关似乎将 HTTP/2 调用的所有标头转换为小写,但保持 HTTP/1.1 的大写。 This caused the access to event.headers.origin to fail.这导致对event.headers.origin的访问失败。

Check if you're having this issue too:检查您是否也遇到此问题:

Assuming your API is located at https://api.example.com , and your front-end is at https://www.example.com .假设您的 API 位于https://api.example.com ,而您的前端位于https://www.example.com Using CURL, make a request using HTTP/2:使用 CURL,使用 HTTP/2 发出请求:

curl -v -X OPTIONS -H 'Origin: https://www.example.com' https://api.example.com

The response output should include the header:响应输出应包括标题:

< Access-Control-Allow-Origin: https://www.example.com

Repeat the same step using HTTP/1.1 (or with a lowercase Origin header):使用 HTTP/1.1(或使用小写的Origin标头)重复相同的步骤:

curl -v -X OPTIONS --http1.1 -H 'Origin: https://www.example.com' https://api.example.com

If the Access-Control-Allow-Origin header is missing, you might want to check case sensitivity when reading the Origin header.如果缺少Access-Control-Allow-Origin标头,您可能需要在读取Origin标头时检查区分大小写。

In addition to others comments, something to look out for is the status returned from your underlying integration and if the Access-Control-Allow-Origin header is returned for that status.除了其他评论之外,还需要注意的是从您的底层集成返回的状态,以及是否为该状态返回了 Access-Control-Allow-Origin 标头。

Doing the 'Enable CORS' thing only sets up 200 status.执行“启用 CORS”操作只会设置 200 个状态。 If you have others on the endpoint, eg 4xx and 5xx, you need to add the header yourself.如果您在端点上有其他人,例如 4xx 和 5xx,您需要自己添加标头。

In my case I enabled all the methods and gateway responses.就我而言,我启用了所有方法和网关响应。 Then it worked like a charm.然后它就像一个魅力。 Don't forget to deploy.不要忘记部署。

在此处输入图片说明

For those using Cognito authorizers in API Gateway, there's actually no need to set custom Gateway Responses.对于在 API Gateway 中使用 Cognito 授权器的用户,实际上无需设置自定义网关响应。 The API Gateway blocks pre-flight because they're "unauthorized" by default AWS logic. API 网关会阻止预检,因为它们在默认的 AWS 逻辑中是“未经授权的”。

Fortunately, there's a built-in parameter to fix this.幸运的是,有一个内置参数可以解决这个问题。 Simply add AddDefaultAuthorizerToCorsPreflight: False to your API Authorizer and API Gateway will disable authentication for pre-flight requests.只需将AddDefaultAuthorizerToCorsPreflight: False添加到您的 API Authorizer,API Gateway 将禁用预检请求的身份验证。 Here's the documentation , and an example setup:这是文档和示例设置:

MyApi:
Type: AWS::Serverless::Api
Properties:
  StageName: Prod
  Cors: 
    AllowHeaders: "'*'"
    AllowMethods: "'*'"
    AllowOrigin: "'*'"
  Auth:
    DefaultAuthorizer: MyCognitoAuthorizer
    AddDefaultAuthorizerToCorsPreflight: False
    Authorizers:
      MyCognitoAuthorizer:
        UserPoolArn: !GetAtt MyCognitoUserPool.Arn

For future sufferers:对于未来的患者:

This cursed problem haunted me once again and this time it was because I was sending a custom header:这个该死的问题再次困扰着我,这次是因为我发送了一个自定义标题:

let headers = {
  'Content-Type': 'application/json',
  'Is-Web': true,
  Authorization: `Bearer ${accessToken}`,
};

This "Is-Web" custom header made API Gateway block my requests and masked it as a CORS error.这个“Is-Web”自定义标头使 API Gateway 阻止了我的请求并将其屏蔽为 CORS 错误。 If you're sending one, just remove it and test it.如果您要发送一个,只需将其删除并测试即可。 Almost lost a whole day of work because of this.几乎因此失去了一整天的工作。

I have been having this issue for quite sometime.我已经有这个问题很长一段时间了。 I endend up putting this to my python lambda function我最终把它放到我的 python lambda 函数中

 response ={
        'statusCode': statusCode,
        'headers':{
             'Access-Control-Allow-Headers': 'Content-Type',
             'Access-Control-Allow-Origin': '*',
             'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
                  },
                  'body':json.dumps(body)
              }
    return response 

I hope this helps someone out there我希望这可以帮助那里的人

In my case, I was simply writing the fetch request URL wrong.就我而言,我只是将获取请求 URL 写错了。 On serverless.yml , you set cors to true :serverless.yml ,你设置corstrue

register-downloadable-client:
    handler: fetch-downloadable-client-data/register.register
    events:
      - http:
          path: register-downloadable-client
          method: post
          integration: lambda
          cors: true
          stage: ${self:custom.stage}

and then on the lambda handler you send the headers, but if you make the fetch request wrong on the frontend, you're not going to get that header on the response and you're going to get this error.然后在 lambda 处理程序上发送标头,但是如果在前端使提取请求出错,则不会在响应中获得该标头,并且会收到此错误。 So, double check your request URL on the front.因此,请仔细检查前面的请求 URL。

In Python you can do it as in the code below:在 Python 中,您可以按照以下代码进行操作:

{ "statusCode" : 200,
'headers': 
    {'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': "*"
     },
"body": json.dumps(
    {
    "temperature" : tempArray,
    "time": timeArray
    })
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Web API 2 CORS不存在“ Access-Control-Allow-Origin”标头 - web api 2 CORS No 'Access-Control-Allow-Origin' header is present AWS API 网关不存在“Access-Control-Allow-Origin”标头 - AWS API Gateway No 'Access-Control-Allow-Origin' header is present 标题CORS“Access-Control-Allow-Origin”缺少Codeigniter - header CORS “Access-Control-Allow-Origin” missing Codeigniter 由watchguard剥离的CORS Access-Control-Allow-Origin标头 - CORS Access-Control-Allow-Origin header stripped by watchguard 缺少 CORS 标头“Access-Control-Allow-Origin” - CORS header 'Access-Control-Allow-Origin' missing CORS-不存在“ Access-Control-Allow-Origin”标头 - CORS - No 'Access-Control-Allow-Origin' header is present c#已启用CORS的Web Api和所请求资源上存在可怕的“Access-Control-Allow-Origin”标头 - c# Web Api with CORS Enabled and the dreaded No 'Access-Control-Allow-Origin' header is present on the requested resource 使用 AWS API Gateway 时出现错误“访问控制允许来源” - Error 'Access-Control-Allow-Origin' using AWS API Gateway CORS django &#39;访问控制-允许-来源&#39; - CORS django 'Access-Control-Allow-Origin' Zillow API错误:“不存在“ Access-Control-Allow-Origin”标头” - Zillow API Error:“No 'Access-Control-Allow-Origin' header is present”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM