使用BOTO3为AWS Api网关自动化CORS

时间:2016-06-27 11:36:34

标签: amazon-web-services cors aws-api-gateway boto3

我一直在尝试为AWS Api Gateway配置CORS的最后几个小时。我试图逐字复制"启用CORS"按钮在aws控制台内完成。但即使每个方法在控制台中看起来都相同,POST到其余API也可以使用"启用CORS"按钮但在使用我的代码设置CORS时返回500权限错误。

这是与CORS设置相关的代码:

# Set the put method response of the POST method
self.apigateway.put_method_response(
    restApiId=self.rest_api['id'],
    resourceId=root_resource['id'],
    httpMethod='POST',
    statusCode='200',
    responseParameters={
        'method.response.header.Access-Control-Allow-Origin': False
    },
    responseModels={
        'application/json': 'Empty'
    }
)

# Set the put integration response of the POST method
self.apigateway.put_integration_response(
    restApiId=self.rest_api['id'],
    resourceId=root_resource['id'],
    httpMethod='POST',
    statusCode='200',
    responseParameters={
        'method.response.header.Access-Control-Allow-Origin': '\'*\''
    },
    responseTemplates={
        'application/json': ''
    }
)

# Add an options method to the rest api
api_method = self.apigateway.put_method(
    restApiId=self.rest_api['id'],
    resourceId=root_resource['id'],
    httpMethod='OPTIONS',
    authorizationType='NONE'
)

# Set the put integration of the OPTIONS method
self.apigateway.put_integration(
    restApiId=self.rest_api['id'],
    resourceId=root_resource['id'],
    httpMethod='OPTIONS',
    type='MOCK',
    requestTemplates={
        'application/json': ''
    }
)

# Set the put method response of the OPTIONS method
self.apigateway.put_method_response(
    restApiId=self.rest_api['id'],
    resourceId=root_resource['id'],
    httpMethod='OPTIONS',
    statusCode='200',
    responseParameters={
        'method.response.header.Access-Control-Allow-Headers': False,
        'method.response.header.Access-Control-Allow-Origin': False,
        'method.response.header.Access-Control-Allow-Methods': False
    },
    responseModels={
        'application/json': 'Empty'
    }
)

# Set the put integration response of the OPTIONS method
self.apigateway.put_integration_response(
    restApiId=self.rest_api['id'],
    resourceId=root_resource['id'],
    httpMethod='OPTIONS',
    statusCode='200',
    responseParameters={
        'method.response.header.Access-Control-Allow-Headers': '\'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token\'',
        'method.response.header.Access-Control-Allow-Methods': '\'POST,OPTIONS\'',
        'method.response.header.Access-Control-Allow-Origin': '\'*\''
    },
    responseTemplates={
        'application/json': ''
    }
)

当通过AWS控制台启用CORS时,这是来自POST和OPTIONS的get-method的响应:

{
    "httpMethod": "POST",
    "apiKeyRequired": false,
    "methodIntegration": {
        "httpMethod": "POST",
        "cacheKeyParameters": [],
        "integrationResponses": {
            "200": {
                "responseParameters": {
                    "method.response.header.Access-Control-Allow-Origin": "'*'"
                },
                "statusCode": "200",
                "responseTemplates": {
                    "application/json": null
                }
            }
        },
        "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:477869670267:function:controller/invocations",
        "requestTemplates": {
            "application/json": null
        },
        "cacheNamespace": "o9h9b8tzo2",
        "type": "AWS"
    },
    "methodResponses": {
        "200": {
            "responseParameters": {
                "method.response.header.Access-Control-Allow-Origin": false
            },
            "statusCode": "200",
            "responseModels": {
                "application/json": "Empty"
            }
        }
    },
    "authorizationType": "NONE"
}
{
    "requestParameters": {},
    "httpMethod": "OPTIONS",
    "methodResponses": {
        "200": {
            "statusCode": "200",
            "responseParameters": {
                "method.response.header.Access-Control-Allow-Headers": false,
                "method.response.header.Access-Control-Allow-Methods": false,
                "method.response.header.Access-Control-Allow-Origin": false
            },
            "responseModels": {
                "application/json": "Empty"
            }
        }
    },
    "apiKeyRequired": false,
    "methodIntegration": {
        "cacheNamespace": "o9h9b8tzo2",
        "type": "MOCK",
        "requestTemplates": {
            "application/json": "{\"statusCode\": 200}"
        },
        "integrationResponses": {
            "200": {
                "responseTemplates": {
                    "application/json": null
                },
                "statusCode": "200",
                "responseParameters": {
                    "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
                    "method.response.header.Access-Control-Allow-Methods": "'POST,OPTIONS'",
                    "method.response.header.Access-Control-Allow-Origin": "'*'"
                }
            }
        },
        "cacheKeyParameters": []
    },
    "authorizationType": "NONE"
}

