基於 Github API 的圖床 Chrome 外掛開發全紀錄

jrainlau發表於2019-05-09

image

最近基於 Github API 開發了一款圖床 Chrome 外掛 Picee,現在已經開源並上架 Chrome 應用商店。當中的過程涉及到一些有趣的知識點,故將其記錄下來。

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

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

至此,整個外掛的開發——釋出流程就已經完成了。

相關文章