(※) ソーシャルログインは次のバージョンより提供予定です。
ここでは、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=abc
X-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=abc
Authorization: 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. | バルクコピー中につき使用できない。後ほど実行してください。 |