(※) ソーシャルログインは次のバージョンより提供予定です。


ここでは、Tagging Serviceにおけるリソース管理について説明します。
/@{サービス名}/{ユーザ定義のフォルダ}/・・/{ユーザ定義のEntry} /{ユーザ定義のフォルダ}/・・/{ユーザ定義のEntry} /{uid}/{ユーザ定義のフォルダ}/・・/{ユーザ定義のEntry} curl -H "Authorization: Token {Accesstoken}" http://sample.vte.cx/d/registration/1?e{
"feed": {
"entry": [
{
"favorite": {
"food": "りんご"
},
"author": [
{
"uri": "urn:vte.cx:created:11"
},
{
"uri": "urn:vte.cx:updated:11"
}
],
"id": "/registration/1,16",
"link": [
{
"___href": "/registration/1",
"___rel": "self"
}
],
"published": "2015-10-16T10:58:10.956+09:00",
"updated": "2015-10-16T23:44:58.176+09:00"
}
]
}
}<feed>
<title>{メッセージ}</title>
</feed>{
"feed":{
"entry":[
{
"itemcode":"001",
"typeno":"",
"size":"中",
"color":"紫",
"design":"",
"brand":"",
"functions":"",
"styles":"",
"manufacturer":"",
"material":"",
"country":"日本",
"expiration_date":"",
"author":[
{
"uri":"urn:vte.cx.net:created:9"
},
{
"uri":"urn:vte.cx:updated:9"
}
],
"content":{
"______text":"花がランに似ていることからモクランという呼び方もある"
},
"id":"/9/imgs/mokuren,4",
"link":[
{
"___href":"/9/imgs/mokuren",
"___rel":"self"
},
{
"___href":"/9/albums/folder1/mokuren",
"___rel":"alternate"
},
{
"___href":"blobkey12345",
"___rel":"related",
"___type":"blob",
"___title":"flower.jpg",
"___length":"1"
}
],
"published":"2014-02-23T13:45:41.001+09:00",
"summary":"落葉低木",
"title":"モクレン",
"subtitle":"木蘭",
"updated":"2014-02-23T13:56:07.796+09:00"
}
]
}
}<?xml version="1.0" encoding="UTF-8" ?>
<feed>
<entry>
<itemcode>001</itemcode>
<typeno></typeno>
<size>中</size>
<color>紫</color>
<design></design>
<brand></brand>
<functions></functions>
<styles></styles>
<manufacturer></manufacturer>
<material></material>
<country>日本</country>
<expiration_date></expiration_date>
<author>
<uri>urn:vte.cx:created:xxx@gmail.com</uri>
</author>
<author>
<uri>urn:vte.cx:updated:xxx@gmail.com</uri>
</author>
<content>花がランに似ていることからモクランという呼び方もある</content>
<id>/9/imgs/mokuren,4</id>
<link href="/9/imgs/mokuren" rel="self"/>
<link href="/9/albums/folder1/mokuren" rel="alternate"/>
<link href="blobkey12345" rel="related" type="blob"
title="flower.jpg" length="1"/>
<published>2014-02-23T13:45:41.001+09:00</published>
<summary>落葉低木</summary>
<title>モクレン</title>
<subtitle>木蘭</subtitle>
<updated>2014-02-23T13:56:07.796+09:00</updated>
</entry>
</feed>{
"feed": {
"entry": [
{
"A001": {
"count": "3"
},
"id": "/stock/book,3",
"link": [
{
"___href": "/stock/book",
"___rel": "self"
}
]
},
{
"item": {
"book": "A001"
},
"id": "/order/1,16",
"link": [
{
"___href": "/order/1",
"___rel": "self"
}
]
}
]
}
}1. トランザクションを開始
2. データを1件get(READロック:LockMode.READ_COMMITED)
3. getしたデータを編集
4. 編集したデータをput
5. Feed(Entryを複数件包含する)の場合、2.-4.を繰り返す
6. トランザクションをcommit
<link rel="related" title="flower.jpg" href="/img/flower.jpg" />
GET /9/imgs/mokuren?_related=flower.jpg GET /9/imgs/mokuren+flower.jpg
./rxcp.sh xxxx folder http://xxx.vte.cx/d/1/folder content (folder -> http://xxx.vte.cx/d/1/folder)
_entry.number.default : エントリーGET時のデフォルト最大数 [100]
_ignore.condition.{連番} : 検索条件除外値。ここに指定した値はGETでクエリパラメータに指定しても検索条件とならない。
_errorpage.{適用順}.{エラーページselfid}={PathInfoの正規表現} : エラー画面表示URLパターン(正規表現)
_aws.sns.push.self : 更新者自身にpush通知を行うかどうか(Amazon Web Service SNS mobile push) [false]
_rxid.minute : RXID(WSSE)有効時間(分) [120]
_rxid.counter.{連番}.{回数} : 同じRXIDを使用しても指定回数まで許可されるURLパターンを指定。
_session.minute : セッション有効時間 [30]
_aws.sns.push.self : 更新者自身にpush通知を行うかどうか(Amazon Web Service SNS mobile push) [false]_mail.from.personal : EMailの送信元名 _mail.from : Emailのfrom _mail.transport.protocol : smtpsなどのメール送信プロトコル _mail.password : メール送信アカウントのパスワード _mail.smtp.host : メール送信ホスト _mail.smtp.port : メール送信ポート _mail.smtp.auth : true/false
_errorpage.1.error.html=^/_html/.*$
<contributor>
<uri>urn:vte.cx:acl:{uid|*|+|-|GroupKey},{C|R|U|D|E|.|/}</uri>
</contributor><entry>
<id>/1/test_low,1</id>
<link rel="self" href="/1/test_low" />
<contributor>
<uri>urn:vte.cx:acl:1,CRUD</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:5,CRUD/</uri>
</contributor>
</entry>
<entry>
<link rel="self" href="/1/test_low/t001" />
<title>テストLow-001</title>
</entry>GET /1/test_low (配下のEntry一覧) GET /1/test_low/t001?e POST /1/test_low/t005 POST /1/test_low/# (自動採番、実際の指定時は#を付けない。) PUT /1/test_low/t001 DELETE /1/test_low/t001
GET /1/test_low?e (自身のEntry参照) PUT /1/test_low DELETE /1/test_low
<entry>
<id>/1/test_own,1</id>
<link rel="self" href="/1/test_own" />
<contributor>
<uri>urn:vte.cx:acl:1,CRUD</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:5,CRUD.</uri>
</contributor>
</entry>
<entry>
<link rel="self" href="/1/test_own/t001" />
<title>テストOwn-001</title>
</entry>GET /1/test_own?e PUT /1/test_own DELETE /1/test_own
GET /1/test_own GET /1/test_own/t001?e POST /1/test_own/t005 POST /1/test_own/# (自動採番、実際の指定時は#を付けない。) PUT /1/test_own/t001 DELETE /1/test_own/t001
<entry>
<id>/1/test_minus,1</id>
<link rel="self" href="/1/test_minus" />
<link rel="alternate" href="/5/test_minus" />
<contributor>
<uri>urn:vte.cx:acl:-,CRUD</uri>
</contributor>
</entry>
<entry>
<link rel="self" href="/1/test_minus/t001" />
<title>テストLow-001</title>
</entry>GET /5/test_minus?e GET /5/test_minus GET /5/test_minus/t001?e POST /5/test_minus/t005 POST /5/test_minus/# (自動採番、実際の指定時は#を付けない。) PUT /5/test_minus PUT /5/test_minus/t001 DELETE /5/test_minus DELETE /5/test_minus/t001
GET /1/test_minus?e GET /1/test_minus GET /1/test_minus/t001?e POST /1/test_minus/t005 POST /1/test_minus/# (自動採番、実際の指定時は#を付けない。) PUT /1/test_minus PUT /1/test_minus/t001 DELETE /1/test_minus DELETE /1/test_minus/t001
<entry>
<contributor>
<uri>urn:vte.cx:acl:{uid},CRUD.</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:-,R.</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:/{uid}/group/{グループ名},CRUD/</uri>
</contributor>
<id>/{uid}/group/{グループ名},{revision}</id>
<link rel="self" href="/{uid}/group/{グループ名}" />
</entry><contributor>
<uri>urn:vte.cx:acl:{GroupKey}</uri>
</contributor><entry>
<id>/{uid}/group/{グループ名},{revision}</id>
<link rel="self" href="/{uid}/group/{グループ名}" />
<link rel="alternate" href="/{ユーザBのuid}/group/{グループ名}" />
</entry>PUT /{ユーザのグループKey}?_signature={Revision}DELETE /{ユーザのグループKey}?_signature<entry>
<id>/1/group/g001/share,1</id>
<link rel="self" href="/1/group/g001/share" />
</entry> <entry>
<contributor>
<uri>urn:vte.cx:acl:-,R.</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:/{グループ作成者uid}/group/{グループ名},CRUD/</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:{グループ作成者uid},CRUD.</uri>
</contributor>
<id>/{グループ作成者uid}/group/{グループ名},1</id>
<link rel="self" href="/{グループ作成者uid}/group/{グループ名}" />
<link rel="alternate" href="/{共有者1uid}/group/{グループ名}" />
<link rel="alternate" href="/{共有者2uid}/group/{グループ名}" />
....
</entry> <entry>
<contributor>
<uri>urn:vte.cx:acl:/{グループ作成者uid}/group/{グループ名},CRUD</uri>
</contributor>
<id>/{フォルダ作成者uid}/folders/{フォルダKey},1</id>
<link href="/{フォルダ作成者uid}/folders/{フォルダKey}" rel="self"/>
<link href="/{グループ作成者uid}/group/{グループ名}/share/{フォルダKey}" rel="alternate"/>
</entry><entry>
<contributor>
<uri>urn:vte.cx:acl:/{グループ1作成者uid}/group/{グループ1名},CRUD</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:/{グループ2作成者uid}/group/{グループ2名},CRUD</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:/{グループ3作成者uid}/group/{グループ3名},CRUD</uri>
</contributor>
<id>/{フォルダ作成者uid}/folders/{フォルダKey},1</id>
<link href="/{フォルダ作成者uid}/folders/{フォルダKey}" rel="self"/>
<link href="/{グループ1作成者uid}/group/{グループ1名}/share/{フォルダKey}" rel="alternate"/>
<link href="/{グループ2作成者uid}/group/{グループ2名}/share/{フォルダKey}" rel="alternate"/>
<link href="/{グループ3作成者uid}/group/{グループ3名}/share/{フォルダKey}" rel="alternate"/>
....
</entry>0 : システムユーザ (システム内でのみ使用) 1 : スーパーユーザ 上記以外の番号を一般ユーザに振り分ける
GET ?_uid={ユーザアカウント}GET ?_whoami
<feed>
<entry>
<link href="/{uid}" rel="self"/>
<title>{ユーザアカウント}</title>
<subtitle>{ニックネーム}</subtitle>
<summary>{ユーザステータス}</summary>
</entry>
...
</feed><feed>
<entry>
<link href="/{uid}" rel="self"/>
<title>{ユーザアカウント}</title>
</entry>
...
</feed><feed>
<entry>
<contributor>
<uri>urn:vte.cx:auth:{ユーザアカウント},{パスワード}</uri>
<name>{ニックネーム}</name>
</contributor>
</entry>
</feed>/_group/$admin,CRUD
{uid},CRUD<feed>
<entry>
<contributor>
<uri>urn:vte.cx:auth:{ユーザアカウント}</uri>
</contributor>
</entry>
</feed><feed>
<entry>
<contributor>
<uri>urn:vte.cx:auth:,{パスワード}</uri>
</contributor>
</entry>
</feed><feed>
<entry>
<contributor>
<uri>urn:vte.cx:auth:{ユーザアカウント},{パスワード}</uri>
<name>{ニックネーム}</name>
</contributor>
</entry>
<entry>
<link rel="self" href="/_group/$admin" />
<link rel="alternate" href="/#/group/$admin" /> <!-- 管理者権限の付与 -->
</entry>
<entry>
<link rel="self" href="/#/message" /> <!-- ユーザ登録情報 -->
</entry>
<entry>
<link rel="self" href="/#/message/1" />
<link rel="via" type="email" /> <!-- メールの送信 -->
<title>ユーザ登録</title>
<subtitle>foo@bar.com</subtitle>
<summary>ユーザ登録されました</summary>
</entry>
...
</feed>/_group/$admin,CRUD
{uid},CRUD<feed>
<title>{Accesstoken}</title>
</feed>Authorization : Token {Accesstoken}<feed>
<title>{Linktoken}</title>
</feed>挿入文: ${LINK=/setpass.html}&value=abc
実際のメール本文: https://test.vte.cx/setpass.html?_token=xxx&value=abcX-PLATFORM : 端末のプラットフォーム
Androidの場合、"gcm"
iPhoneの場合、"apns"
Kindleの場合、"adm"
X-PLATFORM-TOKEN : platformToken
Android、Kindleの場合、registrationId
iPhoneの場合、deviceToken<entry>
<contributor>
<uri>urn:vte.cx:acl:{サービス管理者},CRD.</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:{サービス管理者},CRUD/</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:{システム管理者(0)},RUD.</uri>
</contributor>
<contributor>
<uri>urn:vte.cx:acl:+,R/</uri>
</contributor>
<id>/@{サービス名},{Revision}</id>
<link rel="self" href="/@{サービス名}" title="{APIKey(署名)}" />
<title>{サービス検索名}</title>
<subtitle>{サービスの状態}</subtitle>
</entry>挿入文: ${RXID=/setpass.html}&value=abc
実際のメール本文: https://test.vte.cx/setpass.html?_RXID=xxx&value=abcAuthorization: RXID {RXIDトークン}{Createdのタイムスタンプ13桁}-{Nonce}-{PasswordDigest}-{usernameのrotate13文字列}
例) 20131115144337P09-JYdRiPmQ7JD-t3Lkktx12VFu9nA8QMVK9JHCgE1xaMgATbagXkzQf4Z-ybtvafhcre<文法>
http://xxx.xxx/{Key}?f&{name}{=|-eq-|-lt-|-le-|-gt-|-ge-|-ne-|-rg-}{value}&{name}{=|-eq-|-lt-|-le-|-gt-|-ge-|-ne-|-rg-}{value}&...&l={n}&p={カーソル文字列}
<例:好きな食べ物がeggで価格が5000以下の最大件数20件を取得>
http://xxx.xxx/{Key}?f&subInfo.favorite.food-eq-egg&price-lt-5000&l=20?{項目}=*&・・created_desc:/log
//現在のページ設定
var _activePage;
var _url;
var _feeddata = {};
var _pageindex=0;
var pagination = function(page,param) {
// pageが取得済のpageindexより大きな値の場合にpage+9までindexを取得する
var pageindex = page+9>_pageindex ? page+9 : _pageindex;
if (pageindex>_pageindex) {
if (_pageindex>1) {
param = _pageindex+','+pageindex+param;
}else {
param = pageindex+param;
}
// 1ページ=50件で開始ページ〜終了ページまでpageindexを張る
$.getJSON('/d/registration?f&l=50&_pagination='+param, function(json){
//
});
_pageindex = pageindex;
}
}
var getFeed = function(param) {
$.ajax({
url: '/d/registration?f&l=50'+param,
method: 'get',
dataType: 'json'
}).done(function( res ) {
if(res) {
_feeddata.feed = res.feed;
// 件数が変わっているかもしれないので取り直す
$.ajax({
url: '/d/registration?c'+param,
method: 'get',
dataType: 'json'
}).done(function( res ) {
_feeddata.table_count = res.feed.title; // 件数
drawtable();
}).fail(function( jqXHR, textStatus, errorThrown ) {
location.href = 'login.html';
});
}
}).fail(function( jqXHR ) {
// もしまだpageindexが張られていなければ1秒待って再検索する
if (jqXHR.responseJSON.feed.title=='Please make a pagination index in advance.') {
setTimeout(function(){getFeed(param)},1000);
}else {
location.href = 'login.html';
}
});
}
// データ取得(引数は取得するページ数と検索条件)
var getTableData = function(url, page,param) {
// 取得するデータのURL
_url = url;
// 取得するページをグローバル変数に保存
_activePage = page;
// pageindex取得
pagination(page,param)
// 取得するページを指定
if (page>1) {
param = '&n='+page+param;
}
// データと件数取得
getFeed(param);
}POST /d <!-- URLは/dだけで構いません --> <entry> ・・・ <link href="/foo/bar" rel="self"/> <!-- link rel="href" にKeyを指定します --> </entry>
POST /d/foo <!-- フォルダのURLを指定します --> <entry> ・・・ <!-- link rel=self は設定しません --> </entry>
POST /7/group/folder
<feed>
<entry>
<id>/1/group/folder/#,0</id>
....
</entry>
</feed><!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>ファイルアップロードサンプル</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<form id="form">
<p>写真:
<input type="file" id="file" name="picture"></p>
<p><input type="submit" id="submitBtn" value="登録する"></p>
</form>
<script>
$(function() {
$('#submitBtn').on('click', function(evt) {
var form = $('#form').get()[0];
var formData = new FormData( form );
$.ajax({
url: '/entry'
method: 'post',
dataType: 'json',
data: formData,
processData: false,
contentType: false
}).done(function( res ) {
// 送信成功
console.log( 'SUCCESS', res );
}).fail(function( jqXHR, textStatus, errorThrown ) {
// 送信失敗
console.log( 'ERROR', jqXHR, textStatus, errorThrown );
});
return false;
});
});
</script>
</body>
</html><feed>
<entry>
<member>
<member_code>00001</member_code>
<member_name>◯◯ 太郎</member_name>
<address>東京都港区芝×丁目△-▼</address>
<phonenumber>03-1111-1111</phonenumber>
<gender>1</gender>
<birthdate>2000-01-01</birthdate>
<profile>テストデータです。</profile>
</member>
<link href="/1/member/00001" rel="self"/>
</entry>
<entry>
<member>
<member_code>00002</member_code>
<member_name>◯◯ 次郎</member_name>
<address>東京都港区赤坂×丁目△-▼</address>
<phonenumber>03-2222-2222</phonenumber>
<gender>1</gender>
<birthdate>2000-01-02</birthdate>
<profile>テストデータ2番目です。</profile>
</member>
<link href="/1/member/00002" rel="self"/>
</entry>
<entry>
<member>
<member_code>00003</member_code>
<member_name>◯◯ 三郎</member_name>
<address>東京都港区芝浦×丁目△-▼</address>
<phonenumber>03-3333-3333</phonenumber>
<gender>1</gender>
<birthdate>2000-01-03</birthdate>
<profile>テストデータ3番目です。</profile>
</member>
<link href="/1/member/00003" rel="self"/>
</entry>
</feed><entry>
<member>
<member_code>00002</member_code>
<member_name>◯◯ 次郎</member_name>
<gender>1</gender>
<birthdate>2000-01-02</birthdate>
<profile>プロフィール更新しました。</profile>
</member>
<id>/1/member/00002,1</id>
<link href="/1/member/00002" rel="self"/>
</entry><entry> <title>タイトル</title> <id>/1/member/00002,2</id> <link href="/1/member/00002" rel="self"/> </entry>
<link rel="{self | alternate}" href="{Key}" title="{署名({revision},{文字列})}" />sha256({usersecret} + {Key} + {Revision} + {Entryのpublished})yyyy-MM-dd yyyy-MM-dd HH yyyy-MM-dd HH:mm yyyy-MM-dd HH:mm:ss yyyy-MM-dd HH:mm:ss.SSS 上記の"-"を"/"にしたもの 上記の" "を"T"にしたもの yyyyMMdd yyyyMMddHH yyyyMMddHHmm yyyyMMddHHmmss yyyyMMddHHmmssSSS 上記の各フォーマットについて、末尾にタイムゾーン([ISO 8601] +99:99、+9999、+99)を加えたもの
id
email
verified_email(Boolean) // Boolean型
name
given_name
family_name
error
errors{2} // インデントでerrorの子要素。Mapで多重度は2
domain
reason
message
locationType
location
code(int){1~100} // 1~100の範囲
message
subInfo
favorite
$attribute // $で始まる項目はXMLの属性となる(項目の先頭に記述する)
food!=^.{3}$ // !で必須項目を示す。もし{}や[]があればそれよりも後に記述する。 food[]!=xxx など
music=^.{5}$
favorite2
food
food1
favorite3
food
hobby{}
$$text // $$textはXMLのテキストノードになるsubInfo.favorite.food:/master|/data // :の後に正規表現を指定することでIndex項目となる(/masterまたは/data) subInfo.favorite.music# // #で暗号化項目(Indexか暗号化かはどちらか一つだけ指定可能) subInfo.favorite.food=3+W,/grp1+W,/*+R // ユーザ3とgrp1の書込権限、および全員(*)に読込権限 subInfo.favorite3.food:/[0-9]+/(self|alias)=1+W // IndexとACL権限は同時につけられる subInfo.favorite2.food.food1#=1+W // 暗号化とACL権限は同時につけられる
title:^/$|^/@[^/]*$ // ルートおよびサービス直下のtitleのIndex指定(任意のサービス名) contributor=@+RW,/_group/$admin+RW // contributorは自身と/_group/$adminグループのRW権限 contributor.uri# // contributor.uriの暗号指定 rights#=@+RW,/_group/$admin+RW // rightsの暗号指定、自身と/_group/$adminグループのRW権限
{
"feed": {
"entry": [
{
"email": "email1",
"error": {
"code": 100,
"errors": [
{
"domain": "com.google.auth",
"location": "Authorization",
"locationType": "header",
"message": "invalid header",
"reason": "invalidAuthentication"
}
],
"message": "Syntax Error"
},
"family_name": "管理者Y",
"given_name": "X",
"name": "管理者",
"subInfo": {
"favorite": {
"food": "カレー",
"music": "ポップス1"
}
},
"verified_email": false
},
{
"email": "email1",
"error": {
"code": 100,
"errors": [
{
"domain": "com.google.auth",
"location": "Authorization",
"locationType": "header",
"message": "invalid header",
"reason": "invalidAuthentication"
}
],
"message": "Syntax Error"
},
"family_name": "管理者Y",
"given_name": "X",
"name": "管理者",
"subInfo": {
"favorite": {
"food": "カレー",
"music": "ポップス1"
]
}
},
"verified_email": false
}
]
}
}<feed>
<entry>
<email>email1</email>
<verified_email>false</verified_email>
<name>管理者</name>
<given_name>X</given_name>
<family_name>管理者Y</family_name>
<error>
<errors>
<domain>com.google.auth</domain>
<reason>invalidAuthentication</reason>
<message>invalid header</message>
<locationType>header</locationType>
<location>Authorization</location>
</errors>
<code>100</code>
<message>Syntax Error</message>
</error>
<subInfo>
<favorite>
<food>カレー</food>
<music>ポップス1</music>
</favorite>
</subInfo>
</entry>
<entry>
<email>email1</email>
<verified_email>false</verified_email>
<name>管理者</name>
<given_name>X</given_name>
<family_name>管理者Y</family_name>
<error>
<errors>
<domain>com.google.auth</domain>
<reason>invalidAuthentication</reason>
<message>invalid header</message>
<locationType>header</locationType>
<location>Authorization</location>
</errors>
<code>100</code>
<message>Syntax Error</message>
</error>
<subInfo>
<favorite>
<food>カレー</food>
<music>ポップス1</music>
</favorite>
</subInfo>
</entry>
</feed><link rel="via" type="email" />
<link rel="via" type="email" title="{Method}" /> <link rel="via" href="http://foo/" type="webhook" />
<link rel="via" href="http://foo/" title="POST,PUT" />
<link rel="via" type="websocket" />
<link rel="via" type="push" title="{Method}" /> : 配下のエントリーが指定のメソッドで処理された場合
<link rel="via" type="push" /> : title属性が指定なしの場合、対象エントリーがPOST、PUTされた場合// index.js
import reflexcontext from 'reflexcontext'
import Person from './person'
const person = new Person('Steve')
reflexcontext.log(person.say())
reflexcontext.sendMessage(200, person.say())/* @flow */
// person.js
export default class Person {
name:string
constructor(
name:string = 'dummy'
) {
this.name = name
}
say():string {
return 'Hello, I\'m ' + this.name + '!!'
}
}//ssr.html.js
import reflexcontext from 'reflexcontext'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
const element = (
<h3> Hello, World! </h3>
)
const html = ReactDOMServer.renderToStaticMarkup(element)
reflexcontext.doResponseHtml(html)import reflexcontext from 'reflexcontext'
const feed = reflexcontext.getFeed('/registration') // デフォルトではJSONが返る
reflexcontext.doResponse(feed) | メソッド | 説明 |
| reflexcontext.getRequest() | リクエストオブジェクト(feed.entry[0] ~ feed.entry[n])を取得する |
| reflexcontext.getPathinfo() | PATHINFO(リクエストURLのパス)を取得する |
| reflexcontext.getQuerystring() | クエリストリングを取得する |
| reflexcontext.httpmethod() | HTTPメソッド(GET,POST,PUT,DELETE)を取得する |
| reflexcontext.getUriAndQuerystring() | PATHINFO+クエリストリングを取得する |
| reflexcontext.getContentType() | Content Typeを取得する |
| reflexcontext.getHeaders() | リクエストヘッダを取得する |
| reflexcontext.getCookies() | Cookieを取得する |
| reflexcontext.getQueryString(param) | URLパラメータを取得する |
| reflexcontext.uid() | uidを取得する |
| reflexcontext.getSettingValue(key) | keyを指定してサービス設定情報を取得する |
| メソッド | 説明 |
| reflexcontext.getEntry(uriAndQuery) | Entryを取得する。キーとクエリパラメータを指定する |
| reflexcontext.getFeed(uriAndQuery) | Feedを取得する。キーとクエリパラメータを指定する |
| reflexcontext.count(uriAndQuery) | 件数を取得する。キーとクエリパラメータを指定する |
| reflexcontext.post(feed,uri) | 親フォルダuriを指定してfeedをPOSTする |
| reflexcontext.post(feed) | feedをPOSTする |
| reflexcontext.put(feed) | feedをPUTする。戻り値は更新後のFeed |
| reflexcontext.delete(uri,revision) | uriのrevisionのentryを削除する |
| reflexcontext.deleteFolder(uri) | uriとその配下のentryを削除する |
| reflexcontext.saveFiles(props) | props(Map)に従ったファイル名で保存する |
| reflexcontext.getHtml(uri) | HTMLを取得する |
| reflexcontext.getContent(uri) | コンテンツを取得する |
| reflexcontext.getCsv(header[],items[],parent,skip,encoding) | アップロードされたCSVをJSONに変換して取り出す |
| メソッド | 説明 |
| reflexcontext.setids(uri,value) | uriの値をvalueにセットする |
| reflexcontext.allocids(uri,num) | uriで指定された採番数(num)だけ採番する |
| reflexcontext.addids(uri,num) | uriの採番の値を加算(+num)する |
| reflexcontext.rangeids(uri,value) | uriの採番範囲を指定する(value=start-end) |
| メソッド | 説明 |
| reflexcontext.setStatus(rc) | ステータスコードrcを設定する |
| reflexcontext.setHeader(name,value) | レスポンスヘッダを設定する |
| reflexcontext.sendRedirect(location) | リダイレクトを設定する |
| reflexcontext.sendError(rc) | ステータスコードを設定する |
| reflexcontext.sendError(rc,msg) | ステータスコード、メッセージを設定する(HTTP) |
| reflexcontext.sendMessage(rc,msg) | ステータスコード、メッセージを設定する(JSON) |
| reflexcontext.doResponse(feed[,sc]) | feed.entry[0] ~ feed.entry[n]を出力する。ステータスコードscを指定可能。リクエストパラメータで?x(xml)、?m(messagepack)を指定可能 |
| reflexcontext.doResponseHtml(html) | htmlを返却する |
| メソッド | 説明 |
| reflexcontext.log(title[,subtitle][,message]) | ログに記録する |
| メソッド | 説明 |
| reflexcontext.toPdf(feed,template,filename) | PDFを出力する |
| reflexcontext.toPdf(feed,template,filename,base) | PDFを出力する(PDF合成) |
| reflexcontext.toXls(feed,template,filename) | XLSを出力する |
| メソッド | 説明 |
| reflexcontext.getMail(settings) | メールを受信する(settings:メール設定) |
import reflexcontext from 'reflexcontext'
const param = new Object()
param.picture1 = reflexcontext.getQueryString('key1')
param.picture2 = reflexcontext.getQueryString('key2')
reflexcontext.saveFiles(param)/* @flow */
import axios from 'axios'
import React from 'react'
import ReactDOM from 'react-dom'
import {
Form,
FormGroup,
FormControl,
Button
} from 'react-bootstrap'
type InputEvent = {
target: any,
preventDefault: Function
}
class UploadPictureForm extends React.Component {
constructor() {
super()
this.state = { picture1: {}, picture2: {} }
}
handleChange(e:InputEvent) {
const file: File = e.target.files.item(0)
const key = '/registration/'+encodeURIComponent(file.name)
const name = e.target.name
// 画像以外は処理を停止
if (! file.type.match('image.*')) {
return
} else {
// 画像表示
let reader = new FileReader()
reader.onload = () => {
this.setState({ [name]: { value: reader.result, key: key } })
}
reader.readAsDataURL(file)
}
}
handleSubmit(e:InputEvent){
e.preventDefault()
const formData = new FormData(e.currentTarget)
const param = (this.state.picture1.key ? 'key1='+this.state.picture1.key+'&' : '') +
(this.state.picture2.key ? 'key2='+this.state.picture2.key : '')
// 画像は、/d/registration/{key} としてサーバに保存されます
axios({
url: '/s/savefiles?'+param,
method: 'post',
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
data : formData
}).then(() => {
alert('success')
}).catch((error) => {
if (error.response) {
alert('error='+JSON.stringify(error.response))
} else {
alert('error')
}
})
}
render() {
return (
<Form horizontal onSubmit={(e) => this.handleSubmit(e)}>
<img src={this.state.picture1.value} />
<br/>
<img src={this.state.picture2.value} />
<br/>
<FormGroup>
<FormControl type="file" name="picture1" onChange={(e) => this.handleChange(e)}/>
</FormGroup>
<FormGroup>
<FormControl type="file" name="picture2" onChange={(e) => this.handleChange(e)}/>
</FormGroup>
<FormGroup>
<Button type="submit" className="btn btn-primary">
登録
</Button>
</FormGroup>
</Form>
)
}
}
ReactDOM.render(<UploadPictureForm />, document.getElementById('container'))import reflexcontext from 'reflexcontext'
// リソースデータ取得
const data = {'feed': {'entry': [{'title': 'Hello World'}]}}
// PDF出力
reflexcontext.toPdf(data, '/pdf/hello_world.html', 'test.pdf')<?xml version="1.0" encoding="UTF-8" ?>
<html>
<body>
<!-- 用紙サイズ指定:(A4・縦) -->
<div class="_page" style="pagesize:A4; orientation:portrait;">
<table>
<tr>
<td>
<!-- 表示させたい値の項目名をidに定義します -->
<p id="title" />
</td>
</tr>
</table>
</div>
</body>
</html>import reflexcontext from 'reflexcontext'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
function formatName(user) {
return user.firstName + ' ' + user.lastName
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
}
const element = (
<html>
<body>
<div className="_page" style={{ pagesize: 'A4', orientation: 'portrait'}}>
<table>
<tr>
<td>
<p> Hello, {formatName(user)}! </p>
</td>
</tr>
</table>
</div>
</body>
</html>
)
const html = ReactDOMServer.renderToStaticMarkup(element)
// PDF出力
reflexcontext.toPdf({}, html, 'test.pdf')// hello.xls.js
import reflexcontext from 'reflexcontext'
const data = {'feed' : {'entry' : [{'userinfo' : {'id' : 123,'email' : 'foo@bar.com'}},{'favorite' : {'food' : 'ラーメン','music' : ['ジャズ','ポップス','ロック']}}]}}
// XLS出力
reflexcontext.toXls(data, '/xls/person_template.xls', 'test.xls')import reflexcontext from 'reflexcontext' const settings = new Object() // 基本設定(例:yahooメール) settings['mail.pop3.host']='pop.mail.yahoo.co.jp' settings['mail.pop3.port'] = '995' // タイムアウト設定 settings['mail.pop3.connectiontimeout'] = '60000' //SSL関連設定 settings['mail.pop3.socketFactory.class']='javax.net.ssl.SSLSocketFactory' settings['mail.pop3.socketFactory.fallback']='false' settings['mail.pop3.socketFactory.port'] = '995' settings['username']='xxxxx@yahoo.co.jp' settings['password']='xxxxx' const result = reflexcontext.getMail(settings) reflexcontext.log(JSON.stringify(result))
{"feed":{"entry":[{"title" : "Header parse error"}]}} import reflexcontext from 'reflexcontext'
const items = ['item1','item2(int)','item3(int)']
const header = ['年月日','件数','合計']
const parent = 'order'
const skip = 1
//const encoding = 'SJIS'
const encoding = 'UTF-8'
// CSV取得
const result = reflexcontext.getCsv(header,items,parent,skip,encoding)
reflexcontext.log(JSON.stringify(result)) // {"feed":{"entry":[{"order":{"item1":"2021/7/5","item2":3,"item3":3}},{"order":{"item1":"2021/7/6","item2":5,"item3":8}},{"order":{"item1":"2021/7/7","item2":2,"item3":10}}]}}// この1行はskipする 年月日,件数,合計 "2021/7/5",3,3 "2021/7/6",5,8 "2021/7/7",2,10
/* @flow */
import axios from 'axios'
import React from 'react'
import ReactDOM from 'react-dom'
import {
Form,
FormGroup,
FormControl,
Button
} from 'react-bootstrap'
type InputEvent = {
target: any,
preventDefault: Function
}
class UploadCsvForm extends React.Component {
constructor() {
super()
this.state = { }
}
handleSubmit(e:InputEvent){
e.preventDefault()
const formData = new FormData(e.currentTarget)
// 画像は、/d/registration/{key} としてサーバに保存されます
axios({
url: '/s/getcsv',
method: 'post',
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
data : formData
}).then(() => {
alert('success')
}).catch((error) => {
if (error.response) {
alert('error='+JSON.stringify(error.response))
} else {
alert('error')
}
})
}
render() {
return (
<Form horizontal onSubmit={(e) => this.handleSubmit(e)}>
<FormGroup>
<FormControl type="file" name="csv" />
</FormGroup>
<FormGroup>
<Button type="submit" className="btn btn-primary">
登録
</Button>
</FormGroup>
</Form>
)
}
}
ReactDOM.render(<UploadCsvForm />, document.getElementById('container'))| 番号 | メッセージ | 意味 |
| 1 | XX is required. | XXの指定が必要 |
| 2 | XX is not available. | XXが使えない |
| 3 | XX does not exist. | XXが存在しない |
| 4 | XX is invalid. | XXが不正 |
| 5 | Allocate id must be a numeric value. | 正しい数値がIDに指定されていない |
| 6 | Callback strings must use alphanumeric characters. | callbackには英数字以外使用不可 |
| 7 | Duplicated Link self. | Link selfが重複している |
| 8 | Duplicated rules for ACLs. | 既に同じ権限が設定されている |
| 9 | Duplicated URIs for | URIが重複している |
| 10 | Forbidden request to this service. | このサービスへの許可されないリクエスト |
| 11 | Max must be greater than min. | 最大値が最小値より大きい値ではない |
| 12 | Must specify a 'E'(External) control. | E権限を指定する必要がある |
| 13 | Not allowed to cancel the process. | プロセスをキャンセルできない |
| 14 | Not allowed to use an alias for bulkcopy. | bulkcopyではaliasは使えない |
| 15 | Optimistic locking failed for the specified template. | 指定したテンプレートの更新エラー(楽観的排他エラー)が発生 |
| 16 | Password must be contain at least 8 characters, including at least 1 number and includes both lower and uppercase letters. | passwordは1文字以上で数字と小文字と大文字混じりである必要がある |
| 17 | Request format is invalid: XX | リクエストのフォーマットが正しくセットされていない |
| 18 | Revision number must be a numeric value. | リビジョンが数字ではない |
| 19 | Specified value is out of range. | リビジョンの値が範囲外 |
| 20 | Specified URI does not match the id nor key. | 指定したURIがIDとKeyに一致しない |
| 21 | The first limit must be less than limit(XX). | first limitはlimit(XX)以下を指定しなければならない |
| 22 | The first limit must be more than 0. | first limitは0以上を指定しなければならない |
| 23 | The number of pages must be more than 0. | number of pagesは0以上を指定しなければならない |
| 24 | Too many entities. | entityの数が多すぎる |
| 25 | Unauthorized request to modify the auth. | Authの変更リクエストは受け付けられない |
| 26 | URI must not contain any prohibited characters. | URIに許可していない文字の使用は不可 |
| 27 | URI must not contain any white-space characters. | URIにblank文字は使えない |
| 28 | URI must start with a slash. | URIは/から始まるものでなければならない |
| 29 | Accesskey and Accesstoken can not be used. | AccesskeyとAccesstokenが使えない |
| 30 | Please set only one key. | selfは1エントリ1件のみ |
| 31 | Please make a pagination index in advance. | 先にpagination indexを作成する必要がある |
| 32 | Session is disabled. | セッションが無効になっている |
| 33 | Session does not exist. | セッションが存在しない |
| 34 | Top entry can not be specified. | ルートエントリは指定不可 |
| 35 | Forbidden request to this service. | このサービスで実行できない |
| 36 | Service init entry is nothing. | サービス初期化エントリが存在しない |
| 37 | .js' is not found. | .jsファイルが見つからない |
| 38 | Service does not exist. | サービスが存在しない |
| 39 | The Web Application has not been activated. | Webアプリケーションが有効になっていない |
| 番号 | メッセージ | 意味 |
| 1 | Authentication is locked. | 認証がロックされている |
| 2 | Authentication time out. | 認証タイムアウト |
| 3 | Remote access is not allowed. | リモートからのアクセスは禁止 |
| 4 | Captcha required at next login. | 次回からCaptcha認証が必要 |
| 番号 | メッセージ | 意味 |
| 1 | Duplicated primary key. | Keyが重複している |
| 2 | Alias is duplicated. | aliasが重複している |
| 3 | User is already registered. | ユーザが既に登録されている |
| 4 | Optimistic locking failed. | 更新エラー(楽観的排他エラー) |
| 番号 | メッセージ | 意味 |
| 1 | The service is currently not available due to registration process.Please try again later. | バルクコピー中につき使用できない。後ほど実行してください。 |