NO IMAGE

【Go】GitHub上の「特定の1ファイル」を取得する

NO IMAGE

Go言語でAPIを使う練習のため、タイトルにある「GitHubのリポジトリにある特定の1ファイルの内容を取得する」プログラムを書いてみました。

Contents

取得するファイル(GitHubリポジトリ側)

今回はチュートリアル用のリポジトリから、以下のようなREADME.mdのコンテンツを取ってきてみたいと思います。

This is a script for API-tutorial- feature-A- fix-B- feature-C

プログラム全文

package mainimport ("encoding/base64""encoding/json""fmt""io/ioutil""net/http")func main() {blobUrl := "https://api.github.com/repos/fugithora812/git-tutorial/contents/README.md"req, err := http.NewRequest("GET", blobUrl, nil)if err != nil {fmt.Println("failed: NewRequest")}req.Header.Set("Accept", "application/vnd.github.v3+json")client := new(http.Client)resp, err := client.Do(req)if err != nil {fmt.Println("failed: DoReq")}defer resp.Body.Close()contents, err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println("failed: ReadAll")}var blob interface{}err = json.Unmarshal(contents, &blob)if err != nil {fmt.Println("failed: Unmarshal")}src := blob.(map[string]interface{})["content"]dec, err := base64.StdEncoding.DecodeString(src.(string))fmt.Println(string(dec))}

実行結果

$ go run main.goThis is a script for API-tutorial- feature-A- fix-B- feature-C

解説

少し解説じみたことを書きます。上のmain()では、まずGitHubのAPIを用いてファイル情報を取得するための準備をしています。

blobUrl := "https://api.github.com/repos/fugithora812/git-tutorial/contents/README.md"req, err := http.NewRequest("GET", blobUrl, nil)if err != nil {fmt.Println("failed: NewRequest")}req.Header.Set("Accept", "application/vnd.github.v3+json")

リクエストのヘッダには、{"Accept": "application/vnd.github.v3+json"}を指定します(⇒Resources in the REST API – GitHub Docs)。もし取得先のリポジトリがプライベートなものであれば、これに加えて適切な権限をもったパーソナルアクセストークンが必要です。トークンは以下のように設定できます。

token := {GitHubのPersonal Access Token}req.Header.Set("Authorization", fmt.Sprintf("token %s", token))

main()関数ではこのトークンの設定は行わず(パブリックなので)、実際にAPIリクエストを行っています。

client := new(http.Client)resp, err := client.Do(req)if err != nil {fmt.Println("failed: DoReq")}defer resp.Body.Close()

ここからAPIレスポンスの内容を取得していきます。GitHubのドキュメントによると、レスポンスとして返ってくるJSONデータは以下のような構造になっています。

{  "type": "file",  "encoding": "base64",  "size": 5362,  "name": "README.md",  "path": "README.md",  "content": "encoded content ...",  "sha": "3d21ec53a331a6f037a91c368710b99387d012c1",  "url": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md",  "git_url": "<https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1>",  "html_url": "https://github.com/octokit/octokit.rb/blob/master/README.md",  "download_url": "https://raw.githubusercontent.com/octokit/octokit.rb/master/README.md",  "_links": { "git": "<https://api.github.com/repos/octokit/octokit.rb/git/blobs/3d21ec53a331a6f037a91c368710b99387d012c1>", "self": "https://api.github.com/repos/octokit/octokit.rb/contents/README.md", "html": "https://github.com/octokit/octokit.rb/blob/master/README.md"  }}

ここで欲しいのは、この中の”content”の値です。base64でエンコーディングされているので、そのデコード処理も行っています。

// レスポンスのJSON全体を(バイト列で)取得contents, err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Println("failed: ReadAll")}// jsonとして扱えるようUnmarshallして"content"の内容を取得var blob interface{}err = json.Unmarshal(contents, &blob)if err != nil {fmt.Println("failed: Unmarshal")}src := blob.(map[string]interface{})["content"]// 取得した"content"の値をデコードdec, err := base64.StdEncoding.DecodeString(src.(string))// ファイルの内容を出力fmt.Println(string(dec))

これで、ファイル内容の取得・出力ができました。

参考

NO IMAGE
最新情報をチェックしよう!