跳至主要内容

使用 CORS 和 JSONP 进行跨域请求

您可以使用跨域资源共享 (CORS) 和 JSONP 回调在不同域之间进行 API 请求。

关于跨域请求

跨域请求是指向与发起请求的域不同的域发出的请求。出于安全原因,大多数 Web 浏览器会阻止跨域请求。但是,您可以使用跨域资源共享 (CORS) 和 JSONP 回调来进行跨域请求。

跨域资源共享 (CORS)

REST API 支持跨域资源共享 (CORS),用于来自任何来源的 AJAX 请求。有关更多信息,请参阅“CORS W3C 建议”和HTML 5 安全指南

以下是一个来自浏览器,命中 http://example.com 的示例请求

$ curl -I https://api.github.com -H "Origin: http://example.com"
HTTP/2 302
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: ETag, Link, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval

这是 CORS 预检请求的样子

$ curl -I https://api.github.com -H "Origin: http://example.com" -X OPTIONS
HTTP/2 204
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE
Access-Control-Expose-Headers: ETag, Link, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
Access-Control-Max-Age: 86400

JSON-P 回调

您可以向任何 GET 调用发送一个 ?callback 参数,以使结果包装在 JSON 函数中。这通常用于浏览器希望在网页中嵌入 GitHub 内容并避免跨域问题时。响应包含与常规 API 相同的数据输出,以及相关的 HTTP 标头信息。

$ curl https://api.github.com?callback=foo

> /**/foo({
>   "meta": {
>     "status": 200,
>     "x-ratelimit-limit": "5000",
>     "x-ratelimit-remaining": "4966",
>     "x-ratelimit-reset": "1372700873",
>     "Link": [ // pagination headers and other links
>       ["https://api.github.com?page=2", {"rel": "next"}]
>     ]
>   },
>   "data": {
>     // the data
>   }
> })

您可以编写一个 JavaScript 处理程序来处理回调。以下是一个您可以尝试的最小示例

<html>
<head>
<script type="text/javascript">
function foo(response) {
  var meta = response.meta;
  var data = response.data;
  console.log(meta);
  console.log(data);
}

var script = document.createElement('script');
script.src = 'https://api.github.com?callback=foo';

document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>

<body>
  <p>Open up your browser's console.</p>
</body>
</html>

所有标头都具有与 HTTP 标头相同的字符串值,除了 LinkLink 标头会为您预先解析,并以 [url, options] 元组数组的形式出现。

例如,一个看起来像这样的链接

Link: <url1>; rel="next", <url2>; rel="foo"; bar="baz"

在回调输出中将看起来像这样

{
  "Link": [
    [
      "url1",
      {
        "rel": "next"
      }
    ],
    [
      "url2",
      {
        "rel": "foo",
        "bar": "baz"
      }
    ]
  ]
}