32 KiB
5.1. WIP over HTTP
WIP over HTTPは、3. Protocolのlogical data modelをHTTP request / responseとJSONへ対応付ける標準Transport Bindingである。HTTP上の表現は、5. Transport Bindingsの共通要件に従って定める。
目的と範囲
HTTPへ対応付けるCore interactionは、次の三つである。
observefetch_interfacecall_operation
HTTP version、communication scheme、TLS、authentication方式、connection reuse、multiplexing、proxy、gateway、cache、Host内部のframework、backend接続方式は規定しない。これらはHTTP実装とdeploymentが、WIPとは独立して選択する。複数のCore interactionが必要な場合も、それぞれを独立したHTTP request / responseとして交換する。
Operationは、WebSocket等のendpointをApplication dataとして返してよい。ただし、そのendpoint上のprotocol、状態、lifecycleは、WIPの規定対象外である。
Endpoint
WIP endpointは、一つのWorldspace access surfaceを指すabsolute hierarchical base URLである。URLのpath prefixはdeploymentが任意に選択できる。Clientはorigin直下や/wip等の既定prefixを仮定せず、Worldspace pathとの対応も仮定しない。
Endpoint URLには、次の条件を適用する。
- HTTP実装がrequest先として使用できるabsolute URLである。
- Authorityとhostを持つ。
- Queryとfragmentを持たない。
- Pathが
/で終わるcanonical formである。
利用者から末尾/のないURLを受け付ける実装は、routeを解決する前に/を追加し、canonical formへ変換する。URL schemeと通信securityはHTTP実装とdeploymentが選択し、このbindingは制約しない。
各routeは、endpoint URLをbase URLとして、次のrelative referenceをRFC 3986に従って解決する。すべてのinteractionでPOSTを使用する。
| Interaction | Method | Relative reference |
|---|---|---|
observe |
POST |
v1/observe |
fetch_interface |
POST |
v1/fetch_interface |
call_operation |
POST |
v1/call_operation |
v1は、WIP over HTTP Bindingのmajor versionを表す。Interactionごとに独立したrouteを設定したり、固定suffixを別名へ置き換えたりしない。
例えば、endpointが次のURLである場合、
http://gateway.example/tenants/acme/filesystem/wip/
observe routeは次のURLになる。
http://gateway.example/tenants/acme/filesystem/wip/v1/observe
このpath prefixはHTTP deployment上のroutingであり、Worldspace内のpathではない。Worldspace pathは、request bodyのlogical fieldとして渡す。標準route URLはqueryを持たず、query付きURLや追加path segmentを同じrouteとして扱わない。
Clientは、異なるcanonical endpoint間でKnown Space、Object observation、Interface observation、validatorを混在させない。同じendpointでも、認証主体、tenant、capability、その他のsecurity contextによって異なるWorldspaceが見える場合は、異なるeffective Worldspace viewとして分離する。
HTTP request metadata
標準routeへのrequestには、次の条件を適用する。
- Methodは
POST。 Content-Typeはapplication/jsonまたはapplication/json; charset=utf-8。- BodyはUTF-8のJSON text。
- 標準Clientは
Accept: application/jsonを送る。 - Request URLは標準routeと完全に一致し、queryを持たない。
Media typeとparameter名は、HTTPの規則に従ってcase-insensitiveに比較する。charsetを指定する場合に許可するのはutf-8だけである。同じparameterの重複、UTF-8以外のcharset、その他のmedia type parameterは、標準bindingでは使用しない。
Hostは、Acceptがないrequestを受理してよい。Acceptがある場合はHTTP content negotiationの規則を適用し、application/jsonに対するeffective quality valueが正である場合だけ、JSON responseを返す。
すべての実装はHTTP identity content codingを扱える。Requestとresponseのcontent codingはoptionalなHTTP機能であり、このbindingは特定の圧縮方式を必須にしない。Hostが対応しないrequest content codingは、Transport-levelの415 Unsupported Media Typeとして拒否する。Clientが対応しないresponse content codingは、Transport failureとして扱う。
Routeとmetadataのfailure
Route、method、content negotiation、Transport authenticationは、logical WIP requestの外側で扱う。次のresponseには、Protocol error envelopeを要求しない。
| 条件 | HTTP response |
|---|---|
| 未知route、query付きroute、追加path segment | 404 Not Found |
既知routeへのPOST以外のmethod |
405 Method Not AllowedとAllow: POST |
UnsupportedなContent-Typeまたはrequest content coding |
415 Unsupported Media Type |
JSON responseを拒否するAccept |
406 Not Acceptable |
| Transport authenticationが必要 | 401 Unauthorized、必要ならWWW-Authenticate |
| Endpoint access surface全体へのaccess拒否 | 403 Forbidden |
Clientは、これらをInvalidRequest、NotFound、PermissionDenied等へ変換しない。
一方、標準route、method、media type、authenticationを受理した後に、bodyがmalformed JSONである、logical requestへdecodeできない、required fieldがない、未知fieldがある、またはfield semanticsに違反する場合は、Protocol failureとなる。Hostは400 Bad Requestと、invalid_requestのProtocol error envelopeを返す。
HTTP server、proxy、gateway、Clientの運用設定によってmessage size、timeout、rate等の上限に達した場合は、Transport failureである。HTTP statusがProtocol error mappingと同じでも、validなProtocol error envelopeを持たないresponseをProtocol failureへ変換しない。
HTTP response
各interactionが成功した場合、Hostは200 OKを返す。Response bodyには、対応するProtocol responseを直接encodeし、result等の共通envelopeで包まない。
Protocol failureの場合は非2xx statusを返し、bodyにProtocol error envelopeをencodeする。
WIP Hostが生成するbody付きresponseは、Content-Type: application/jsonまたはapplication/json; charset=utf-8を持つ。Protocol successとProtocol failureのbodyは、いずれもUTF-8 JSON textである。
HTTP statusは、大分類とHTTP infrastructureのための補助情報である。Protocol failureの意味を決定するものではなく、Clientはstatus、reason phrase、人間向けmessageからProtocolErrorCodeを推測しない。
非2xx responseが、正しいContent-TypeとvalidなProtocol error envelopeを持たない場合、ClientはTransport failureとして扱う。Proxyやgatewayが生成したresponseを、Host由来のProtocol failureと誤認しないためである。
これに対し、次のresponseはInvalidResponseとなる。
200 OK以外の2xx statusにvalidなsuccess bodyがある。- 2xx statusにProtocol error envelopeがある。
- 非2xx statusにvalidなsuccess bodyがある。
- Success bodyまたはProtocol error envelopeがschema、request correlation、interactionごとのcode制約に違反する。
JSON共通規則
JSON encodingには、次の規則を適用する。
- JSON textはUTF-8でencodeする。
- RecordはJSON object、listはJSON arrayで表す。
- Field名と列挙stringはcase-sensitiveである。
- 同じJSON object内のduplicate memberを拒否する。
- 本章がschemaを定義するobjectでは、許可していないmemberを拒否する。Descriptorの未知formatとTypeExpr
Jsonのobjectには、それぞれ後述する例外を適用する。 - Required fieldは必ず存在する。
- Protocol structのoptional fieldはmemberの省略で表し、
nullで置き換えない。 - JSON objectのmember順に意味を持たせない。
- Protocol listのarray順は保持する。
- StringへUnicode normalizationを適用しない。
- JSON syntaxが表現できないNaNと正負Infinityを使用しない。
Schema表でoptionalと記していないfieldは、requiredとして扱う。
Vec<u8>はcanonical base64 stringとしてencodeする。RFC 4648 Section 4のstandard base64 alphabetを使用し、必要な= paddingを含める。Whitespace、URL-safe alphabet、padding省略、同じoctet列に対する別表現は受理しない。
Path、Interface参照、Object identity、名前、validatorの意味は、fieldの位置とProtocolの型によって決まる。JSON上の表現は次のとおりである。
| Logical field | JSON encoding |
|---|---|
Path / entry |
canonical absolute Worldspace pathのstring |
| Object、Operation、Type、Field、Parameter、Case名 | string |
| Interface参照 | InterfaceReference object |
ref |
string |
format |
string |
| Object / Interface validator | canonical base64 string |
ただし、JSON serialization全体をcanonical化するわけではない。Whitespace、escapeの選択、object member順はcanonical化せず、同じlogical valueがbyte-for-byte同一のJSONになることも要求しない。
Interface Reference
InterfaceReferenceは、次のfieldだけを持つexactなJSON objectとしてencodeする。
| Field | JSON type | Presence |
|---|---|---|
scope |
canonical absolute Worldspace pathのstring | required |
name |
空でないUnicode string | required |
{
"scope": "/github",
"name": "issue.read"
}
Object.interfacesの各要素、FetchInterfaceRequest.interface、FetchInterfaceResponse.interface、InterfaceTarget.referenceで、この形を共通して使用する。Scopeの省略、relative scope、null、空name、追加member、旧形式のopaque string、"/github::issue.read"等の短縮表記stringは認めない。Requestで違反した場合は400 Bad Requestとinvalid_requestを返し、responseで違反した場合はClient-localなInvalidResponseとする。
参照は、JSON decode後のscopeとnameの完全一致で比較する。Object member順やJSON escapeの違いは、同一性に影響しない。ScopeへURL encoding / decodingを追加せず、name内の::や#も通常の文字として保持する。
ScopeはWorldspace上のpathである。HTTP endpointのprefixを加えたり、scope用のHTTP routeを生成したりしない。合成によるscope変換は、ProtocolのWorldspace compositionに従う。
ObjectとObjectObservation
Objectは、次のfieldを持つJSON objectとしてencodeする。
| Field | JSON type | Presence |
|---|---|---|
name |
string | required |
description |
string | optional |
interfaces |
InterfaceReference objectのarray |
required |
ref |
string | optional |
validator |
canonical base64 string | optional |
ObjectのJSON表現の例:
{
"name": "123",
"description": "First item",
"interfaces": [
{ "scope": "/", "name": "item-interface-v1" },
{ "scope": "/", "name": "item-marker-interface-v1" }
],
"ref": "item:123",
"validator": "aXRlbS12YWxpZGF0b3I="
}
interfacesのarray順にはHostの立項順を保持し、(scope, name)の完全一致による重複を含めない。各参照のscopeは、観測pathに対してProtocolの祖先制約を満たす。
ObjectObservationは、Objectとchildrenの観測を次のJSON objectで表す。
| Field | JSON type | Presence |
|---|---|---|
object |
Object |
required |
children |
ObjectObservationのarray |
optional |
childrenの省略は未観測を表す。空arrayは、観測済みで直接のindexable childが存在しないことを表す。Requested depthより浅いnodeではchildrenを必ず含め、depth境界のnodeでは省略する。
Success responseはrequested depthまで完全であり、truncated markerやpartial successを返さない。
Interface Descriptor
Format discriminator
標準v1のInterface Descriptor formatは、wip-interface/1である。このformatのJSON grammarは、以下の定義に従う。
Clientは、Descriptor objectのstring formatを先に読み、対応しないformatをUnsupportedDescriptorFormatとして扱える。未知formatでも、DescriptorはJSON objectであり、string formatを必ず持つ。
それ以外のmemberはformat固有であるため、未知formatをwip-interface/1のschemaで検証しない。Memberの存在、欠落、型をこのschemaで判定せず、内容をOperationへ使用しない。標準v1 Hostはwip-interface/1を返す。
Documentation
Documentationは、説明を次のJSON objectで表す。
| Field | JSON type | Presence |
|---|---|---|
summary |
string | required |
details |
string | optional |
Descriptor root
InterfaceDescriptorのrootは、次のJSON objectである。
| Field | JSON type | Presence |
|---|---|---|
format |
string。標準v1ではwip-interface/1 |
required |
documentation |
Documentation |
optional |
types |
TypeDeclarationのarray |
required |
operations |
OperationDeclarationのarray |
required |
typesとoperationsのarrayには、declaration順を保持する。
TypeDeclaration
| Field | JSON type | Presence |
|---|---|---|
name |
string | required |
documentation |
Documentation |
optional |
definition |
TypeExpr |
required |
TypeExpr
すべてのTypeExprを、string kindを持つJSON objectとしてencodeする。kindごとに持つmemberは、次のものに限定する。
| TypeExpr | kind |
その他のmember |
|---|---|---|
| Unit | unit |
なし |
| Boolean | boolean |
なし |
| Integer | integer |
なし |
| Number | number |
なし |
| String | string |
なし |
| Bytes | bytes |
なし |
| Json | json |
なし |
| Entry | entry |
なし |
| Named | named |
required string name |
| Record | record |
required FieldDeclaration array fields |
| List | list |
required TypeExpr items |
| Enum | enum |
required EnumCase array cases |
| Union | union |
required UnionCase array cases |
ListのitemsがNamedであるTypeExprの例:
{
"kind": "list",
"items": {
"kind": "named",
"name": "ItemSummary"
}
}
Primitive kindのobjectに、別memberを追加してはならない。例えばUnitの表現は、{"kind":"unit"}だけである。
FieldDeclaration
| Field | JSON type | Presence |
|---|---|---|
name |
string | required |
required |
boolean | required |
documentation |
Documentation |
optional |
type |
TypeExpr |
required |
EnumCase
| Field | JSON type | Presence |
|---|---|---|
name |
string | required |
documentation |
Documentation |
optional |
UnionCase
| Field | JSON type | Presence |
|---|---|---|
name |
string | required |
documentation |
Documentation |
optional |
payload |
TypeExpr |
optional |
payloadを省略したcaseは、payloadを持たない。
OperationDeclaration
| Field | JSON type | Presence |
|---|---|---|
name |
string | required |
documentation |
Documentation |
optional |
parameters |
ParameterDeclarationのarray |
required |
returns |
ReturnDeclaration |
required |
ParameterDeclaration
| Field | JSON type | Presence |
|---|---|---|
name |
string | required |
required |
boolean | required |
documentation |
Documentation |
optional |
type |
TypeExpr |
required |
ReturnDeclaration
| Field | JSON type | Presence |
|---|---|---|
documentation |
Documentation |
optional |
type |
TypeExpr |
required |
JSON shapeの検証だけでは、Descriptorのvalidityは確認できない。名前一意性、Named参照、cycle、型整合性等も、3. Protocolに従って検証する。
Typesとoperationsを含む、完全なDescriptorの例:
{
"format": "wip-interface/1",
"documentation": {
"summary": "Reads items and their relationships."
},
"types": [
{
"name": "Relation",
"definition": {
"kind": "enum",
"cases": [
{ "name": "parent" },
{ "name": "sibling" }
]
}
},
{
"name": "RelatedItem",
"definition": {
"kind": "union",
"cases": [
{
"name": "found",
"payload": { "kind": "entry" }
},
{ "name": "not_found" }
]
}
}
],
"operations": [
{
"name": "get_related_item",
"parameters": [
{
"name": "relation",
"required": true,
"type": {
"kind": "named",
"name": "Relation"
}
}
],
"returns": {
"type": {
"kind": "named",
"name": "RelatedItem"
}
}
}
]
}
Operation Value
Operationのargumentsとresultは、選択したInterface DescriptorのTypeExprに従ってJSONへencodeする。Raw Value variantを示す共通tagged envelopeは使用しない。
| TypeExpr | JSON encoding |
|---|---|
| Unit | null |
| Boolean | boolean |
| Integer | 小数部と指数部を持たないJSON number。-9007199254740991から9007199254740991まで |
| Number | finiteなJSON number |
| String | string |
| Bytes | canonical base64 string |
| Json | JSONのnull、boolean、number、string、array、object |
| Entry | canonical absolute Worldspace pathのstring |
| Named | 同じDescriptor内の参照先TypeExprと同じencoding |
| Record | declarationされたfieldをmemberとするobject |
| List | items TypeExprに従うarray |
| Enum | 宣言されたcase名のstring |
| Union | $caseと、必要ならvalueを持つobject |
Json内部のnumberにも、相互運用可能なsafe integerまたはfinite binary64という制約を適用する。小数部と指数部を持たずsafe integer範囲にあるJSON numberはlogical Integerとして、それ以外のfiniteなJSON numberはlogical Numberとしてdecodeする。
Json内部にはBytesの特別なencodingを適用しない。Base64らしいstringがあっても、Bytesと推測しない。
RecordとOperation argumentsでは、required = falseのfieldやparameterを省略できる。ただし、省略とnullは異なる。TypeExprがUnit、Json、またはそれらへ解決されるNamedである場合、存在するmemberのnullはその型のvalueであり、省略を表さない。それ以外の型ではnullを使用してはならない。
Record valueには、declarationされていないmemberを含めない。Operation argumentsは、parameter名をmember名とするJSON objectであり、位置引数を使用しない。引数のないOperationには空objectを使用する。
Enumはcase名だけをstringで表し、object envelopeは使用しない。
Payloadを持つUnionは、$caseとvalueを持つ次の形で表す。
{
"$case": "found",
"value": "/items/123"
}
Payloadを持たないUnionでは、valueを省略する。
{
"$case": "not_found"
}
Union objectに含めるmemberは、$caseと必要なvalueだけである。Payloadありcaseではvalueがrequiredとなり、payloadなしcaseではvalueを禁止する。
Clientは、Descriptorに従ってvalueをdecodeする。Worldspace entryとして認識するのは、entryと宣言された位置のstringだけである。通常のStringやopaqueなJsonに含まれるpathらしいstringから、entryを推測しない。
observe
Request
POST v1/observeのbodyには、次のJSON objectを使用する。
| Field | JSON type | Presence |
|---|---|---|
path |
canonical absolute Worldspace pathのstring | required |
depth |
0以上4294967295以下のinteger |
required |
{
"path": "/items",
"depth": 1
}
Success response
Success bodyには、rootのObjectObservationを直接encodeする。
{
"object": {
"name": "items",
"description": "Item collection",
"interfaces": [{ "scope": "/", "name": "item-collection-interface-v1" }],
"validator": "cm9vdC12YWxpZGF0b3I="
},
"children": [
{
"object": {
"name": "123",
"description": "First item",
"interfaces": [{ "scope": "/", "name": "item-interface-v1" }],
"ref": "item:123",
"validator": "aXRlbS12YWxpZGF0b3I="
}
}
]
}
Responseのpath、name、depth、children completenessは、requestと3. Protocolに従って検証する。Hostがresource budget内で完全なresponseを構築できない場合は、partial successにせず、resource_limit_exceededを返す。
fetch_interface
Request
POST v1/fetch_interfaceのbodyには、次のJSON objectを使用する。
| Field | JSON type | Presence |
|---|---|---|
interface |
InterfaceReference object |
required |
{
"interface": { "scope": "/", "name": "item-interface-v1" }
}
Success response
| Field | JSON type | Presence |
|---|---|---|
interface |
InterfaceReference object |
required |
scope_ref |
scope Objectのrefを表すstring |
optional |
descriptor |
Interface Descriptor object | required |
validator |
canonical base64 string | optional |
{
"interface": { "scope": "/", "name": "item-interface-v1" },
"scope_ref": "world:root",
"descriptor": {
"format": "wip-interface/1",
"types": [],
"operations": []
},
"validator": "aW50ZXJmYWNlLXZhbGlkYXRvcg=="
}
Responseのinterfaceは、requestと完全一致しなければならない。scope_ref、Descriptor、validatorは、一つのInterface observationとして扱う。
scope_refはscope Objectのrefと同じopaque stringであり、base64化しない。Scope Objectがrefを持つ場合は含め、持たない場合は省略する。nullは使用しない。
Scope Objectにrefがない場合も、次のresponseはvalidである。
{
"interface": { "scope": "/", "name": "item-interface-v1" },
"descriptor": {
"format": "wip-interface/1",
"types": [],
"operations": []
}
}
scope_refもvalidatorもない観測は許可される。この場合、scopeのidentityは追跡できず、Descriptorは参照の有効期間中immutableとして扱う。
call_operation
Request
POST v1/call_operationのbodyには、次のJSON objectを使用する。
| Field | JSON type | Presence |
|---|---|---|
target |
Target object |
required |
interface |
InterfaceTarget object |
required |
operation |
Operation名のstring | required |
arguments |
選択したOperation declarationに従うobject | required |
Targetは、pathとoptionalなvalidatorを次のfieldで表す。
| Field | JSON type | Presence |
|---|---|---|
path |
canonical absolute Worldspace pathのstring | required |
validator |
canonical base64 string | optional |
InterfaceTargetは、参照とその観測metadataを次のfieldで表す。
| Field | JSON type | Presence |
|---|---|---|
reference |
InterfaceReference object |
required |
scope_ref |
観測したscope Objectのrefを表すstring |
optional |
validator |
canonical base64 string | optional |
{
"target": {
"path": "/items/current",
"validator": "b2JqZWN0LXZhbGlkYXRvcg=="
},
"interface": {
"reference": { "scope": "/", "name": "item-interface-v1" },
"scope_ref": "world:root",
"validator": "aW50ZXJmYWNlLXZhbGlkYXRvcg=="
},
"operation": "get_related_item",
"arguments": {
"relation": "sibling"
}
}
interface.referenceとoperationは、別fieldである。表示用の/::item-interface-v1#get_related_itemを、一つのfieldへencodeしない。scope_refもInterfaceReferenceのmemberや短縮表記の一部にはせず、InterfaceTargetの独立したoptional fieldとして送る。
Clientは、fetch_interfaceの観測にscope_refがあればコピーし、なければ省略する。nullや非stringをscope_refに指定したrequestは、invalid_requestとなる。
Validなstringを指定していても、現在のscope Objectのrefと一致しない場合は、Protocolの検証順に従ってinterface_mismatchとする。現在のrefが欠落している場合も含む。scope_refを省略した場合はscope identity preconditionを適用せず、省略だけを理由に拒否しない。
Hostはまず、Descriptorに依存しないtarget、interface、operationのshapeを検証する。次に、Protocolのerror precedenceに従って現在のObjectとInterface observationを固定し、そのDescriptorに従ってargumentsをdecodeする。
Success response
| Field | JSON type | Presence |
|---|---|---|
result |
Operation return TypeExprに従うJSON value | required |
validator |
実行後のObject validatorを表すcanonical base64 string | optional |
{
"result": {
"$case": "found",
"value": "/items/123"
},
"validator": "bmV3LW9iamVjdC12YWxpZGF0b3I="
}
resultのencodingには、requestで指定し、Hostがprecondition確認時に固定したOperation declarationのreturn TypeExprを使用する。
Validator
Object validatorとInterface validatorは、対応する次のJSON body fieldにcanonical base64としてencodeする。
Object.validatorTarget.validatorFetchInterfaceResponse.validatorInterfaceTarget.validatorCallOperationResponse.validator
WIP validatorをETag、If-Match、その他のHTTP headerだけへ移し、body fieldを省略してはならない。
Host、gateway、HTTP cacheは、通常のHTTP representation metadataとしてETag等を追加してよい。ただし、その値はWIP validatorとは独立している。ClientはHTTP metadataを、Object identity、Interface observation、Operation preconditionとして解釈しない。
Protocol error envelope
各interactionのProtocol failureは、次のexactなJSON objectとしてencodeする。
{
"error": {
"code": "invalid_arguments",
"message": "Required argument `relation` is missing"
}
}
Top-level objectに含めるのはerrorだけである。error objectも、次のfieldだけを持つ。
| Field | JSON type | Presence |
|---|---|---|
code |
下表のstableなsnake_case string | required |
message |
boundedな人間向け診断string | required |
Clientはmessageを分岐に使用しない。Hostは秘密情報、credential、非公開Object、backend path、内部stack traceをmessageへ含めない。
ProtocolErrorCodeには、次のwire spellingとcanonical HTTP statusを対応付ける。
| Protocol error code | Wire spelling | HTTP status |
|---|---|---|
InvalidRequest |
invalid_request |
400 Bad Request |
NotFound |
not_found |
404 Not Found |
InterfaceNotFound |
interface_not_found |
404 Not Found |
InterfaceMismatch |
interface_mismatch |
409 Conflict |
OperationNotFound |
operation_not_found |
404 Not Found |
InvalidArguments |
invalid_arguments |
422 Unprocessable Content |
ValidatorRequired |
validator_required |
428 Precondition Required |
ValidatorMismatch |
validator_mismatch |
412 Precondition Failed |
InterfaceValidatorRequired |
interface_validator_required |
428 Precondition Required |
InterfaceValidatorMismatch |
interface_validator_mismatch |
412 Precondition Failed |
PermissionDenied |
permission_denied |
403 Forbidden |
ResourceLimitExceeded |
resource_limit_exceeded |
422 Unprocessable Content |
Internal |
internal |
500 Internal Server Error |
OperationOutcomeUnknown |
operation_outcome_unknown |
500 Internal Server Error |
resource_limit_exceededは、WIP Protocolが扱うlogical requestまたはresponseの上限超過を表す。Observation completeness、logical nesting、collection件数等が対象であり、HTTP statusには422 Unprocessable Contentを使用する。HTTP implementationやdeploymentのmessage-size上限超過を、このcodeへ変換しない。
Rate limitやdeployment concurrency limitによる429 Too Many Requestsは、Transport / deployment concernである。ValidなProtocol error envelopeがない限り、ResourceLimitExceededへ変換しない。
Hostは、interactionごとに3. Protocolで許可されたcodeだけを返す。ClientがvalidなProtocol error envelopeを取得した場合、回復actionはcodeに従う。HTTP statusがcanonical mappingと一致しなくても、statusから別codeを推測しない。Status mismatchは、Binding違反として診断してよい。
InvalidResponseとUnsupportedDescriptorFormatはClient-local classificationであり、Hostがerror envelopeで返してはならない。Domain failureもProtocol errorへ変換せず、Operation return typeに従うApplication dataとしてencodeする。
HTTP authentication boundary
Authentication方式、credential、mTLS、proxy、gateway等は、HTTP implementationとdeploymentが設定・運用する。このbindingは規定しない。
HTTP layerがWIP interactionを開始せずに返す401 Unauthorizedや403 Forbiddenは、validなProtocol error envelopeを持たないTransport failureである。ClientはこれらをPermissionDeniedへ変換しない。
WIP interactionを開始した後のObject、Interface、Operation visibilityとauthorizationは、Protocol semanticsに従う。ProtocolのPermissionDeniedは、validなWIP error envelopeを持つ403 Forbiddenであり、HTTP layerのaccess rejectionとは区別する。
HTTP replay
3xx response自体は、WIP successやProtocol failureではなく、Transport failureである。Endpoint discovery、redirect、proxy routingの扱いは、HTTP implementationとdeploymentが決定する。
ただし、これらの機構によって、一つのlogical call_operation requestを複数回dispatchしてはならない。Dispatch後にredirect responseを受け取った場合も、methodとbodyを維持して別endpointへ自動再送しない。
Dispatchとretry
Failureをnot dispatchedとして扱えるのは、requestがHostへ送信されていないとTransport実装が証明できる場合である。送信開始後にresponseを取得できない場合、ClientはHostがrequestを受理した可能性を否定しない。
observeとfetch_interfaceの再送とtimeout・retry・cancellation policyは、ClientとHTTP実装が決定する。Response ownershipとProtocol上のcache semanticsは、4. Clientに従う。
call_operationには、次の規則を適用する。
- Redirect、connection retry、HTTP stackのautomatic replay、proxy retryによって再送しない。
Retry-AfterまたはHTTP statusだけを理由に再送しない。- Response不達またはlocal cancellationを、Operationが未実行またはrollback済みである証拠として扱わない。
internalまたはoperation_outcome_unknownを受信しても自動再実行しない。- 同じOperationを利用者が改めて実行する場合は、Protocolの回復規則に従って必要なObjectまたはInterfaceを再観測する。
HTTP implementationとdeploymentは、失敗したPOST v1/call_operationを透過的にreplayしない。
HTTP facilitiesとの境界
HTTP cache、proxy、gateway、compression、connection管理、TLS、message size、timeout、concurrency、rate limit等の設定と運用は、このbindingの規定対象外である。
HTTP cache metadataは、WIP ClientのKnown Space、Interface cache、Object validator、Interface validatorとは別の機構である。ETag、If-Match、Age、Last-Modified等を、WIP observationやvalidatorとして解釈しない。それ以外のHTTP cache policyは、HTTP implementationとdeploymentが決定する。
HTTP implementationやdeploymentの都合でrequestやresponseを交換できない場合、ClientはTransport failureとして扱う。WIPはこれらの運用設定を規定せず、そのfailureをresource_limit_exceededその他のProtocol errorへ包み直さない。
非目標
このbindingの定義には、次のものを含めない。
- Host内部のAPI、database、filesystem、queueとの接続方法。
- Endpoint discovery service。
- 固定のauthentication scheme。
- HTTP cacheを使ったWorldspace同期。
- Operation idempotency keyまたはexactly-once execution。
- Operation cancellation protocol。
- Streaming、subscription、server push、WebSocket binding。
- 複数のCore interactionを一つのWIP requestへまとめる共通envelope。
- Domain failureの共通HTTP mapping。