【vte.cx応用】14. コンテンツマネージメントについて


本日はvte.cxのコンテンツ管理について説明します。

# BaaSに求められるCMS機能

ほとんどのBaaSはバックエンドのAPIを提供するだけでHTMLやCSS、JavaScript、画像といったコンテンツは扱えません。
なかにはWebシステムを想定したバックエンドのAPIを提供するものもありますが、オリジンが異なるためクロスドメイン対策が必要になります。
そもそもHTMLコンテンツとAPIが異なるドメインになるのはセキュリティ面でも運用面でも筋が悪いように思います。それに、別途、Webコンテンツをホスティングするためのサーバも必要になります。

vte.cxは本格的なWebシステムを構築するためのBaaSであり、コンテンツもデータと同じリソースとして扱えるのが特徴です。つまり、コンテンツもデータも同じドメインから取り出すことができ、CMS(Content Management System)としての機能を備えています。コンテンツを置くためのサーバはもう必要ありません。

これにより、コンテンツもAPIも同じオリジンになるため、一般的なWebアプリケーションと同様の普通の開発できるようになります。

#ATOM EntryのContentでコンテンツを管理する

vte.cxではコンテンツをATOM Entryで管理しています。
EntryのcontentタグにはHTMLやJavaScript、画像などのコンテンツを格納することができます。
この項目がセットされている場合、**?fや?eなどのURLパラメータをつけないで**GETすると格納されているコンテンツそのものを取得することができます。つまり、HTMLや画像などを表示したりすることが可能なわけです。
このことからも、vte.cxではデータとコンテンツを区別することなく扱えるCMSとしての機能があることがわかります。

content-typeもセットすることができます。
content-typeがtext/で始まるものであれば、HTMLエンコーディングされた状態でセットされます。その他はバイナリとしてBase64変換した文字列がセットされます。

より詳しい説明は、[ドキュメントの内部コンテンツ](http://reflexworks.jp/documentation.html#taggingservice.html#R12)を参照してください。

#将来的なコンテンツ管理の分離

現在はコンテンツをデータと同じデータストアに登録していますが、ラージオブジェクトなどを管理するために別途ストレージを用意することを考えています。

そのストレージにはAmazon S3やGoogle Cloud Storageといったクラウドのストレージサービスを想定しています。管理画面でユーザが選択したストレージサービスを接続すれば自由に容量の際限なく登録できる仕組みになる予定です。

#コンテンツの登録とrxcp.shの詳細

コンテンツの登録では、POSTかPUTでURLパラメータに`?_content`をつけて実行します。すると登録したデータがcontentタグの中に変換されて格納されます。データはどのようなフォーマットでも構いません。

`?_content`をつけないで実行した場合は通常のFeed登録となります。
この場合、JSONかXML、MessagePackなどのフォーマットでなければエラーとなります。

vtecxblankにはデプロイのためのシェルスクリプト rxcp.sh が用意されています。
わずか40行ほどのbashシェルスクリプトですが、これだけでローカルにあるコンテンツを全てサーバにデプロイすることができます。

```
#!/bin/bash

function send() {
    if [ -d $3 ]; then
        echo "$3 is a directory."
        curl -H "Authorization: Token "$1 -H "Content-Type:"$4 -H "Content-Length: 0" -X PUT $2$5?_content
    else
        curl -H "Authorization: Token "$1 -H "Content-Type:"$4 -T $3 $2$5$6
        fi
    echo -e '\n'
}

for file in `find $2`
do
echo -n $file' --> '

type="application/octet-stream"

case ${file##*/*.} in
  "json" ) type="application/json" ;;
  "xml" ) type="text/xml" ;;
  "html" ) type="text/html;charset=UTF-8" ;;
  "js" ) type="text/javascript;charset=UTF-8" ;;
  "css" ) type="text/css;charset=UTF-8" ;;
  "png" ) type="image/png" ;;
  "gif" ) type="image/gif" ;;
  "jpeg" ) type="image/jpeg" ;;
  "jpg" ) type="image/jpeg" ;;
esac

tgt=${file#$2}
echo -n $3$tgt'   '

opt=""
if [ -n "$4" ]; then
   opt=?_$4
fi

send $1 $3 $file $type $tgt $opt
done
```

### rxcp.shの動作

 指定されたローカルフォルダ配下のコンテンツについて以下を再帰的に繰り返します。

 - ディレクトリであればサーバにフォルダを作成します。(中身が0バイトで`?_content`がついていることに注意してください）
    - ``` curl -H "Authorization: Token "$1 -H "Content-Type:"$4 -H "Content-Length: 0" -X PUT $2$5?_content ```
 - ファイルであればサーバにそれを登録します。(コンテンツかデータかは$6で決定します)
    - ```curl -H "Authorization: Token "$1 -H "Content-Type:"$4 -T $3 $2$5$6``` 
    
実際にrxcp.shが呼ばれるのは、gulpコマンドかCircleCIの以下のコマンドからです。

```
./rxcp.sh ${accesstoken} dist https://{service name}.1.vte.cx content
./rxcp.sh ${accesstoken} setup https://{service name}.1.vte.cx/d
```

1行目のdistはビルド後のHTML、CSS、JavaScript等のコンテンツがあるディレクトリです。
2行目のsetupはサーバフォルダのACL設定やスキーマテンプレートなどがあるディレクトリです。
これはコンテンツではなくFeedとして登録されます。`?_content`がつかないので注意してください。

以上で本日はおしまいです。
明日はトランザクション処理と採番処理について説明します。
それでは。