楽観的ロック
#条件付きPUT=1.GET(ETagを得るため)→2.PUT(得られたETagを使う、条件付きPUT=If-Match(下図))
#1.リクエスト
GET /1120002 HTTP/1.1
Host: zip.ricollab.jp
↓
#1.リスポンス
HTTP/1.1 200 OK
Content-Type: application/json
ETag: sample-etag-value
{
"zipcode": "1120002",
"address": {
"prefecture": "東京都",
"city": "文京区",
"town": "小石川",
},
"yomi": {
"prefecture": "トウキョウト",
"city": "ブンキョウク",
"town": "コイシカワ",
},
}
#2.リクエスト 条件付きPUT=1.GET(ETagを得るため)→2.PUT(得られたETagを使う、条件付きPUT=If-Match(下図))
PUT /1120002 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
If-March: sample-etag-value
{
"zipcode": "1120002",
"address": {
"prefecture": "東京都",
"city": "文京区",
"town": "小石川",
},
"yomi": {
"prefecture": "トウキョウト",
"city": "ブンキョウク",
"town": "コイシカワ",
},
}
↓
#2.リスポンス
HTTP/1.1 200 OK
#条件付きGET/PUT/DELETEとヘッダ対応
| メソッド | Last-Modified | ETag |
| GET |If-Modified-Since | If-None-Match|
| PUT/DELETE |If-Unmodified-Since| If-Match |
#リクエスト 削除
DELETE /1120002 HTTP/1.1
Host: zip.ricollab.jp
Content-Type: application/json
If-March: sample-etag-value
↓
#リスポンス
HTTP/1.1 200 OK
条件付きGET/PUT/DELETEとヘッダ対応
| メソッド | Last-Modified | ETag |
| GET |If-Modified-Since | If-None-Match|
| PUT/DELETE |If-Unmodified-Since| If-Match |
悲観的ロック
#リクエスト
LOCK /1120002 HTTP/1.1
Host: zip.ricollab.jp
Timeout: Second-3600
Content-Type: application/xml; charset=utf-8
Authorization: Basic ...
<D:lockinfo xmlns:D="DAV">
<D:lockscope><D:exclusive/></D:lockscope>
<D:lockscope><D:write/></D:lockscope>
</D:lockinfo>
------------------
イメージ
LOCK→
←200OK
GET→
←200OK
←GET
200OK→
PUT(by_a)→
←200OK
←PUT(by_b)
→200OK
GET→
←200OK
UNLOCK→
←200OK
---------------
#リスポンス
<D:prop xmlns:D="DAV">
<D:lockdiscoverry>
<D:activelock>
<D:lockscope><D:exclusive/></D:lockscope>
<D:lockscope><D:write/></D:lockscope>
<D:depth>Infinity</D:depth>
<D:owner>
<D:href>mailto:yohei@gmail.com</D:href>
<D:owner>
<D:timeout>Second-3600</D:timeout>
<D:lockstoken>
<D:href>opaquelocktoken:e71d4fae-5dec-22d6-fea5</D:href>
</D:lockstoken>
</D:activelock>
</D:lockdiscoverry>
</D:prop>
#ロック機能確認
#リクエスト リソース編集 (失敗 Ifヘッダでロックトークンを指定しなかった場合)
↓
#リスポンス
HTTP/1.1 423 Locked
---------
#リクエスト(成功)
PUT /1120002 HTTP/1.1
IF:(<opaquelocktoken:e71d4fae-5dec-22d6-fea5>)
Content-Type: application/json
{
"zipcode": "1120002",
"address": {
"prefecture": "東京都",
"city": "文京区",
"town": "小石川",
},
"yomi": {
"prefecture": "トウキョウト",
"city": "ブンキョウク",
"town": "コイシカワ",
},
}
↓
#リスポンス
HTTP/1.1 200 OK
#リクエスト (ロック解除)
UNLOCK /1120034 HTTP/1.1
Host: zip.ricollab.jp
Content-Type: application/xml; charset=utf-8
Authorization: Basic ...
Lock-Token: opaquelocktoken:e71d4fae-5dec-22d6-fea5
↓
#リスポンス
HTTP/1.1 200 OK
#リクエスト (ロックしたいURIのみ、×WebDAVのデータモデルに適用、LOCK対象の子リソースPOST)
POST /1120034 HTTP/1.1
Host: zip.ricollab.jp
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ...
scope=exclusive&timeout=300
↓
#リスポンス
HTTP/1.1 201 Created
Location: http://zip.ricollab.jp/1120034/lock
Content-Type: application/json
{
"locktype": "exclusive",
"timeout": "2010-09-07T10:00:30Z",
"owner": "yohei",
}
#ロック削除
DELETE /1120034/lock HTTP/1.1
Host: zip.ricollab.jp
Authorization: Basic ...
↓
HTTP/1.1 200 OK
トランザクション(失敗時に元の状態に戻せる、金銭取引等に使われる)
http://zip.ricollab.jp/transactions
↓POST送信
#リクエスト
POST /transaction/308 HTTP/1.1
Host: zip.ricollab.jp
#レスポンス
HTTP/1.1 201 Created
Location: http://zip.ricollab.jp/transactions/308
------
#リクエスト(PUT>POST頻出度)+/1追加
PUT /transaction/308/1 HTTP/1.1
Host: zip.ricollab.jp
↓
#リスポンス +/1追加
HTTP/1.1 201 Created
Location: http://zip.ricollab.jp/transactions/308/1
------
#リクエスト
PUT /transaction/308 HTTP/1.1
Host: zip.ricollab.jp
+ Content-Type: application/x-www-form-urlencoded
+commit=true
↓
#リスポンス OK/ERROR
HTTP/1.1 200 OK
HTTP/1.1 500 Internal Server Error
#トランザクション 削除
DELETE /1120002 HTTP/1.1
Host: zip.ricollab.jp
↓
HTTP/1.1 200 OK
#パッチ処理 トランザクション POST一括削除
PUT /batch HTTP/1.1
Host: zip.ricollab.jp
Content-Type: application/xml; charset=utf-8
DELETE /1
DELETE /2
DELETE /3
パッチ処理(一括更新)
リクエスト PUT(一括更新)
PUT /9999999 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"zipcode": "9999998",
"address": {
"prefecture": "aa都",
"city": "bb区",
"town": "ccc",
},
"yomi": {
"prefecture": "aaト",
"city": "bbク",
"town": "ccc",
},
}
{
"zipcode": "9999999",
"address": {
"prefecture": "aa都",
"city": "bb区",
"town": "ccc",
},
"yomi": {
"prefecture": "aaト",
"city": "bbク",
"town": "ccc",
},
}
レスポンス XML (複数のに、ひとつひとつステータスコードを返す)
HTTP/1.1 200 OK
Content-Type: application/json
<D:multistatus xmlns:D="DAV:">
<D:response>
<D:href>http://zip.ricollab.jp</D:href>
<D:propstat>
<D:status>HTTP/1.1 200 OK<D:status>
</D:propstat>
<D:propstat>
<D:status>HTTP/1.1 200 OK<D:status>
<D:responsedescription>
データベース接続エラーです。
</D:responsedescription>
</D:propstat>
</D:response>
<D:responsedescription>
全2つのリクエスト中1つが成功しました。
</D:responsedescription>
</D:multistatus>
レスポンス JSON(複数のstatusに、ひとつひとつステータスコードを返す)
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"status": "200 OK",
"description: "成功しました。"
},
{
"status": "500 Internal Server Error",
"description: "データベース接続エラーです。"
}
]
更新 PUT
バルクアップデート PUT 更新
PUT /9999999 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"zipcode": "1120002",
"address": {
"prefecture": "aa都",
"city": "bb区",
"town": "ccc",
},
"yomi": {
"prefecture": "aaト",
"city": "bbク",
"town": "ccc",
},
}
パーチャルアップデート PUT 更新
PUT /9999999 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"yomi": {
"prefecture": "aaト",
}
}
作成 POST/PUT
リクエスト POST
POST /9999999 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"zipcode": "9999999",
"address": {
"prefecture": "aa都",
"city": "bb区",
"town": "ccc",
},
"yomi": {
"prefecture": "aaト",
"city": "bbク",
"town": "ccc",
},
}
リスポンス POST
HTTP/1.1 201 Created
Content-Type: application/json/9999999
{
"zipcode": "9999999",
"address": {
"prefecture": "aa都",
"city": "bb区",
"town": "ccc",
},
"yomi": {
"prefecture": "aaト",
"city": "bbク",
"town": "ccc",
},
}
リクエスト PUT
PUT /9999999 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"zipcode": "9999999",
"address": {
"prefecture": "aa都",
"city": "bb区",
"town": "ccc",
},
"yomi": {
"prefecture": "aaト",
"city": "bbク",
"town": "ccc",
},
}
リスポンス PUT
HTTP/1.1 201 Created
Content-Type: application/json
{
"zipcode": "9999999",
"address": {
"prefecture": "aa都",
"city": "bb区",
"town": "ccc",
},
"yomi": {
"prefecture": "aaト",
"city": "bbク",
"town": "ccc",
},
}
CRUD-HTTP
| Create | 作成 | POST/PUT |
| Read | 読み込み | GET |
| Update | 更新 | PUT |
| Delete | 削除 | DELETE |
GET,POST,PUT,DELETE,HEAD,OPTION,TRACE,CONNECT
httpヘッダ
Content-Type(メディアタイプ),charset(文字のエンコーディング),Authorization(Basic認証、ユーザー名とパスワード),If-None-Match(条件付きGET、ETagを条件にする),Content-discription(ファイル名を指定する)
ステータスコード
200 OK リクエスト成功、500 InternalServerError サーバー内部エラー
URI
.json(拡張子),/2010/05/01(マトリクスURI)