Go + Firebase で短縮URL生成ツールを作る

息抜きに Go と Firebase を使って短縮URL生成ツールを作ってみました。
ところどころ雑な部分が目立ちますが、大目にみてください。
https://github.com/suhaya3317/short-url
では、早速解説にいってみたいと思います。

# Firebaseプロジェクトを作る

https://console.firebase.com
でプロジェクトを作ります。
# Dynamic Linksの設定

メニューの「拡大」のところに「Dynamic Links」があるのでクリックして開きます。
<img width="1152" alt="スクリーンショット 2019-02-14 10.52.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/213446/855123f5-b848-48fe-c426-a48c40eecda4.png">

そのまま「始める」を押すと、以下の画面になります。
サブドメインをカスタマイズできるので、自分のお好みに設定してください。
<img width="1152" alt="スクリーンショット 2019-02-14 10.52.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/213446/e1c8f786-b156-1304-4e5f-fadb0b4f3878.png">

無事、作成が完了すると以下の画面になります。
これでDynamic Linksの設定は完了です。
<img width="1152" alt="スクリーンショット 2019-02-14 10.53.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/213446/044436d2-a398-bc4b-7723-30f8e037c0ee.png">

# Go
次に実際のコードを見ていきましょう。
* エラーハンドリングはしてません。。

## conifg.envの作成
ファイル内には

- FirebaseのAPIキー
- 上記で設定したドメイン

を書き込んでおきます。
FirebaseのAPIキーは、Firebaseプロジェクトの設定ページの「ウェブ API キー」です。

```config.env
FIREBASE_KEY=*****************************
DOMAIN=https://example.page.link
```

## .envファイルを読み込む
`github.com/joho/godotenv`というパッケージを使用しています。
https://godoc.org/github.com/joho/godotenv

```terminal
$ go get github.com/joho/godotenv
```

```main.go
err := godotenv.Load("config.env")
if err != nil {
	panic(err)
}
```

## リクエスト先のURLを設定する

```main.go
const dynamicLinksApiUrl = "https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key="
url := dynamicLinksApiUrl + os.Getenv("FIREBASE_KEY")
```
## 短縮したいURLを取得する
コマンドラインパラメータから取得しています。

```main.go
longLink := os.Args[1]
```
## 必要な情報を詰めていく
リクエストする際のjsonは以下のようなものです。

```json
{
   "longDynamicLink": "https://example.page.link/?link=https://example.com/aaa/bbb/ccc/ddd/eee",
   "suffix": {
     "option": "SHORT"
   }
}
```
`longDynamicLink`は`設定したドメイン`+`/?link=`+`短縮したいURL`となっていて、
`option`は`SHORT`または`UNGUESSABLE`を入れることができます。
*
`SHORT` 👉 パスコンポーネントが4文字(`https://example.page.link/WXYZ`)
`UNGUESSABLE` 👉 パスコンポーネントが17文字(`https://example.page.link/UVWXYZuvwxyz12345`)

```main.go
type RequestJson struct {
	LongDynamicLink string `json:"longDynamicLink"`
	Suffix          `json:"suffix"`
}

type Suffix struct {
	Option string `json:"option"`
}

// SHORTを指定しているため、パスコンポーネントは4文字になる
requestJson := &RequestJson{os.Getenv("DOMAIN") + "/?link=" + longLink, Suffix{"SHORT"}}
requestJsonByte, err := json.Marshal(requestJson)
if err != nil {
	panic(err)
}

// *Request(req)を作ります。
req, err := http.NewRequest("POST", url, bytes.NewReader(requestJsonByte))
if err != nil {
	panic(err)
}
// リクエストヘッダーをセットします。
req.Header.Set("Content-Type", "application/json")
```
## リクエストする

```main.go
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
	panic(err)
}
```

## レスポンスをパースする
レスポンスのjsonは以下のようなものです。

```json
{
	"shortLink": "https://examle.page.link/****",
	"previewLink": "https://examle.page.link/****?d=1"
}
```

```main.go
body, err := ioutil.ReadAll(res.Body)
if err != nil {
	panic(err)
}
defer res.Body.Close()

type ResponseJson struct {
	ShortLink   string
	PreviewLink string
}

var responseJson ResponseJson
err = json.Unmarshal(body, &responseJson)
if err != nil {
	panic(err)
}
```
## 出力する

```main.go
fmt.Print(responseJson.ShortLink)
```

## ビルドする

```terminal
$ go build main.go
```

## 実行する

```terminal
$ ./main 短縮したいURL
```

# 参考文献
https://firebase.google.com/docs/dynamic-links/rest?hl=ja
https://qiita.com/ryo_hisano/items/ffbba33d4737664626e8