这是使用我的代码启用CORS的get-method的响应:

{
    "authorizationType": "NONE",
    "httpMethod": "POST",
    "methodIntegration": {
        "requestTemplates": {
            "application/json": null
        },
        "cacheNamespace": "308o168qal",
        "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:477869670267:function:controller/invocations",
        "httpMethod": "POST",
        "cacheKeyParameters": [],
        "integrationResponses": {
            "200": {
                "responseParameters": {
                    "method.response.header.Access-Control-Allow-Origin": "'*'"
                },
                "statusCode": "200",
                "responseTemplates": {
                    "application/json": null
                }
            }
        },
        "type": "AWS"
    },
    "apiKeyRequired": false,
    "methodResponses": {
        "200": {
            "responseParameters": {
                "method.response.header.Access-Control-Allow-Origin": false
            },
            "responseModels": {
                "application/json": "Empty"
            },
            "statusCode": "200"
        }
    }
}
{
    "authorizationType": "NONE",
    "apiKeyRequired": false,
    "methodIntegration": {
        "integrationResponses": {
            "200": {
                "statusCode": "200",
                "responseTemplates": {
                    "application/json": null
                },
                "responseParameters": {
                    "method.response.header.Access-Control-Allow-Methods": "'POST,OPTIONS'",
                    "method.response.header.Access-Control-Allow-Origin": "'*'",
                    "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
                }
            }
        },
        "cacheNamespace": "bm4zmvzkdk",
        "type": "MOCK",
        "cacheKeyParameters": [],
        "requestTemplates": {
            "application/json": "{\"statusCode\": 200}"
        }
    },
    "requestParameters": {},
    "methodResponses": {
        "200": {
            "statusCode": "200",
            "responseModels": {
                "application/json": "Empty"
            },
            "responseParameters": {
                "method.response.header.Access-Control-Allow-Methods": false,
                "method.response.header.Access-Control-Allow-Origin": false,
                "method.response.header.Access-Control-Allow-Headers": false
            }
        }
    },
    "httpMethod": "OPTIONS"
}

我看不出一个区别,我做错了什么?

根据AWS的MikeD请求,POST请求来自位于s3内的文件中的javascript:

function post_request() {
    var xhr = new XMLHttpRequest();
    var params = JSON.stringify({
        request: "registerUser",
        user:{ 
            username: document.getElementById("usernameInput").value, 
            email: document.getElementById("emailInput").value,
            password: document.getElementById("passwordInput").value
        }
    });
    xhr.open("POST", "$(endpoint_url)", true);
    xhr.setRequestHeader("Content-type", "application/json");
    xhr.setRequestHeader("x-api-key", "$(api_key)");
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
            if(xhr.status === 200){
                alert("You are registered!");
            }
            else{
                alert("Could not register. Please try again later.");
            }
        }
    };
    xhr.send(params);
    return false;
}

我的设置脚本将$(endpoint_url)和$(api_key)替换为适当的值(我已确认值是准确的)。

这是发出POST请求时Chrome控制台的逐字响应:

register.html?X-Amz-Date=20160628T070211Z&X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-…:39 OPTIONS https://dn9sjxz0i9.execute-api.us-east-1.amazonaws.com/prod post_request @ register.html?X-Amz-Date=20160628T070211Z&X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-…:39document.getElementById.onsubmit @ register.html?X-Amz-Date=20160628T070211Z&X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-…:44
register.html?X-Amz-Date=20160628T070211Z&X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-…:1 XMLHttpRequest cannot load https://dn9sjxz0i9.execute-api.us-east-1.amazonaws.com/prod. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://s3.amazonaws.com' is therefore not allowed access. The response had HTTP status code 500.

1 个答案:

答案 0 :(得分:1)

OPTIONS方法的put集成需要有一个映射模板,其中包含一个值为200的statusCode。看起来您的代码将映射模板设置为空字符串('')。通过API网关创建集成时,它会添加以下默认映射模板:{“statusCode”:200}

将相同的映射模板添加到put集成中,如下所示:

# Set the put integration of the OPTIONS method
self.apigateway.put_integration(
    restApiId=self.rest_api['id'],
    resourceId=root_resource['id'],
    httpMethod='OPTIONS',
    type='MOCK',
    requestTemplates={
        'application/json': '{"statusCode": 200}'
    }
)