simplify the life

获取某用户在 GitHub 上所 star 的项目总数以及 star/unstar api 的一个小坑

获取 star 项目总数

由于 StarsKeeper 开发需要,需要获取某用户在 GitHub 上所 star 的项目的总数,记录如下。

一开始想到的是 user 有关的 api,开发中 headers 头上加上 Authorization Token,其实就是这个 api https://api.github.com/user。但是这里有 followers 和 following 数量,却没有 starred repo 的数量。

SO 上搜了下,果然有 类似问题。方法很简单,有点 hack 的意思。以用户 hanzichi 为例,请求 https://api.github.com/users/hanzichi/starred?per_page=1 即可(如果加上 Authorization Token,那么就是 https://api.github.com/user/starred?per_page=1),我们可以在命令行敲下如下代码:

curl -I "https://api.github.com/users/hanzichi/starred?per_page=1"

得到返回如下:

HTTP/1.1 200 OK
Date: Sat, 01 Sep 2018 08:41:02 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 5900
Server: GitHub.com
Status: 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1535794862
Cache-Control: public, max-age=60, s-maxage=60
Vary: Accept
ETag: "c19c7d6569715474d9f0d49b10717584"
X-GitHub-Media-Type: github.v3; format=json
Link: <https://api.github.com/user/10890665/starred?per_page=1&page=2>; rel="next", <https://api.github.com/user/10890665/starred?per_page=1&page=692>; rel="last"
Access-Control-Expose-Headers: ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
X-Runtime-rack: 0.049747
Vary: Accept-Encoding
X-GitHub-Request-Id: 9E01:4809:1EEAAE:291ED5:5B8A509C

有用的其实就是 Link:

Link: <https://api.github.com/user/10890665/starred?per_page=1&page=2>; rel="next", 
<https://api.github.com/user/10890665/starred?per_page=1&page=692>; rel="last"

关注下 692 这个数字,其实就是结果。

该问答里还有个 补充回答,如果返回 repos 的数量是 0 或者 1,那么是没有 Link 这个 header 返回的,如果没有,则用 repo.length 可以获取。

在 GitHub API 中,这个 Link header 和页码有关,详情可以看 https://developer.github.com/v3/#pagination

这个 header value 有些奇怪,其实它是 RFC5988 HTTP header,我们可以用 parse-link-header 这个包去解析它得到对象。

后端用 node-fetch 实现:

const fetch = require('node-fetch')
const parse = require('parse-link-header')

module.exports.getStarredRepoCount = token => {
  return new Promise(resolve => {
    fetch('https://api.github.com/user/starred?per_page=1', {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': "token " + token,
      }
    })
    .then(res => {
      let linkHeader = res.headers.get('Link')
      if (linkHeader) {
         resolve(parse(linkHeader).last.page)
      } else {
        return res.json().then(res => {resolve(res.length)})
      }
    })
    .catch(e => {
      console.log(e)
    })
  })
}

如果没有 linkHeader 的情况下,必须 return res.json() 才能在下一步 resolve(res.length),不能直接 resolve(res.json().length) 一步到位,因为 res.json() 返回的是一个 promise。fetch 用的还不是很多,坑不少啊。

另外要注意的是 res.headers 也不能直接 resolve 到客户端,客户端会得到空对象,如果需要处理或者遍历 headers,最好在服务端做。

star/unstar api 的一个小坑

(2018/09/05 add)

今天在做 repo 的 star/unstar 功能时,碰到了一个小坑,记录如下。

官方提供的 api 看起来很简单(注意,必须获得 token 后才能用这个 api),之前已经做过 OAuth,也获得了 token,但是和之前一样操作去请求,总是返回 404,也不是报没有权限的错误(token 过期),所以我一直怀疑 api 路径是不是有问题,百思不得其解。

直到找到 这个解答,果然 SO 还是万能的!具体文档在 这里。简单的说,在 OAuth 的时候,之前设置的链接长这样 https://github.com/login/oauth/authorize?client_id=ab8b599de3eb9f9633cd,现在加上 scope=repo 即可 https://github.com/login/oauth/authorize?client_id=ab8b599de3eb9f9633cd&scope=repo

上个月 23 号开始做的 GitHub stars 管理工具 StarsKeeper 目前已经初具雏形,UI 部分参考了 OhMyStar2,目前实现的功能也类似 OhMyStar2。放个简单截图以供留念:

posted on 2018-09-01 17:30 子迟 阅读(...) 评论(...) 编辑 收藏

导航

统计信息

News