V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
jrainlau
V2EX  ›  分享创造

基于 Github API 的图床 Chrome 插件开发全纪录

  •  1
     
  •   jrainlau · 2019-05-09 10:08:32 +08:00 · 3763 次点击
    这是一个创建于 1806 天前的主题,其中的信息可能已经有所发展或是发生改变。

    image

    最近基于 Github API 开发了一款图床 Chrome 插件 Picee,现在已经开源并上架 Chrome 应用商店。当中的过程涉及到一些有趣的知识点,故将其记录下来。

    Github 地址: https://github.com/jrainlau/picee

    Chrome 商店下载地址:Picee

    灵感

    平时有写点东西的习惯,但是奈何一直找不到合适的图床。有人推荐以微博或者七牛来做图床,但是总给我一种”受制于人“的感觉,不知道什么时候就会被各种限制,比如禁止图片外链等等。后来发现其实 Github 是非常适合做图床的,因为仓库里的文件都可以通过 https://raw.githubusercontent.com 这个链接直接外链以供下载。但是如果为了写个文章而每次添加图片都需要一顿 Git 操作,那么写作体验必定非常不好,如果有更方便的办法就好了——那就是 Github API。

    Github API

    Github 提供了一套完善的 API 以供操作,几乎涵盖了开发一个完整 Github 客户端的所有功能。API 分为 REST 风格的 v3 版本和 GraphQL 风格的 v4 版本。为了使用方便,我选择的是 v3 版本。具体的 API 细节可以在官方文档查看。

    要制作一个图床应用,我们只需要用到上传文件的 API 即可。但是在调用这个 API 之前,首选需要用户对应用进行授权,也就是所谓的登录操作。

    授权

    对于一般的”查看”操作,是不需要授权的,比如获取用户的公开信息,获取公有仓库的 issues 等等。但是有两个场景是需要授权的,其一是任何对于仓库的“增删改查”操作(包括提交 issue,评论等);其二则是对于某 IP 有 API 的调用次数限制,若这个 IP 调用 Github API 的次数过多则需要授权。

    那么授权应该怎么做呢?官方提供了三种办法,分别是 BasicoAuth2 tokenoAuth2 key/secret

    Basic 授权

    也就是最传统的账号密码授权方式,我们可以在命令行用 curl 来测试之:

    curl -u "账号:密码" https://api.github.com
    

    如果是正确的账号密码,则会返回一系列的内容,否则会返回错误信息。

    对于开发来说,我更推荐使用 Postman 来对 API 进行测试:

    image

    点开右边的 code,可以看到 JS 代码: image

    其中 xhr.setRequestHeader("Authorization", "Basic xxxxxx");就是我们需要设置的授权 header,当中的 xxxxxx 是这么来的:

    btoa(username + ':' + password)
    

    oAuth2 token 授权

    对于账号密码来说,轻易地在第三方平台输入其实并不那么安全,那么有没有办法既能保障账户的安全,又能实现授权的需求呢?答案就是 oAuth token。

    简单来说,oAuth token 相当于用户提供给第三方的一张授权令牌,第三方通过这张令牌可以获得用户所允许使用的一系列权限,但是却不会知晓用户的账号和密码,于是便得以在有效保障用户账号安全的同时,又能方便地对第三方应用进行授权。

    在 Github 里,可以在这个地方设置生成具有某些权限的 token:

    image

    最后在 Postman 里选择 OAuth 2.0 或者 Bearer Token,然后把这串 token 粘贴进去即可。

    image

    其中的授权 header 为 Bearer token

    oAuth 2 key/secret 授权

    这种授权方式是通过生成一对 key/secret,来允许第三方获取用户的公开信息,是一种只读的授权方式,无法对仓库进行改写操作,主要用于第三方登录,故在这里不适用。更多关于 key/secret 的内容可以查看阮一峰的《 GitHub OAuth 第三方登录示例教程》,写得非常生动详细。


    在了解了三种授权方式之后,我们就可以进行下一步操作,实现图片的上传了。

    图片上传 API

    图片上传使用了 content API 的 create-a-file 接口,通过 PUT 发送一条文件内容为 base64 的请求到指定的仓库目录。

    image

    这里着重圈出了必须把文件进行 base64 编码,否则接口调用将会出错。

    通过 btoa('hello world) 方法把 hello world 转成 base64,然后放在 Postman 里测试一下:

    image

    image

    看来效果是 OK 的,接下来就是对图床插件进行开发的步骤了。

    Chrome 插件开发

    除了看官方文档学习插件开发以外,也可以参考由 @小茗同学 所写的《 [干货] Chrome 插件(扩展)开发全攻略》,里面对于 Chrome 插件的开发有着详细的叙述,非常值得一读。

    读完上面推荐的文章之后,我选择使用 VueJS 进行开发。由于项目比较简单,所以我没有用任何的打包工具,直接通过 script 的方式引入 VueJS。值得注意的是,Chrome 插件不允许行内 script 和行内 style,所以任何的 css 和 js 文件都必须通过本地文件链接的方式去使用。另外由于我们的 JS 是运行在 Chrome 环境的,所以可以放心大胆地使用 es 模块和 async/await 等高级语法,而无需任何的构建工具参与。

    但是在使用 VueJS 的第一步我就遇到了问题,绑定了 new Vue() 的 DOM 元素竟然显示不出来。经过查证,原来 Chrome 插件有 Content Security Policy (CSP) 限制,默认是不支持 eval()new Function() 等方式运行代码的,而完整版的 VueJS 恰好是这么干的(官网有说),所以就出问题了。那么怎么解决呢?很简单,在 manifest.json 里面声明一下就好了:

    // manifest.json
    
    {
      // ...
      "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
    }
    

    这里我采用的是 popup 形式的插件,弹出来的窗口就是项目所定义的 index.html。如果要调试插件的页面,可以直接在插件弹出的窗口点击右键,然后点击“检查”,就会弹出我们熟悉的开发者工具了。如果插件文件有改动,除了重新打开插件以外,我们也可以在开发者工具通过 cmd + r 去直接刷新,省去了多次点击的麻烦。

    功能实现

    经过前面的准备,我们已经掌握了如何对 Github API 进行授权然后上传图片的办法,接下来就是在业务逻辑里去实现它们。我封装了一下原生的 fetch 方法,让它更方便调用:

    const $fetch = (options) => {
      return window.fetch(options.url, {
        method: options.method || 'GET',
        headers: {
          "Content-Type": "application/json",
          "Authorization": localStorage.getItem('picee_token')
        },
        body: JSON.stringify(options.body) || null,
        mode: 'cors'
      })
        .then(async res => {
          if (res.status >= 200 && res.status < 400) {
            return {
              status: res.status,
              data: await res.json()
            }
          } else {
            return {
              status: res.status,
              data: null
            }
          }
        })
        .catch(e => e)
    }
    
    export default $fetch
    

    请求接口时携带的授权 header 所需的 token,我把它们存放在插件的 localStorage 下,方便调用。

    有了请求接口的方法以后,接下来就要完成选择图片和把图片转化成 base64 的工作。这里我复用了另一个作品里的 chooseImg.jspaste.js 方法,最终能够支持以选择、粘贴、拖拽的方式上传图片。

    剩下的一些功能细节就不赘述了,代码非常简单,建议读者们自行查阅。

    应用发布

    准备好了 logo,描述等善后工作之后,就可以正式提交应用发布了。我们可以在开发者信息中心里面把插件提交上去,填入必要的信息以后点击发布,等待审核完成。但是在此之前,你必须支付 5 美元的开发者注册费,国内的开发者在完成这一步的时候可能会遇到蛮大的困难,这一个问题在知乎也有讨论:如何在中国使用信用卡支付“ Chrome 网上应用店”开发者注册费?。我是通过万能的淘宝搞定的。

    在完成注册之后和发布以后,就能看到插件的主页了:

    chrome google com_webstore_detail_picee_nmeeieecbmdnilkkaliknhkkakonobbc(iPad)

    值得注意的是,刚发布的插件是暂时不能被搜索出来的,需要等待一段时间以后才能搜索出来。

    image

    至此,整个插件的开发——发布流程就已经完成了。

    19 条回复    2019-05-10 12:33:10 +08:00
    erDaren
        1
    erDaren  
       2019-05-09 10:12:05 +08:00 via Android
    github 做图床,是不是有点...
    closedevice
        2
    closedevice  
       2019-05-09 10:13:49 +08:00
    目的很好..但是能不能换个其他存储,github 做图床,有点....
    Heanes
        3
    Heanes  
       2019-05-09 10:16:23 +08:00
    github 做图床,在国内速度一般吧,不过整个开发流程挺赞的
    mauve
        4
    mauve  
       2019-05-09 10:21:00 +08:00
    @erDaren 滥用?小声说,有一点
    haozes
        5
    haozes  
       2019-05-09 10:26:09 +08:00
    我倒觉得 github 做图床挺好的,就是操蛋的 chrome 安装了半天装不上插件
    Track13
        6
    Track13  
       2019-05-09 10:30:31 +08:00 via Android
    有点滥用了吧,而且速度感人
    heirenhua
        7
    heirenhua  
       2019-05-09 11:15:39 +08:00
    容量和速度 是个问题
    Lax
        8
    Lax  
       2019-05-09 11:24:19 +08:00
    咱楼主动手精神。
    楼上朋友说速度一般真是太客气了
    fumichael
        9
    fumichael  
       2019-05-09 11:46:58 +08:00
    github issues 的图有时会莫名其妙的挂掉的
    Rcnaec
        10
    Rcnaec  
       2019-05-09 12:18:07 +08:00 via Android
    滥用了吧
    Kyon945
        11
    Kyon945  
       2019-05-09 12:19:24 +08:00 via iPhone
    楼上说滥用的……

    很早前就有人问过,Github 官方回复过这个问题了啊:不算滥用。
    kisara
        12
    kisara  
       2019-05-09 13:57:41 +08:00 via iPhone
    @erDaren
    @Rcnaec
    @Track13

    GitHub 做图床为什么是滥用? GitHub 本身鼓励大家把博客主页放在 GitHub 上 我觉得微博当图床才算滥用
    fengbjhqs
        13
    fengbjhqs  
       2019-05-09 14:05:03 +08:00
    github 应该没说过可以当外链图片, 担心他会把外链给封了,不太敢用
    jamblues
        14
    jamblues  
       2019-05-09 14:11:20 +08:00 via iPhone
    搭一层 github 反向代理+缓存 既不会超额被封 又能起到备份的作用 还可以用 nginx 去做缩略图等等等等 不能多说了 我搬砖去了
    suyuyu
        15
    suyuyu  
       2019-05-09 14:38:54 +08:00
    速度实在受不了-- 不过感谢开源
    DAPTX4869
        16
    DAPTX4869  
       2019-05-09 17:20:29 +08:00
    用了下 感觉不错
    以后不用搞图床了
    jiejiss
        17
    jiejiss  
       2019-05-10 09:46:05 +08:00
    速度太慢了……
    cnguangming
        18
    cnguangming  
       2019-05-10 12:32:18 +08:00
    赞👍
    jason94
        19
    jason94  
       2019-05-10 12:33:10 +08:00
    github 的图片是不是会过期?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2580 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 16:01 · PVG 00:01 · LAX 09:01 · JFK 12:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.