フロントから Contentful への POST リクエストの方法がドキュメントを見ても分かりにくかったのでまとめた

# はじめに
JAMStack でサービスを作りたいなと思い、前から気になってたヘッドレス CMS の Contentful を使ってみました。
ブラウザから投稿するのは簡単でしたが、フロントから Contentful へ POST リクエストをする方法がドキュメントを見ても分かりにくかったのでまとめました。
いろんな方法があると思うので、あくまで一例として参考になれば幸いです。

##設定条件
**【対象】 Contentful を導入済みで、すでに GET の方法までは確認済みの方。**

- contentful-cli を入れる([contentful-cli 導入コマンド確認](https://www.npmjs.com/package/contentful-cli))


**【ゼロから始める場合】以下の設定から始めます。**

- Nuxt.js でディレクトリを作る([nuxt パッケージをインストール](https://ja.nuxtjs.org/guide/installation))
- [Contentful を導入する](https://www.contentful.com/)

Contentful の導入から GET まではこちらの記事が参考になります :point_down_tone2:
(引用：[ぐるたかログ「 Nuxt に Contentful を設定する方法。導入からデータ取得までの流れをまとめてみた【スクショあり】」](https://gurutaka-log.com/nuxt-contentful-setting))

## POST 用に API キーを作成する
自分専用の POST 用 API キー（トークン）を作成する必要があります。

### ① Contentful 上で、作成済のスペースのメニューの Settings で API Keys を選択
![スクリーンショット 2020-05-07 17.16.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296366/e763861b-e4e2-c5d4-d9bd-2749ff3216c9.png)

### ② Content management tokens を選択し、「 Generate personal token 」ボタンで自分専用のトークンを作成する（トークンはメモしておく:writing_hand_tone2:）
![スクリーンショット 2020-05-07 17.15.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296366/c4484dcb-be7f-85dd-496d-3a1b7b6dfd6e.png)

##環境 ID ・コンテントタイプ ID を確認（メモする:writing_hand_tone2:）

環境 ID・・・スペースのメニュー「 Setting 」 →　「 Environments 」 →　「 Environment ID 」
<img width="1130" alt="スクリーンショット 2020-05-07 13.23.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296366/c58292a0-1110-7a55-4d51-0a66f6438617.png">


コンテントタイプ ID ・・・スペースのメニュー「 Content 」 →　「 Info 」 →　「 CONTENT TYPE ID 」
<img width="815" alt="スクリーンショット 2020-05-07 17.41.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296366/44d6f0b6-6105-900e-0227-6145728c313f.png">

## .env で変数にして nuxt.config.js に追記する

.env にメモした上記 3 つを追記します。今回自作したトークンは「 CTF_FOR_MY_APP_TOKEN 」としています。
その後、nuxt.config.js ファイルの env 欄に下記のように追記します。
<img width="428" alt="スクリーンショット 2020-05-07 18.11.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296366/fa546856-4ef1-19e0-46dc-af6af8ad2220.png">

## スクリプトにコードを記述
POST 用のページを今回は Nuxt.js で作成しているので、script タグ以下に記述。
フォーム入力のデータは v-model で紐付けをしています。
まずは必要な定数を定義します。
トークンは先程設定した自作トークンの内容です。

```js:new.vue
const contentful = require('contentful-management')
const client = contentful.createClient({
  accessToken: process.env.CTF_FOR_MY_APP_TOKEN
})
```
フォームのデータ部分も最初は null で入力しておきます。（単語帳として、v-model で紐付け済）

```js:new.vue
data() {
  return {
    formData: {
      word: null,
      meaning: null
    }
  }
},
```

### POST 用のメソッドを作成
Contentful のスペースにアクセスして、環境 ID を呼び出し新規エントリー（POST 内容）を作成する流れです。
環境 ID なしで最初行いましたが、非推奨ということなので書き換えました。
createEntry する際はコンテントタイプ ID が必要になります。


```js:new.vue
methods: {
  async postWord() {
    const mySpace = await client.getSpace(process.env.CTF_SPACE_ID)
    const myEnvironment = await mySpace.getEnvironment(
      process.env.CTF_ENVIRONMENT_ID
    )
    const res = await myEnvironment.createEntry(
      process.env.CTF_CONTENT_TYPE_ID,
      {
        fields: {
          word: {
            'en-US': this.formData.word
          },
          meaning: {
            'en-US': this.formData.meaning
          }
        }
      }
    )
    await res.publish()
    console.log(res)
  }
}
```
### :speaking_head: 注意ポイント
Contentful の仕様上、fields 内に POST する内容を入れていきますが、上記のようにバリデーションを指定してオブジェクト形式にしないとエラーが出てしまうので要注意です。

あと、POST するだけだとドラフトのままなので、 `publish()` で最後に公開状態に変更しています。

##まとめ
Contentful は POST でリクエストする際のオブジェクトの書き方が特殊で、ドキュメントを参考にしても分かりにくい部分が多いですが、GET で扱う場合はいろんな扱い方が出来そうなので可能性は大きそうです。
仕様に慣れれば使いやすそうなので（もちろん Contentful のサイトから直接投稿するのは簡単です）、他でも使っていきたいと思います :smiley: