GitHub API CORS 政策
GitHub API CORS Policy
我正在使用 jQuery 和 ajax 向 GitHub API 发出获取请求,但是在我刷新大约 3 次后,请求开始失败说:
Access to XMLHttpRequest at 'https://api.github.com/users/X/repos' from origin 'my domain' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
尽管如此,我已经将我的域注册为 GitHub OAuth 应用程序。
这是我的 javascript:
let repos = [];
const isEnglish = document.documentElement.lang == 'en';
class Repo {
constructor(name, description, webUrl, apiUrl) {
this._name = name;
this._description = description;
this._webUrl = webUrl;
this._apiUrl = apiUrl;
this._languages = [];
this.fetchLanguages();
}
get name() {
return this._name;
}
get description() {
return this._description;
}
get url() {
return this._webUrl;
}
get languages() {
return this._languages;
}
set languages(value) {
this._languages = value;
}
async fetchLanguages() {
const url = this._apiUrl + '/languages';
await $.ajax({
url: url,
complete: data => {
this._languages = Object.keys(data.responseJSON);
},
});
}
}
$(document).ready(async () => {
$.ajax({
url: 'https://api.github.com/users/X/repos',
complete: xhr => {
repos = xhr.responseJSON.map(json => {
return new Repo(json.name, json.description, json.html_url, json.url);
});
// build up list based on data
const container = document.getElementById('projectListContainer');
repos.forEach(repo => {
const li = document.createElement('li');
//header
const collapsibleHeader = document.createElement('div');
collapsibleHeader.classList.add('collapsible-header');
const headerText = document.createTextNode(repo.name);
collapsibleHeader.appendChild(headerText);
li.appendChild(collapsibleHeader);
//body
const collapsibleBody = document.createElement('div');
collapsibleBody.classList.add('collapsible-body');
const description = document.createElement('p');
const descText = document.createTextNode(repo.description);
description.appendChild(descText);
collapsibleBody.appendChild(description);
const languages = document.createElement('p');
languages.style.marginTop = '1rem';
const langTxt = isEnglish ? 'Languages used: ' : 'Talen gebruikt: ';
const langText = document.createTextNode(langTxt + repo.languages);
languages.appendChild(langText);
collapsibleBody.appendChild(languages);
const url = document.createElement('a');
url.href = repo.url;
url.target = '_blank';
url.style.marginTop = '1rem';
url.style.display = 'block';
url.style.fontSize = '12px';
const urlText = document.createTextNode(repo.url);
url.appendChild(urlText);
collapsibleBody.appendChild(url);
li.appendChild(collapsibleBody);
container.appendChild(li);
});
},
error: () => {
const container = document.getElementById('projectListContainer');
const div = document.createElement('div');
div.classList.add('center');
const txt = isEnglish
? 'Something went wrong or the request limit is reached, check back later!'
: 'Er is iets fout gegeaan of het maximum aantal requests is bereikt, kom later terug!';
const text = document.createTextNode(txt);
div.appendChild(text);
container.appendChild(div);
},
});
updateTable();
});
const updateTable = () => {
repos.forEach(repo => {
const tdLanguages = document.getElementsByClassName(`${repo.name}Lang`)[0];
tdLanguages.innerHTML = repo.languages.join(', ');
});
};
对于未经身份验证的请求,他们每小时最多限制 60 个请求。您可以通过验证 api 请求将此增加到每小时 5000。
所以当我几周前遇到这个问题时,我在 gihub 创建了 personal_auth_token
并在 headers
中传递了这个令牌,问题就解决了。
要生成 personal_auth_token
,请登录 github.com
,转到设置 -> 开发人员设置 -> 个人访问令牌 并生成一个。
在 Auhtorization: *token*
下的 headers
中传递此令牌。所以在你的 AJAX 请求中,它可能看起来像这样:
$.ajax({
url: *yourUrl*
...
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', *token*));
},
});
这里要注意的一件事是,如果存储库是 public,不要 将带有此 token
的代码推送到 github。这会立即被检测到并且 token
被撤销,您需要重新创建一个。
For API requests using Basic Authentication or OAuth, you can make up
to 5000 requests per hour. Authenticated requests are associated with
the authenticated user, regardless of whether Basic Authentication or
an OAuth token was used. This means that all OAuth applications
authorized by a user share the same quota of 5000 requests per hour
when they authenticate with different tokens owned by the same user.
For unauthenticated requests, the rate limit allows for up to 60
requests per hour. Unauthenticated requests are associated with the
originating IP address, and not the user making requests.
https://developer.github.com/v3/#rate-limiting
另一个在我的案例中有效的解决方案是解决代理服务器的 CORS
问题。在此,您只需将 API 请求 URL 附加到代理服务提供商,例如 https://cors-anywhere.herokuapp.com/
var url = "http://example.com/repo"; //your api request url,
var proxyUrl = `https://cors-anywhere.herokuapp.com/${url}`;
fetch(proxyUrl)... //Make a request with this proxy url to navigate CORS issue
说实话,GitHub REST API 不拒绝 CORS(参见 old document)。
即使你有CORS错误,那肯定是另一个问题。
就我而言,这是因为
- 旧信息:header 不需要
Authorization: bearer YOUR__TOKEN
但 Authorization: token YOUR_TOKEN
- 错误用法:仅输入错误
- CORS错误但成功:控制台returnsCORS错误,但连接成功
我正在使用 jQuery 和 ajax 向 GitHub API 发出获取请求,但是在我刷新大约 3 次后,请求开始失败说:
Access to XMLHttpRequest at 'https://api.github.com/users/X/repos' from origin 'my domain' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
尽管如此,我已经将我的域注册为 GitHub OAuth 应用程序。
这是我的 javascript:
let repos = [];
const isEnglish = document.documentElement.lang == 'en';
class Repo {
constructor(name, description, webUrl, apiUrl) {
this._name = name;
this._description = description;
this._webUrl = webUrl;
this._apiUrl = apiUrl;
this._languages = [];
this.fetchLanguages();
}
get name() {
return this._name;
}
get description() {
return this._description;
}
get url() {
return this._webUrl;
}
get languages() {
return this._languages;
}
set languages(value) {
this._languages = value;
}
async fetchLanguages() {
const url = this._apiUrl + '/languages';
await $.ajax({
url: url,
complete: data => {
this._languages = Object.keys(data.responseJSON);
},
});
}
}
$(document).ready(async () => {
$.ajax({
url: 'https://api.github.com/users/X/repos',
complete: xhr => {
repos = xhr.responseJSON.map(json => {
return new Repo(json.name, json.description, json.html_url, json.url);
});
// build up list based on data
const container = document.getElementById('projectListContainer');
repos.forEach(repo => {
const li = document.createElement('li');
//header
const collapsibleHeader = document.createElement('div');
collapsibleHeader.classList.add('collapsible-header');
const headerText = document.createTextNode(repo.name);
collapsibleHeader.appendChild(headerText);
li.appendChild(collapsibleHeader);
//body
const collapsibleBody = document.createElement('div');
collapsibleBody.classList.add('collapsible-body');
const description = document.createElement('p');
const descText = document.createTextNode(repo.description);
description.appendChild(descText);
collapsibleBody.appendChild(description);
const languages = document.createElement('p');
languages.style.marginTop = '1rem';
const langTxt = isEnglish ? 'Languages used: ' : 'Talen gebruikt: ';
const langText = document.createTextNode(langTxt + repo.languages);
languages.appendChild(langText);
collapsibleBody.appendChild(languages);
const url = document.createElement('a');
url.href = repo.url;
url.target = '_blank';
url.style.marginTop = '1rem';
url.style.display = 'block';
url.style.fontSize = '12px';
const urlText = document.createTextNode(repo.url);
url.appendChild(urlText);
collapsibleBody.appendChild(url);
li.appendChild(collapsibleBody);
container.appendChild(li);
});
},
error: () => {
const container = document.getElementById('projectListContainer');
const div = document.createElement('div');
div.classList.add('center');
const txt = isEnglish
? 'Something went wrong or the request limit is reached, check back later!'
: 'Er is iets fout gegeaan of het maximum aantal requests is bereikt, kom later terug!';
const text = document.createTextNode(txt);
div.appendChild(text);
container.appendChild(div);
},
});
updateTable();
});
const updateTable = () => {
repos.forEach(repo => {
const tdLanguages = document.getElementsByClassName(`${repo.name}Lang`)[0];
tdLanguages.innerHTML = repo.languages.join(', ');
});
};
对于未经身份验证的请求,他们每小时最多限制 60 个请求。您可以通过验证 api 请求将此增加到每小时 5000。
所以当我几周前遇到这个问题时,我在 gihub 创建了 personal_auth_token
并在 headers
中传递了这个令牌,问题就解决了。
要生成 personal_auth_token
,请登录 github.com
,转到设置 -> 开发人员设置 -> 个人访问令牌 并生成一个。
在 Auhtorization: *token*
下的 headers
中传递此令牌。所以在你的 AJAX 请求中,它可能看起来像这样:
$.ajax({
url: *yourUrl*
...
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', *token*));
},
});
这里要注意的一件事是,如果存储库是 public,不要 将带有此 token
的代码推送到 github。这会立即被检测到并且 token
被撤销,您需要重新创建一个。
For API requests using Basic Authentication or OAuth, you can make up to 5000 requests per hour. Authenticated requests are associated with the authenticated user, regardless of whether Basic Authentication or an OAuth token was used. This means that all OAuth applications authorized by a user share the same quota of 5000 requests per hour when they authenticate with different tokens owned by the same user.
For unauthenticated requests, the rate limit allows for up to 60 requests per hour. Unauthenticated requests are associated with the originating IP address, and not the user making requests.
https://developer.github.com/v3/#rate-limiting
另一个在我的案例中有效的解决方案是解决代理服务器的 CORS
问题。在此,您只需将 API 请求 URL 附加到代理服务提供商,例如 https://cors-anywhere.herokuapp.com/
var url = "http://example.com/repo"; //your api request url,
var proxyUrl = `https://cors-anywhere.herokuapp.com/${url}`;
fetch(proxyUrl)... //Make a request with this proxy url to navigate CORS issue
说实话,GitHub REST API 不拒绝 CORS(参见 old document)。
即使你有CORS错误,那肯定是另一个问题。
就我而言,这是因为
- 旧信息:header 不需要
Authorization: bearer YOUR__TOKEN
但Authorization: token YOUR_TOKEN
- 错误用法:仅输入错误
- CORS错误但成功:控制台returnsCORS错误,但连接成功