Object Change NotificationをApp Engineで受け取る設定

Google Cloud Storage の [Object Change Notification](https://cloud.google.com/storage/docs/object-change-notification) をGoogle App Engineで受け取るための設定方法。
だいたい公式Documentの日本語訳みたいなものだけど、ちょいちょい注意点なんかもいれていくよ。

因みに Google Calendarの [Push Notification](https://developers.google.com/google-apps/calendar/v3/push?hl=en)を使う場合も同じような設定が必要なはず。

# Object Chage Notification (OCN) とは？

Google Cloud Storage (GCS) にObjectがUpload/Replace/Deleteされた時に、指定したURLへHTTPS POSTで通知を送ってくれる機能。
UserがUploadした画像にサムネイル作ったりとか、Uploadされたcsvを自動でBigQueryに取り込むとかやりたい時に使う。
設定はbucket単位で、一つのbucketに複数の設定を行うこともできる。

## OCNへのResponseについて

OCNのRequestへのResponseとしてError Responseを返した場合、自動でリトライされる。
また、OCNへのResponseを20sec以内に返せなかった場合も、Errorとみなされて、リトライに入る。
リトライ間隔は最初は30secで、リトライする度に長くなっていき、最長90minにとなり、7日間リトライを続けます。

## Success, Failure Response Code List

### Success

* 102 Processing
* 200 OK
* 201 Created
* 202 Accepted
* 204 No Content

### Failure

* 401 Unauthorized
* 404 Not Found
* 500 Internal Server Error
* 502 Bad Gateway
* 503 Service Unavailable
* 504 Gateway Timeout

# App EngineでOCNを受け取れるようにする

## Domain Verify

OCNを送る先のApplicationのDomainを自分が持っていることを証明します。

### [Web Master Tool](https://www.google.com/webmasters/tools)にアクセス

### Add Property をクリック
### App Engine ApplicationのURLを入力
ここで注意することが、httpsで設定してやることです。httpsで設定しなかった場合、後で行うPush Notificationの設定が通りません。
App EngineのModuleを使おうと思っている場合も、ここでModuleにアクセスするようにURLを設定します。今回はocn-receiverというModuleを使おうと思っているので、https://ocn-reciever-dot-{application id}.appspot.comで設定しています。

![Screen Shot 2015-08-10 at 11.02.02.png](https://qiita-image-store.s3.amazonaws.com/0/15640/c29c111e-fd00-7d42-4b6a-573553a959d9.png)

### Domain Verify

Domain Verifyする方法はいくつかありますが、App Engineでやりやすい方法は2つ

* Web Master Toolが指定したHTML FileをDomainにdeploy
* Web Master Toolが指定したHTML Tagが入っているHTMLをDomainにdeploy

どちらでもやりやすい方を使ってください。
完了したら、こんな画面になります。

![Search_Console_-_Home.png](https://qiita-image-store.s3.amazonaws.com/0/15640/449b7c97-90b7-d49a-e9b1-6194351daf43.png)

### Push Notification Add domains

OCNを設定するbucketがあるGCP Projectで、Push Notificationを送ることができるDomainを追加

* API Manager -> Credentials -> Domain verification -> Add domainをクリック

<img width="780" alt="Screen Shot 2016-07-07 at 19.34.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/15640/606fa06a-2402-c905-a9db-54b6071a8943.png">

* `{youar application app id}.appspot.com` を登録

App EngineのModuleを使おうと思っている場合は、ここでModuleにアクセスするようにDomainを設定します。今回はocn-receiverというModuleを使おうと思っているので、 `ocn-reciever-dot-{application id}.appspot.com` で設定しました。
`https://ocn-reciever-dot-{application id}.appspot.com` で登録すると、gsutilでOCNを設定しようとした時に、`BadRequestException: 400 No valid domain for WebHook callback`と言われてしまうので注意！

これでApp EngineでOCNを受け取る準備は完了！

# BucketにOCNを設定する

## Service Account

OCNの設定するためにはService Accountが必要です。
Service Accountを作成していない場合は、まず以下の手順でDevelopers Consoleから作成してください。

* APIs & auth > Credentials.
* Create new Client IDをクリック
* Service Accountを選択
* Okayをクリック

## Service AccountにbucketのFull Controlを与える

Service AccountがBucketを扱えるようにACLを追加します。
因みにService AccountがProjectのEditorに入っていれば、この設定は無くても大丈夫かもしれません。

```
gsutil acl ch -u {your service account}@developer.gserviceaccount.com:FC gs://{your bucket name}
```

## gcloudのAccountをService Accountに設定

OCNをgsutilで設定するために、gcloud sdkの認証をService Accountに設定します。

```
$ gcloud auth activate-service-account {service-account-email} --key-file path/to/key.json
```

service-account-email, path/to/key.jsonは自分のService AccountのEmail, key.jsonを利用します。
key.jsonはService accountのCreate Keyをクリックすればdownloadできます。

gcloud auth listで以下のようになっていれば、OK

```
$ gcloud auth list
Credentialed accounts:
 - {your service account}.gserviceaccount.com (active)
```

## OCN設定

いよいよOCNを設定します。
設定はgsutil notification watchbucketで行います。
この時に返ってくるレスポンスのWatch channel identifier, resource identifierが無いと、OCNを止めれないので、保存しておいた方が良いです。
これを忘れると、今のところOCNのRequestのHeaderを見るしかなくなるので、必ずOCNを受け取ることができるWeb Applicationが必要になります。

```
$ gsutil notification watchbucket https://ocn-receiver-dot-cp300demo1.appspot.com/notify gs://{your bucket name}

Watching bucket gs://cp300demo1-ocn/ with application URL https://ocn-receiver-dot-cp300demo1.appspot.com/notify ...
Successfully created watch notification channel.
Watch channel identifier: ※※※※※※※※※※※
Canonicalized resource identifier: ※※※※※※※※※※※
Client state token: None
```

## OCNを止める

設定するとファイルをUpload,Deleteする度に、OCN Messageが飛んでくるので、止めたい！と思った時は、gsutilで設定を消します。
この時に必要になるのがchannel identifier, resource identifierなので、OCNを設定した時に、何処かにメモって置くのが良いです。
メモってない場合、OCNをWeb Applicationで受け取って、Headerを見ることになります。

```
$ gsutil notification stopchannel {channel identifier} {resource identifier}
```