GCP上にAngular+Java8でWebサイトを構築【「本棚自慢」サイト開発日誌#3 - API定義】

# 経緯
Python3でのWebサイト構築を試みていたのだけど、諸般の事情で表題の技術セットに変更。
乗っける先としてはGAEというのは変えず、クライアントフレームワークとWebAPIの組み合わせにする。
WebAPIにする都合上、Cloud Endpoints を使用する。

# 環境
- 開発端末：Linux（Ubuntu 17.10）
- 言語：
  - フロントエンド：TypeScript（未定）
  - バックエンド：Java（v1.8.0_181）
- フレームワーク：
  - フロントエンド：Angular（未定）
  - バックエンド：？

## ＜前提＞
- GCPはアカウント取得済み。
- Google Cloud SDK取得・認証済み。

# 今日のお題
- リリース第１弾として実装する機能のピックアップ
- 機能の簡単なAPI定義

## ■リリース第１弾として実装する機能のピックアップ
Webサイトの主題が「本棚自慢」なので、自慢する本棚（の画像）を登録できないといけないし、登録した画像を参照できないといけない。
よって、まずは、以下の機能は必須。

- 本棚登録
- 本棚一覧表示

上記だけではサービスとしてあまりにも心許ないものの、今回のシステムで使うスキルがどれも勉強しながらということから、
BabyStepになることを想定し、機能は著しく絞ることにする。
（そもそも、仕事以外で実装に使える時間は日々限られるし、他にもやるべきことは山ほどある・・・）

### 「本棚」情報について
本棚（の画像）をアップしてもらい、タイトルや概要説明、撮影日時を付けてもらう想定。（その他必要な情報はおいおい）

### (1)API定義「本棚登録」

#### ●エンドポイント
http(s)://[ドメイン]/v0/bookshelf

#### ●HTTPメソッド
POST

#### ●認証
＊後回し＊

#### ●リクエスト
<pre>
{
  "bookshelfPath":"bookshelf/xxxxxxxx/zzzz.png",
  "bookshelfName":"ある日の本棚",
  "bookshelfDescription":"ある日の本棚の写真を撮ってみた。",
  "bookshelfShootingDatetime":1234567890
}
</pre>
|No|項目名|説明|
|:--|:--|:--|
|1|bookshelfPath|本棚画像のアップロード先パス|
|2|bookshelfName|本棚のタイトル|
|3|bookshelfDescription|本棚に対する説明|
|4|bookshelfShootingDatetime|本棚写真撮影日時（UnixTimestamp）|

#### ●レスポンス
##### 【正常系】
<pre>
{
  "bookshelfId":"xxxxxxxxxxxxxxxx"
}
</pre>

|No|項目名|説明|
|:--|:--|:--|
|1|bookshelfId|本棚のユニークID|

###### HTTPステータスコード
|ステータスコード|名前|説明|
|:--|:--|:--|
|200|OK|本棚画像の登録に成功|

##### 【異常系】
<pre>
{
  "errors":[
    {
      "innerCode":"E001-001",
      "message":"Unexpected Error",
      "see":"http://xxxxxxxx"
    },
    {
      "innerCode":"E002-002",
      "message":"Bad Bookshelf Name."
    }
  ]
}
</pre>

|No|項目名|説明|
|:--|:--|:--|
|1|errors|エラー群（複数"error"を保持）|
|1-1|error|エラー単体|
|1-1-1|innerCode|内部エラーコード|
|1-1-2|message|エラーメッセージ|
|1-1-3|see|参考URL（なくてもよい）|

###### HTTPステータスコード
|ステータスコード|名前|説明|
|:--|:--|:--|
|400|Bad Request|本棚情報の項目に誤りがある|
|500|Internal Server Error|本棚情報の登録時に予期せぬエラーが発生|
★その他、要検討。

#### ●レートリミット
＊後回し＊

### API定義「本棚一覧表示」

#### ●エンドポイント
http(s)://[ドメイン]/v0/bookshelfs

#### ●HTTPメソッド
GET

#### ●認証
＊後回し＊

#### ●リクエスト
<pre>
{}
</pre>
なし

#### ●レスポンス
##### 【正常系】
<pre>
{
  "bookshelfs":[
    {
      "bookshelfId":"xxxxxxxxxxxxxxxx",
      "bookshelfPath":"bookshelf/xxxxxxxx/zzzz.png",
      "bookshelfName":"ある日の本棚",
      "bookshelfDescription":"ある日の本棚の写真を撮ってみた。",
      "bookshelfShootingDatetime":1234567890
    },
    {
      "bookshelfId":"xxxxxxxxxxxxxxxx",
      "bookshelfPath":"bookshelf/xxxxxxxx/zzzz.png",
      "bookshelfName":"ある日の本棚",
      "bookshelfDescription":"ある日の本棚の写真を撮ってみた。",
      "bookshelfShootingDatetime":1234567890
    }
  ]
}
</pre>

|No|項目名|説明|
|:--|:--|:--|
|1|bookshelfs|本棚情報一覧|
|1-1|bookshelf|本棚情報|
|1-1-1|bookshelfId|本棚のユニークID|
|1-1-2|bookshelfPath|本棚画像のアップロード先パス|
|1-1-3|bookshelfName|本棚のタイトル|
|1-1-4|bookshelfDescription|本棚に対する説明|
|1-1-5|bookshelfShootingDatetime|本棚写真撮影日時（UnixTimestamp）|

###### HTTPステータスコード
|ステータスコード|名前|説明|
|:--|:--|:--|
|200|OK|本棚一覧の取得に成功|

##### 【異常系】
<pre>
{
  "errors":[
    {
      "innerCode":"E001-001",
      "message":"Unexpected Error",
      "see":"http://xxxxxxxx"
    },
    {
      "innerCode":"E002-002",
      "message":"Bad Bookshelf Name."
    }
  ]
}
</pre>

|No|項目名|説明|
|:--|:--|:--|
|1|errors|エラー群（複数"error"を保持）|
|1-1|error|エラー単体|
|1-1-1|innerCode|内部エラーコード|
|1-1-2|message|エラーメッセージ|
|1-1-3|see|参考URL（なくてもよい）|

###### HTTPステータスコード
|ステータスコード|名前|説明|
|:--|:--|:--|
|500|Internal Server Error|本棚情報の登録時に予期せぬエラーが発生|
★その他、要検討。

#### ●レートリミット
＊後回し＊

# 参考
Web API: The Good Parts
https://www.oreilly.co.jp/books/9784873116860/