使用CORS到API网关的AJAX POST不起作用,尽管可以使用CURL进行POST

时间:2016-11-05 20:21:49

标签: jquery ajax curl cors aws-api-gateway

所以我尝试使用$ .ajax()调用将数据提交到API端点。我已经验证我可以使用curl命令进行POST,格式如下:

curl -X POST -H "Content-Type: application/json" -d "{\"uname\":\"myusername2\",\"emailAddr\":\"user2@ex.com\"}" <url to my API endpoint>

curl命令返回一个空的JSON响应(看起来像{}),我的数据被放入数据库(这是我配置的API网关端点)。

但是,当我尝试使用$.ajax()命令执行此操作时,该命令被编程为在填写表单数据后单击按钮时触发,我无法使其工作。

    var obj = new Object();
    obj.uname = $uname;
    obj.emailAddr = $email;
    var stringedObj = JSON.stringify(obj);
    alert("stringified: " + stringedObj);
    $.ajax({
        url: '<same url as in curl>',
        type: 'POST',
        contentType: 'application/json',
        dataType: 'json',
        data: JSON.stringify(obj),
        success: function(data) {
            alert(JSON.stringify(data));
        },
        error: function(e) {
            alert("failed" + JSON.stringify(e));
        }
    });

每当我运行此命令时,我都可以从第一条警报消息中看到我的数据已正确字符串化。但是,我总是得到一条如下所示的错误消息:

failed{"readyState":0,"responseText":"","status":0,"statusText":"error"}

我想知道是否可以获得更详细的错误响应。另外,我尝试过使用parseData: falsecrossdomain: true。再一次,它在我使用curl时有效,所以我很确定这不是API网关配置问题。

感谢您的帮助!

编辑:我从下面的评论中了解到了javascript控制台。现在我发现这是由于CORS没有启用。我在AWS Api Gateway中启用了CORS,等待完成,然后将我的请求更改为:

    $.ajax({
        url: '<my url>',
        type: 'POST',
        data: JSON.stringify(obj),
        dataType: 'json',
        crossDomain: true,
        success: function(data) {
            alert(JSON.stringify(data));
        },
        error: function(e) {
            alert("failed" + JSON.stringify(e));
        }
    });

我在javascript控制台中得到了关于需要CORS的相同响应。 Other threads on CORS have shown以此为例。我想知道我是否需要自定义标头,虽然我尝试添加headers: { "Access-Control-Allow-Origin": "*" }但仍然从javascript控制台得到相同的响应:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://k6i6wk8487.execute-api.us-west-2.amazonaws.com/prod/comments. (Reason: CORS header 'Access-Control-Allow-Origin' missing).

2 个答案:

答案 0 :(得分:2)

想出来,在将其更新为启用CORS后,我没有在AWS API Gateway中点击'deploy'。卫生署!感谢所有帮助过的人。这是我最后的ajax电话:

$.ajax({
                url: $invokeUrl,
                type: 'POST',
                data: JSON.stringify(obj),
                dataType: 'json',
                crossDomain: true,
                contentType: 'application/json',
                success: function(data) {
                    alert(JSON.stringify(data));
                },
                error: function(e) {
                    alert("failed" + JSON.stringify(e));

感谢所有帮助过的人,如果您使用API​​网关遇到此问题,请告诉我,我会尽力提供帮助。

答案 1 :(得分:0)

您可以使用JSONP技术发出请求:

<script>
  function parseJSONP(response) {
    // Process the JSON response here.
  }
  function loadScript(url, data, callback) {
    script = document.createElement('script');
    document.getElementsByTagName('head')[0].appendChild(script);
    script.src = url
      +'?callback='+callback
      +'&data='+encodeURIComponent(JSON.stringify(data))
    ;
  }
  loadScript('http://yourdifferentdomain', yourdata, 'parseJSONP');
</script>

您可能需要调整远程服务以接受和解码URL中的数据参数。

另一种方法,可能更好,是将外部URL包装为参数,将POST数据的一部分包装到本地CURL,让服务器获取其他域的响应,并将其放回到响应中同一个域名。按照你的例子:

JS:

var curlBridge = 'http://samedomain/curl-resource/';
var remoteURL = 'http://otherdomain/target-resource/';
var obj = {}; // Your data to cross-domain post.
$.ajax({
  url: curlBridge,
  type: 'POST',
  data: JSON.stringify({
    "url": remoteURL,
    "headers": null, // Headers you may want to pass
    "post": obj
  }),
  dataType: 'json',
  crossDomain: true,
  contentType: 'application/json',
  success: function(data) {
    alert(JSON.stringify(data));
  },
  error: function(ev) {
    alert("failed" + JSON.stringify(ev));
  }
});

PHP:

<?php
function callUrl($url, $post = null, $headers = null) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_VERBOSE, 0);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 60000); // DEF 1000*60... // Hide/Show
    $post_str = "";
    if (is_array($post)) {
        if (count($post)) {
            foreach ($post as $key => $val) {
                if (is_array($val) && count($val)) {$val = json_encode($val);}
                $post_str .= "&".$key."=".$val;
            }
            if ($post_str[0] == "&") {$post_str = substr($post_str, 1);}
        }
    } else {$post_str = "".$post;}
    if ($post_str || is_array($post)) {
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_str);
    }
    if (is_array($headers) && count($headers)) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    } else {$headers = array();}
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

$input = array_merge($_GET, $_POST);
echo callUrl($input['url'], $input['post'], $input['headers']);