前回=>vte.cxによるバックエンドを不要にする開発(1.Getting Started)
vte.cxのエンドポイント管理
今回はエンドポイントとデータの登録・参照について説明します。
vte.cxは任意のエンドポイントを作成でき、その配下にデータを格納できます。
エンドポイント名には英数文字列およびアンダースコア(_)を使用できます。
では実際に管理画面からエンドポイントを作成してみましょう。
エンドポイント管理タブの新規エンドポイント作成でfooというエンドポイントを作成してみてください。
うまく作成できれば以下のようにエンドポイント一覧に表示されます。
登録されるデータとentryについて
エンドポイントは一つのentryとしてサーバに登録されます。実際に以下のURLをブラウザで表示して確認してみましょう。/dに続けてエンドポイントの/fooの後に?e&x
とパラメータを指定してください。(eはentry、xはxmlを意味します)
http://{サービス名}.vte.cx/d/foo?e&x
結果は以下のようにentryがXML形式で表示されたかと思います。(※ 実はxパラメータを取るとJSONで返しますが、セキュリティの都合上、ブラウザでJSONは表示されないようになっています。JSONはJavaScriptのXHR通信などで取得できます。)
entry の中のlink href='/foo' rel='self' />
のhrefの値(/foo)をkeyといい、エンドポイントの値が入っているのがわかります。また、entry には一意の id が自動的に割り振られています。idは key(エンドポイント) と revision の組み合わせになっています。revision はentryの更新回数です。これが id に含まれているために、更新時に楽観的排他制御ができるようになっています。(楽観的排他制御については別途詳しく説明します)
<id>key,revision</id>
- key: /foo
- revision: 1
エンドポイントの配下にデータを登録する
先程登録したエンドポイント/fooの配下にデータを登録することもできます。
VSCodeのプロジェクト直下にdataフォルダを作成して以下のXMLを作成してください。ファイル名は適当で構いませんがここではfoo1.xml
としています。
<entry>
<title>Hello</title>
<link rel="self" href="/foo/1" />
</entry>
次に、npm run upload:data
コマンドでサーバにデータを送信してください。
以下のように、{"feed" : {"title" : "Accepted."}}
と表示されれば成功です。
$ npm run upload:data
> vtecxblank@1.0.0 upload:data /Users/foo/tutorial
> npx vtecxutil upload:data
data/foo1.xml --> http://{サービス名}.vte.cx/foo1.xml
{"feed" : {"title" : "Accepted."}}
本当にサーバが更新されているかブラウザで確認してみましょう。今度はeパラメータをf(feed)にして実行してみてください。
http://{サービス名}.vte.cx/d/foo?f&x
以下のように、登録したデータが表示されたかと思います。
このデータは、/foo
エントリの配下にある/foo/1
エントリです。
/foo配下には複数件登録できるため entry ではなく feed として表示されます。登録したデータは1件でしたが、feedの中には通常はentryが複数件存在する形になります。
ちなみに、JSON形式のデータも登録することができます。
以下は上記のXMLと同じ意味のJSONになります。
ただし、linkの属性である、hrefやrelの先頭には___
(アンダースコア3つ)が付くので注意してください。また、全体を配列[]で括ってください。
[{
"title": "Hello",
"link": [
{
"___href": "/foo/1",
"___rel": "self"
}
]
}]
データを取得して表示するプログラム
では、登録したデータを取得して表示するプログラムを作成してみます。
まずはじめに、ボタンをクリックしたら回数を表示する単純なReactのプログラムを作ってみましょう。サーバとの通信のところは後から付け加えたいと思います。
index.tsxを以下のプログラムに置き換えて表示させてみてください。
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { useState } from 'react'
const App = () => {
const [x, f] = useState(0)
return (
<div>
<button onClick={() => { f(x+1) }}>
{x} times
</button>
</div>
)
}
ReactDOM.render(<App/>, document.getElementById('container'))
前回学んだように、以下のコマンドでローカル環境とサーバ環境の同時に反映させて確認することができます。
npm run serve:index
ブラウザが起動して、0 times
というボタンが表示されれば成功です。
ボタンを押して数字が増えていくのを確認してみましょう。
次に、実際にサーバのデータを取得するようにしてみます。
以下のようにコードを修正してください。
これは、axiosという通信ライブラリを使って、/foo/1
のentryを取得して表示します。
実際には/d/foo/1?e
をGETリクエストするわけですが、ブラウザ表示のときと違ってxパラメータはありませんので、entryをJSONで取得することになります。
HTTPヘッダにX-Requested-With: XMLHttpRequest
をつけているのはセキュリティ(CSRF対策)のためですが、ここではおまじないだと思って必ずつけるということだけ覚えてください。
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { useState,useEffect } from 'react'
import axios from 'axios'
const App = () => {
const [x, f] = useState(0)
const getdata = async () => {
try {
axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
const res = await axios.get('/d/foo/1?e')
alert(`res= ${res.data.title} `);
} catch (e) {
alert('error')
console.log(e)
}
}
useEffect(() => {
getdata()
})
return (
<div>
<button onClick={() => { f(x+1) }}>
{x} times
</button>
</div>
)
}
ReactDOM.render(<App/>, document.getElementById('container'))
実行結果はerror
がアラート表示されたかと思います。
Chromeのデベロッパーツール(その他のツール>デベロッパーツール)のNetworkタブで確認すると、以下のように403 Forbidden
が返ってきているのがわかります。
実は、/foo/1
のエントリはログインしている状態でないと取得することはできません。
管理画面でエンドポイントを作成しても一般に公開されるわけではなく、デフォルトではログインしないとアクセスできないようにACL(Access Control List)が設定されています。(ACLについては別途詳しく説明します)
では、ログインするために、コンソールで起動中のnpm run serve:index
を一旦止め、代わりにnpm run serve:login
を実行してください。すると、ログイン画面が起動してきますので、サービスにログインしてください。ログインに成功して真っ白な画面が表示されたら、npm run serve:login
を止め、もう一度、npm run serve:index
を起動してみてください。
すると、以下の画面が表示されるかと思います。
実際に/foo/1
エントリのtitleが読まれ、Hello
が表示されました。
今日はここまでです。お疲れ様でした。