【注意】 このドキュメントは、W3CのWeb Annotation Protocol W3C Recommendation 23 February 2017の和訳です。
このドキュメントの正式版はW3Cのサイト上にある英語版であり、このドキュメントには翻訳に起因する誤りがありえます。誤訳、誤植などのご指摘は、訳者までお願い致します。
訳注: Annotation、Collection、Container等、頭文字が大文字になっている語句が本文中に多く出現しますが、それらは大文字・小文字を区別せずに訳しました。
First Update: 2017年3月11日
公開以後に報告されたエラーや問題がないか正誤表を確認してください。
このドキュメントは、規範以外の形式でも入手できます: ePub
この仕様の英語版が唯一の規範のバージョンです。非規範の翻訳版も入手可能かもしれません。
Copyright © 2017 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
アノテーションは、一般的に、資源または資源間の関連性に関する情報を伝えるために用いられます。簡単な例には、1つのウェブ・ページや画像に関するコメントやタグ、ニュース記事に関するブログの投稿が含まれます。
ウェブ・アノテーション・プロトコルは、ウェブ・アーキテクチャおよびRESTのベスト・プラクティスと一貫性のある方法でアノテーションを作成・管理するための転送メカニズムについて記述しています。
この項は、このドキュメントの公開時のステータスについて記述しています。他のドキュメントがこのドキュメントに取って代わることがありえます。現行のW3Cの刊行物およびこの技術報告の最新の改訂版のリストは、http://www.w3.org/TR/のW3C技術報告インデックスにあります。
この勧告の公開により、W3Cは、この勧告で規定している機能は、アクティビティ・ストリームズ2.0[activitystreams-core]およびアクティビティ語彙[activitystreams-vocabulary]の仕様が勧告に進んだ際に、その変更によって影響を受けることはないと予想しています。
このドキュメントは、ウェブ・アノテーション・ワーキンググループによって勧告として公開されました。このドキュメントに関してコメントを行いたい場合には、[email protected](購読、アーカイブ)にお送りください。どのようなコメントでも歓迎します。
ワーキンググループの実装報告書を参照してください。
このドキュメントは、W3Cメンバー、ソフトウェア開発者、他のW3Cグループ、および他の利害関係者によりレビューされ、W3C勧告として管理者の協賛を得ました。これは確定済みドキュメントであり、参考資料として用いたり、別のドキュメントで引用したりすることができます。勧告の作成におけるW3Cの役割は、仕様に注意を引き付け、広範囲な開発を促進することです。これによってウェブの機能性および相互運用性が増強されます。
このドキュメントは、2004年2月5日のW3C特許方針の下で活動しているグループによって作成されました。W3Cは、このグループの成果物に関連するあらゆる特許の開示の公開リストを維持し、このページには特許の開示に関する指示も含まれています。不可欠な請求権(Essential Claim(s))を含んでいると思われる特許に関して実際に知っている人は、W3C特許方針の6項に従って情報を開示しなければなりません。
このドキュメントは、2015年9月1日のW3Cプロセス・ドキュメントによって管理されています。
この項は非規範的です。
システム間の相互運用性には、システム間でやり取りされるデータの構文とセマンティクス、そして、そのやり取りの転送メカニズムという、2つの基本的な側面があります。HTTPプロトコルとウェブ・アーキテクチャは、標準的なトランスポート層に関する重要な出発点となり、システム間でコンテンツを容易かつ効果的にやり取りするために使用できます。これらの基盤に基づくことにより、既存の技術やパターンを利用し、一貫性と開発容易性を確保することができます。
ウェブ・アノテーション・プロトコルは、アノテーションを作成、管理、検索するための転送メカニズムについて記述しています。この仕様のアノテーションは、ウェブ・アノテーション・データ・モデル[annotation-model]およびウェブ・アノテーション語彙[annotation-vocab]の要件に従っているものと想定されます。この仕様は、RESTの原則とリンクト・データ・プラットフォーム[ldp]の勧告を基にしており、それに精通していることが推奨されます。
ウェブ・アノテーション・プロトコルの主な目的は、アノテーションのクライアントとサーバーがシームレスに相互運用できるような一連の対話の標準を提供することです。アノテーションプロトコルのエンドポイントおよびそれとの対話方法を発見できることにより、クライアントを自動的に、または、ユーザが設定し、アノテーションを、一組のクライアントとサーバーに閉じ込めるのではなく、互換性のある遠隔システムに蓄積することができます。
ウェブ・アノテーション・モデル、LDP、RESTに精通している人にとっては、アノテーション・プロトコルの大半は非常に明確でしょう。下記の側面が最も重要な新しい要件です。
application/ld+json;profile="http://www.w3.org/ns/anno.jsonld
です。ldp:constrainedBy
のURLはhttp://www.w3.org/TR/annotation-protocol/
です。http://www.w3.org/ns/oa#annotationService
のrel
タイプを用いて任意の資源からアノテーション・コンテナを参照できます。非規範的と記している項と同じく、この仕様のすべての作成ガイドライン、図、例、注は、非規範的です。この仕様のその他の部分はすべて規範的です。
「することができる/してもよい(MAY)」、「しなければならない(MUST)」、「してはならない(MUST NOT)」、「推奨される(RECOMMENDED)」、「すべきである/する必要がある(SHOULD)」、「すべきでない/する必要がない(SHOULD NOT)」というキーワードは、[RFC2119]で記述されているように解釈されるべきです。
ウェブ・アノテーション・プロトコルは、次の基本原則を用いて定義されています。
アノテーション・サーバーは、アノテーションのIRIに次のHTTPメソッドをサポートしなければなりません(MUST)。
GET
(アノテーションの記述内容を検索する)、HEAD
(エンティティー・ボディなしにアノテーションのヘッダーを検索する)、OPTIONS
(CORSプレフライト・リクエスト[cors]を有効にする)。サーバーは、アノテーションの検索を含むすべての対話にHTTPではなくHTTPSを用いるべきです(SHOULD)。
サーバーは、ウェブ・アノテーション・プロファイルを用いてJSON-LD表現をサポートしなければなりません(MUST)。その応答には、application/ld+json
というメディア・タイプのContent-Type
ヘッダーがなければならず(MUST)、そのprofile
パラメータにはhttp://www.w3.org/ns/anno.jsonld
というウェブ・アノテーション・のプロファイルIRIがあるべきです(SHOULD)。
サーバーは、Turtle表現をサポートすべきで(SHOULD)、その他の形式をサポートできます(MAY)。複数のアノテーションの表現を利用できる場合は、サーバーは内容交渉をサポートすべきです(SHOULD)。様々なシリアル化に対する内容交渉は、希望するメディア・タイプをリクエストのHTTP Accept
ヘッダーに含めることで実行されますが、クライアントは、サーバーがそのプレファレンスを尊重することを前提とすることはできません[rfc7231]。
サーバーは様々なJSON-LDプロファイルをサポートできます(MAY)。様々なJSON-LDプロファイルに対する内容交渉は、Accept
ヘッダーの一部として、空白で区切られた引用符付きリストでJSON-LDメディア・タイプにprofile
パラメータを追加することで実行されます。
サーバーは、アノテーションを検索するリクエストの処理中にエラーが発生しなかった時には、200のHTTPステータス・コードを用いるべきで(SHOULD)、3XXのHTTPステータス・コードを用いて新しいロケーションにリダイレクトできます(MAY)。
アノテーション・サーバーからの応答には、ターゲットIRIがhttp://www.w3.org/ns/ldp#Resource
で、rel
パラメータの値がtype
であるLink
ヘッダー・エントリーがなければなりません(MUST)。http://www.w3.org/ns/oa#Annotation
というアノテーション・タイプを同じrel
タイプを用いて追加することもできます(MAY)。これは、たとえクライアントがその表現の形式を処理できなくても、検索された表現が資源とアノテーションであることをクライアントシステムに知らせるためのものです。
HEADおよびGETのリクエストでは、応答には、HTTP[rfc7232]のエンティティー・タグの概念を実装したエンティティー参照値を持つETag
ヘッダーがなければなりません(MUST)。この値は、更新または削除のリクエストを送信する時にクライアントが用いるでしょう。
応答には、アノテーションとの対話に利用できるHTTPメソッド[rfc7231]を列挙したAllow
ヘッダーがなければなりません(MUST)。
HEADおよびGETのリクエストでは、サーバーが、形式またはJSON-LDプロファイルによる内容交渉をサポートしている場合、応答には、値にAccept
があるVary
ヘッダーがなければなりません(MUST)[rfc7231]。これは、そのリクエスト・ヘッダーの値に基づいて表現が変わるということをキャッシュが理解していることを確保するためです。
GET /annotations/anno1 HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
HTTP/1.1 200 OK
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Link: <http://www.w3.org/ns/ldp#Resource>; rel="type"
ETag: "_87e52ce126126"
Allow: PUT,GET,OPTIONS,HEAD,DELETE,PATCH
Vary: Accept
Content-Length: 287
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/annotations/anno1",
"type": "Annotation",
"created": "2015-01-31T12:03:45Z",
"body": {
"type": "TextualBody",
"value": "I like this page!"
},
"target": "http://www.example.com/index.html"
}
アノテーション・サーバーが、作成、更新、削除の1つ以上を含むアノテーションの管理をサポートしている場合は、下記の項の要件が当てはまります。アノテーション・プロトコルは、ウェブ・アノテーション・データ・モデル[annotation-model]から派生した一部の追加の制約を用いた、リンクト・データ・プラットフォーム[ldp]仕様の利用法です。
アノテーション・サーバーは、アノテーション・コンテナという、アノテーションを管理できるコンテナを1つ以上提供しなければなりません(MUST)。アノテーション・コンテナは、コンテナ[ldp](アノテーションを管理するためのサービス)であると同時にOrderedCollection[activitystreams-core](アノテーションの順序付きリスト)でもあります。これには記述と技術情報を関連付けることができ、クライアントがそれをユーザに提供することで、そのユーザはそれを用いるべきか否かを判断できるようになります。コレクション・モデルのクラス、プロパティー、表現については、ウェブ・アノテーション・データ・モデルで記述されており、アクティビティ・ストリームズへのマッピングがウェブ・アノテーション語彙[annotation-vocab]で提供されています。
アノテーション・コンテナは、LDP基本コンテナ仕様を実装すべきですが(SHOULD)、ビジネス・ニーズを満たすために、直接コンテナや間接コンテナなどの他のタイプのコンテナを実装することもできます(MAY)。アノテーション・コンテナのURIには、クエリやフラグメント要素があってはならず(MUST NOT)、パス要素は「/
」という文字で終了しなければなりません(MUST)。
実装は、アノテーション・コンテナとのすべての対話にHTTPではなくHTTPSを用いるべきです(SHOULD)。
アノテーション・コンテナの作成、管理、構造は、この仕様の範囲外です。追加情報については、リンクト・データ・プラットフォーム仕様[ldp]を参照してください。
アノテーション・サーバーは、アノテーション・コンテナのIRIで次のHTTPメソッドをサポートしなければなりません(MUST)。
GET
(下記のとおり、コンテナの記述およびそのコンテンツのリストを検索する)、HEAD
(エンティティー・ボディなしにコンテナのヘッダーを検索する)、OPTIONS
(CORSプリフライト・リクエスト[cors]を有効にする)。アノテーション・コンテナにHTTP GETリクエストが行われた場合、サーバーはコンテナの記述を返さなければなりません(MUST)。その記述は、JSON-LDで利用できなければならず(MUST)、Turtleで利用できるべきで(SHOULD)、その他の形式で利用できてもかまいません(MAY)。コンテナの記述のJSON-LDシリアル化には、リクエストで別途定められている場合を除き、LDPコンテキスト(http://www.w3c.org/ns/ldp.jsonld
)と、ウェブ・アノテーションのプロファイルとコンテキスト[annotation-model]の両方を用いるべきです(SHOULD)。
リクエストがエラーなく正常に完了し、クライアントのプレファレンスに基づくリダイレクションの必要がない場合には、サーバーは200のHTTPステータス・コードを用いるべきです(SHOULD)。
コンテナのIRIからの、GET
、HEAD
、およびOPTIONS
の応答のAllow
ヘッダーでは、アノテーション・コンテナと対話を行うためにサポートしているすべてのメソッドが公言されているべきです(SHOULD)。Allow
ヘッダーは、他のどの応答にも含めることができます(MAY)。
アノテーション・コンテナは、次の要素を持つすべての応答においてLink
ヘッダー[rfc5988]を返さなければなりません(MUST)。
rel
パラメータの値がtype
、ターゲットIRIが適切なコンテナ型であるリンク(例えば、基本コンテナの場合はhttp://www.w3.org/ns/ldp#BasicContainer
など)を含むことで、そのタイプを公言しなければなりません(MUST)。http://www.w3.org/TR/annotation-protocol/
であり、rel
パラメータ値がhttp://www.w3.org/ns/ldp#constrainedBy
というIRIであるリンクを含めることで、それがアノテーション・プロトコル固有の制約を課すことを公言しなければなりません(MUST)。HEADおよびGETのリクエストでは、アノテーション・コンテナからの応答には、HTTP[rfc7232]のエンティティー・タグの概念を実装したETag
ヘッダーが含まれていなければなりません(MUST)。この値は、アノテーションを更新しようとするクライアントと同じ方法でそれをIf-Match
リクエスト・ヘッダーに含めることで、コンテナを更新する時に管理クライアントが用いるべきです(SHOULD)。
GETリクエストにAccept
ヘッダーがない場合、アノテーション・サーバーは、アノテーション・コンテナのJSON-LD表現で応答しなければなりませんが(MUST)、JSON-LDに対してプレファレンスを有するクライアントは、Accept
リクエスト・ヘッダーを用いてそれを明示的にリクエストすべきです(SHOULD)。
サーバーが、形式またはJSON-LDプロファイルによる内容交渉をサポートしている場合、アノテーション・コンテナからのHEADまたはGETリクエストへの応答には、リクエスト内のこのヘッダーの値に基づいて表現が変わるということをキャッシュが判断できるように、値にAccept
を含んだVary
ヘッダーがなければなりません(MUST)。
アノテーションを作成するためにPOSTメソッドの使用をサポートしているアノテーション・コンテナからの応答には、GET、HEAD、およびOPTIONSリクエストに対する応答にAccept-Post
ヘッダーが含まれているべきです(SHOULD)。値は、クライアントがPOSTで送信するために受け入れ可能なコンマで区切りのメディア・タイプのリストです[ldp]。
Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"
Link: <http://www.w3.org/TR/annotation-protocol/>; rel="http://www.w3.org/ns/ldp#constrainedBy"
ETag: "0f6b5cd8dc1f754a1738a53b1da34f6b"
Vary: Accept
Allow: POST, GET, OPTIONS, HEAD
Accept-Post: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld", text/turtle
1つのコンテナ内に多くのアノテーションが存在している可能性が高いため、アノテーション・プロトコルは、コンテナの内容を返すためにActivityStreamsコレクションのページング・メカニズムを採用しています。個々のコレクション・ページには、すべてのページを横断した時に、クライアントがコンテナ/コレクションの完全な順序付きコンテンツを再構築できるような、管理されたアノテーションのサブセットを持つ順序付きリストが含まれています。個々のページに含まれるIRIやアノテーション記述の数はサーバー次第であり、ページ間で矛盾していてもかまいません。アノテーションをソートする機能は、応答では明示されません。
アノテーション・コレクションのJSON-LD表現に関する要件は、ウェブ・アノテーション・データ・モデルで定義されており、ここで要約しています。
コレクションは、それを識別するIRIを持っていなければならず(MUST)、少なくともAnnotationCollection
クラス(JSON-LDのコンテキストにおいてOrderedCollectionと関連付けられている名前)を持っていなければなりませんが(MUST)、利用するLDPコンテナのタイプを含むその他のタイプを持つこともできます(MAY)。それは、人間が読めるlabel
を持っているべきで(SHOULD)、creator
やcreated
などのその他のプロパティーを持つことができます(MAY)。
コンテナに1つ以上のアノテーションがある場合、その表現には、first
プロパティーの値としてアノテーションの最初のページへのリンクが含まれているか、応答内に組み込まれた最初のページの表現が含まれていなければなりません(MUST)。2ページ以上のアノテーションがある場合、表現には、last
プロパティーを用いて最後のページへのリンクがあるべきです(SHOULD)。
コンテナの表現には、コンテナ内のアノテーションの合計数を記述したtotal
プロパティーが含まれているべきです(SHOULD)。コンテナには、コンテナ内のいずれかのアノテーションの最新のタイム・スタンプを記述したmodified
プロパティーが含まれているべきです(SHOULD)。このタイム・スタンプにより、同じ数が追加・削除されて同じ数のアノテーションが存在している場合であっても、データを再キャッシュすべきタイミングをクライアントが検出できます。
応答で提供されるコンテナのIRIで、ページにIRIだけが含まれているのか、それともアノテーションの完全な記述が含まれているのかを区別できるべきです(SHOULD)。これは、クエリ・パラメータで行うことを推奨します(RECOMMENDED)。サーバーは、クライアントをこのIRIにリダイレクトし、そこに応答を配信することができます(MAY)。そうでない場合は、その値としてIRIを持つContent-Location
ヘッダーが含まれていなければなりません(MUST)。
サーバーの応答の表現を制御するコンテナ・リクエストには、次の3つのプレファレンスがあります。
return=representation;include="http://www.w3.org/ns/ldp#PreferMinimalContainer"
という値を持つPrefer
リクエスト・ヘッダーが含まれていなければなりません(MUST)。return=representation;include="http://www.w3.org/ns/oa#PreferContainedIRIs"
という値を持つPrefer
リクエスト・ヘッダーが含まれていなければなりません(MUST)。return=representation;include="http://www.w3.org/ns/oa#PreferContainedDescriptions"
という値を持つPrefer
リクエスト・ヘッダーが含まれていなければなりません(MUST)。リンクト・データ・プラットフォーム[ldp]で定義されているとおり、クライアントは、複数のプレファレンスをinclude
パラメータの値として送信できます(MAY)。しかし、サーバーが両方を同時に尊重することはできないため、クライアントは、同じリクエストにPreferContainedIRIs
とPreferContainedDescriptions
のプレファレンスの両方を含めてはなりません(MUST NOT)。PreferMinimalContainer
プレファレンスが指定されている場合は、サーバーは、それにアノテーションや参照を組み込むべきではなく(SHOULD NOT)、最初と最後のアノテーション・ページへの参照を含むべきです(SHOULD)。ページがIRI参照なのか、完全な記述なのかは、それぞれPreferContainedIRIs
とPreferContainedDescriptions
の使用で制御できます。クライアントがプレファレンスを指定していない場合は、サーバーは、PreferContainedDescriptions
の挙動をデフォルト設定とすべきです(SHOULD)。サーバーは、クライアントのプレファレンスを無視できます(MAY)。
クライアントが、アノテーション・コンテナの最小限の表現をリクエストした場合、応答にはldp:contains
という述語を含むことも、応答内にアノテーションの最初のページを組み込むこともしてはなりません(MUST NOT)
リンクされたページは、PreferContainedDescriptions
またはPreferContainedIRIs
プレファレンスに従うべきです(SHOULD)。
サーバーは、PreferMinimalContainer
プレファレンスが提供されていなくても、アノテーションが組み込まれていない表現を返すことができます(MAY)。
GET /annotations/ HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Prefer: return=representation;include="http://www.w3.org/ns/ldp#PreferMinimalContainer http://www.w3.org/ns/oa#PreferContainedIRIs"
HTTP/1.1 200 OK
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
ETag: "_87e52ce123123"
Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"
Link: <http://www.w3.org/TR/annotation-protocol/>; rel="http://www.w3.org/ns/ldp#constrainedBy"
Allow: POST,GET,OPTIONS,HEAD
Vary: Accept
Content-Length: 368
{
"@context": [
"http://www.w3.org/ns/anno.jsonld",
"http://www.w3.org/ns/ldp.jsonld"
],
"id": "http://example.org/annotations/?iris=1",
"type": ["BasicContainer", "AnnotationCollection"],
"total": 42023,
"modified": "2016-07-20T12:00:00Z",
"label": "A Container for Web Annotations",
"first": "http://example.org/annotations/?iris=1&page=0",
"last": "http://example.org/annotations/?iris=1&page=42"
}
サーバーがコンテナのプレファレンスをサポートしている場合、first
の値としてAnnotationPage
を含み、そのitems
に、その含まれているアノテーションのIRIのみが含まれている応答でPreferContainedIRIs
に応答しなければなりません(MUST)。
リンクされたページは、PreferContainedIRIs
プレファレンスに従うべきです(SHOULD)。
PreferContainedIRIs
とPreferContainedDescriptions
のプレファレンスは互いに排他的です。
GET /annotations/ HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Prefer: return=representation;include="http://www.w3.org/ns/oa#PreferContainedIRIs"
HTTP/1.1 200 OK
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Location: http://example.org/annotations/?iris=1
ETag: "_87e52ce123123"
Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"
Link: <http://www.w3.org/TR/annotation-protocol/>; rel="http://www.w3.org/ns/ldp#constrainedBy"
Allow: POST,GET,OPTIONS,HEAD
Vary: Accept, Prefer
Content-Length: 397
{
"@context": [
"http://www.w3.org/ns/anno.jsonld",
"http://www.w3.org/ns/ldp.jsonld"
],
"id": "http://example.org/annotations/?iris=1",
"type": ["BasicContainer", "AnnotationCollection"],
"total": 42023,
"modified": "2016-07-20T12:00:00Z",
"label": "A Container for Web Annotations",
"first": {
"id": "http://example.org/annotations/?iris=1&page=0",
"type": "AnnotationPage",
"next": "http://example.org/annotations/?iris=1&page=1",
"items": [
"http://example.org/annotations/anno1",
"http://example.org/annotations/anno2",
"http://example.org/annotations/anno3",
"http://example.org/annotations/anno4",
"http://example.org/annotations/anno5",
"http://example.org/annotations/anno6",
...
"http://example.org/annotations/anno999",
]
},
"last": "http://example.org/annotations/?iris=1&page=42"
}
サーバーがコンテナのプレファレンスをサポートしている場合、first
の値としてAnnotationPage
を含み、そのitems
に完全なインラインのアノテーションが含まれている応答でPreferContainedDescriptions
に応答しなければなりません(MUST)。
リンクされたページは、PreferContainedDescriptions
プレファレンスに従うべきです(SHOULD)。
PreferContainedIRIs
とPreferContainedDescriptions
のプレファレンスは互いに排他的です。
GET /annotations/ HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Prefer: return=representation;include="http://www.w3.org/ns/oa#PreferContainedDescriptions"
HTTP/1.1 200 OK
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Allow: GET,OPTIONS,HEAD
Vary: Accept, Prefer
Content-Length: 924
{
"@context": [
"http://www.w3.org/ns/anno.jsonld",
"http://www.w3.org/ns/ldp.jsonld"
],
"id": "http://example.org/annotations/?iris=0",
"type": ["BasicContainer", "AnnotationCollection"],
"total": 42023,
"modified": "2016-07-20T12:00:00Z",
"label": "A Container for Web Annotations",
"first": {
"id": "http://example.org/annotations/?iris=0&page=0",
"type": "AnnotationPage",
"next": "http://example.org/annotations/?iris=0&page=1",
"items": [
{
"id": "http://example.org/annotations/anno1",
"type": "Annotation",
"body": "http://example.net/body1",
"target": "http://example.com/page1"
},
{
"id": "http://example.org/annotations/anno2",
"type": "Annotation",
"body": {
"type": "TextualBody",
"value": "I like this!"
},
"target": "http://example.com/book1"
},
...
{
"id": "http://example.org/annotations/anno50",
"type": "Annotation",
"body" : "http://example.org/texts/description1",
"target": "http://example.com/images/image1"
}
]
},
"last": "http://example.org/annotations/?iris=0&page=840"
}
個々のページは、アクティビティ・ストリームズのOrderedCollectionPage
クラスのインスタンスであり、それは、ウェブ・アノテーションJSON-LDのコンテキストではAnnotationPage
と呼ばれます。ページには、そのIRIまたは完全な記述のいずかを用いて、items
プロパティーにアノテーションが含まれています。
アノテーション・コレクション・ページのJSON-LD表現に関する要件は、ウェブ・アノテーション・データ・モデルで定義されており、ここで要約しています。
アノテーション・ページは、それを識別するIRIを持っていなければならず(MUST)、少なくともAnnotationPage
クラス持っていなければなりませんが(MUST)、その他のタイプを持つこともできます(MAY)。そのページが、コレクション内の最後のページでない場合は、next
プロパティーを用いて、それに後続するページへの参照がなければなりません(MUST)。そのページが、コレクション内の最初のページでない場合は、prev
プロパティーを用いて、先行するページへの参照があるべきです(SHOULD)。ページは、0オリジン(zero-based)のstartIndex
プロパティーを用いてコレクションの順序と相対的にitems
リスト内の最初のアノテーションの位置を示すべきです(SHOULD)。
各ページには、partOf
プロパティーを用いて、その一部であるコレクションへのリンクがなければなりません(MUST)。コレクションの記述には、total
およびmodified
のプロパティーが含まれているべきです(SHOULD)。応答には、label
やfirst
とlast
のリンクなど、応答のコレクションのその他のプロパティーを含むことができます(MAY)。
クライアントは、ページをリクエストする時にPrefer
ヘッダーを送信すべきではありません(SHOULD NOT)。これは、コレクションをリクエストする時にすでに考慮されているためです。
この仕様では、クライアントがページに、GET、HEAD、またはOPTIONS以外のリクエストを行う時に、特定の機能は必要ありません。
ページはLDPコンテナではないため、タイプを持つLink
ヘッダーを含める必要はありません。コンテナのIRIに追加されたクエリ・パラメータでURLを構築できることは、実装上の便宜であり、資源のタイプを暗示するものではありません。
組み込まれたIRIの対話の例
GET /annotations/?iris=1&page=0 HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
HTTP/1.1 200 OK
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Allow: GET,OPTIONS,HEAD
Vary: Accept
Content-Length: 630
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/annotations/?iris=1&page=0",
"type": "AnnotationPage",
"partOf": {
"id": "http://example.org/annotations/?iris=1",
"total": 42023,
"modified": "2016-07-20T12:00:00Z",
},
"startIndex": 0,
"next": "http://example.org/annotations/?iris=1&page=1",
"items": [
"http://example.org/annotations/anno1",
"http://example.org/annotations/anno2",
"http://example.org/annotations/anno3",
"http://example.org/annotations/anno4",
"http://example.org/annotations/anno5",
"http://example.org/annotations/anno6",
...
"http://example.org/annotations/anno999",
]
}
組み込まれた記述の対話の例
GET /annotations/?iris=0&page=0 HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
HTTP/1.1 200 OK
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Allow: GET,OPTIONS,HEAD
Vary: Accept, Prefer
Content-Length: 924
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/annotations/?iris=0&page=0",
"type": "AnnotationPage",
"partOf": {
"id": "http://example.org/annotations/?iris=0",
"total": 42023,
"modified": "2016-07-20T12:00:00Z",
},
"startIndex": 0,
"next": "http://example.org/annotations/?iris=0&page=1",
"items": [
{
"id": "http://example.org/annotations/anno1",
"type": "Annotation",
"body": "http://example.net/body1",
"target": "http://example.com/page1"
},
{
"id": "http://example.org/annotations/anno2",
"type": "Annotation",
"body": {
"type": "TextualBody",
"value": "I like this!"
},
"target": "http://example.com/book1"
},
...
{
"id": "http://example.org/annotations/anno50",
"type": "Annotation",
"body" : "http://example.org/texts/description1",
"target": "http://example.com/images/image1"
}
]
}
アノテーション・コンテナのIRIは、あらゆるIRIでありえ(MAY)、すべてのウェブ・サーバーがその機能をサポートすることはありえないと思われるため、これらのサービスの可用性を発見できることは重要です。
資源上のアノテーションが参照先のコンテナ内で作成されるべきである(SHOULD)場合は、あらゆる資源をアノテーション・コンテナにリンクすることができます(MAY)。このリンクは、HTTP Link
ヘッダーで伝送され、rel
パラメータの値はhttp://www.w3.org/ns/oa#annotationService
でなければなりません(MUST)。
資源のHTML表現では、同等のlink
タグをドキュメントのヘッダーで用いることもできます(MAY)。
画像資源の例では、GETリクエストと、上記のアノテーション・コンテナへのリンクを持つ応答は、次のようになります。
リクエスト:GET /images/logo.jpg HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: image/jpeg
Link: <http://example.org/annotations/>; rel="http://www.w3.org/ns/oa#annotationService"
Allow: GET
Content-Length: 76983
[...]
新しいアノテーションは、アノテーション・コンテナへのPOSTリクエストにより作成されます。JSON-LDとしてシリアル化されたアノテーションは、リクエストの本文で送信されます。アノテーションに関するすべての既知の情報が送信されるべきであり(SHOULD)、資源に関連付けられているIRIが既に存在している場合は、それを含めるべきです(SHOULD)。シリアル化にはウェブ・アノテーションJSON-LDプロファイルを用いるべきで(SHOULD)、サーバーは、別の方法で同じモデルが生成される場合であっても、他のコンテキストを拒否することができます(MAY)。サーバーは、ウェブ・アノテーション仕様[annotation-model]に従い、アノテーションとみなされないコンテンツを拒否できます(MAY)。
アノテーションを受け取った時に、サーバーは、アノテーションの任意の資源または空白ノードにIRIを割り当てることができ(MAY)、既に提供されていても、id
プロパティーのアノテーション資源にIRIを割り当てなければなりません(MUST)。資源を個々に検索できる時には、サーバーはHTTPS IRIを用いるべきです(SHOULD)。アノテーションのIRIは、追加のコンポーネントを最後に追加したコンテナのIRIでなければなりません(MUST)。
サーバーは、アノテーションに情報を追加できます(MAY)。追加できる情報には、それを作成したエージェント、アノテーションの作成時間、構成資源の追加のタイプと形式が含まれます。
アノテーションにcanonical
プロパティーが含まれている場合は、その参照は変更せずに維持しなければなりません(MUST)。アノテーションのid
プロパティーにIRIがある場合は、それをvia
プロパティーにコピーすべきで(SHOULD)、アノテーションを利用できるサーバーが割り当てたIRIをid
フィールドに入れて置き換えなければなりません(MUST)。
サーバーは、作成が成功した場合は201
「生成」応答で、そうでない場合には、適切なエラーコードで応答しなければなりません(MUST)。応答には、アノテーションの新しいIRIを持つLocation
ヘッダーがなければなりません(MUST)。
POST /annotations/ HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Length: 202
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"type": "Annotation",
"body": {
"type": "TextualBody",
"value": "I like this page!"
},
"target": "http://www.example.com/index.html"
}
HTTP/1.1 201 CREATED
Allow: PUT,GET,OPTIONS,HEAD,DELETE,PATCH
Location: http://example.org/annotations/anno1
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Length: 287
ETag: "_87e52ce126126"
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/annotations/anno1",
"type": "Annotation",
"created": "2015-01-31T12:03:45Z",
"body": {
"type": "TextualBody",
"value": "I like this page!"
},
"target": "http://www.example.com/index.html"
}
資源のコンテナのIRIに付加されるIRIパス・セグメントは、資源が作成された時に、リクエストのSlug
HTTPヘッダーを用いて、アノテーション・クライアントにより提案できます(MAY)。サーバーは、それが既存の資源を識別していない限り、この名前を用いるべきですが(SHOULD)、それを無視し、自動的に割り当てた名前を用いることもできます(MAY)。
POST /annotations/ HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Length: 202
Slug: "my_first_annotation"
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"type": "Annotation",
"body": {
"type": "TextualBody",
"value": "I like this page!"
},
"target": "http://www.example.com/index.html"
}
HTTP/1.1 201 CREATED
Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"
Allow: PUT,GET,OPTIONS,HEAD,DELETE,PATCH
Location: http://example.org/annotations/my_first_annotation
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
ETag: "_87e52ce126126"
Vary: Accept
Content-Length: 301
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/annotations/my_first_annotation",
"type": "Annotation",
"created": "2015-01-31T12:03:45Z",
"body": {
"type": "TextualBody",
"value": "I like this page!"
},
"target": "http://www.example.com/index.html"
}
アノテーションは、PUTリクエストを用いてアノテーションの全体の状態を置き換えることにより更新できます。アノテーション・サーバーはこのメソッドをサポートすべきです(SHOULD)。サーバーは、アノテーションの変更された部分のみを更新するために、PATCHリクエストの使用もサポートできますが(MAY)、その機能はこのドキュメントでは規定していません。
新しい状態へのアノテーションの置き換えは、PUTメソッドで行わなければならず(MUST)、その場合、リクエストの本文が、意図するアノテーションの新しい状態となります。クライアントは、複数のユーザが同じアノテーションを同時に修正することによる衝突を避けるために、編集プロセスが始まる前にサーバーから受信したETagの値を持つIf-Match
ヘッダーを用いるべきです(SHOULD)。すべてのシステムに1つのアノテーションを変更する潜在力を持っているユーザが複数存在しているわけではなく、上書きが望ましい行為である状況をユースケースが規定している可能性があるため、この機能のサポートは必須ではありません。
サーバーは、canonical
やvia
のプロパティーの値が既に設定されている場合は、ビジネス・ロジックによってリクエストが以前のエラーとして厳然と正しく信頼できるようにならない限り、それらを修正する更新リクエストを拒否すべきです(SHOULD)。
成功した場合は、サーバーは、リクエストされたコンテンツ・タイプに応じて、アノテーションを本文として持つ200「OK」のステータスを返さなければなりません(MUST)。作成の場合と同様に、サーバーは、アノテーションの新しい状態を応答で返さなければなりません(MUST)。
PUT /annotations/anno1 HTTP/1.1
Host: example.org
Accept: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
Content-Length: 294
If-Match: "_87e52ce126126"
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/annotations/anno1",
"type": "Annotation",
"created": "2015-02-01T10:13:40Z",
"body": {
"type": "TextualBody",
"value": "I REALLY like this page!"
},
"target": "http://www.example.com/index.html"
}
HTTP/1.1 200 OK
Content-Type: application/ld+json; profile="http://www.w3.org/ns/anno.jsonld"
ETag: "_87e52ce234234"
Link: <http://www.w3.org/ns/ldp#Resource>; rel="type"
Allow: PUT,GET,OPTIONS,HEAD,DELETE,PATCH
Vary: Accept
Content-Length: 331
{
"@context": "http://www.w3.org/ns/anno.jsonld",
"id": "http://example.org/annotations/anno1",
"type": "Annotation",
"created": "2015-02-01T10:13:40Z",
"modified": "2015-02-02T20:43:19Z",
"body": {
"type": "TextualBody",
"value": "I REALLY like this page!"
},
"target": "http://www.example.com/index.html"
}
クライアントは、DELETE HTTPメソッドを用いて、サーバーがアノテーションを削除するようにリクエストしなければなりません(MUST)。アノテーション・サーバーはこのメソッドをサポートしなければなりません(SHOULD)。クライアントは、If-Match
ヘッダーでアノテーションのETagを送信して、それがアノテーションの最新バージョンに対する操作であることを保証すべきです(SHOULD)。
DELETEリクエストが正常に処理された場合は、サーバーは204のステータス応答を返さなければなりません(MUST)。削除されたアノテーションのIRIは、その後のアノテーションに再利用すべきではありません(SHOULD NOT)。削除されたアノテーションのIRIは、それが作成されたアノテーション・コンテナから削除しなければなりません(MUST)。応答の本文に関する要件はなく、空であってもかまいません(MAY)。
DELETE /annotations/anno1 HTTP/1.1
Host: example.org
If-Match: "_87e52ce126126"
HTTP/1.1 204 NO CONTENT
Content-Length: 0
この項は非規範的です。
アノテーションを検索・管理する時に、エラーが発生することは避けられません。下記のHTTPステータス・コードの使用は、リクエストが失敗した理由を理解する方法をクライアントに提供します。発生する可能性がある一部の状況と、望ましいHTTPステータス・コードを下記に示します。このリストは、HTTPで既に確立されている以上の追加要件を課すものではなく、参考情報かつ説明的なものです。
コード | 状況の例 |
---|---|
400 | アノテーション・クライアントは、リクエストが適切な仕様に従っていないためにアノテーション・サーバーが処理できないリクエストを送信した。 |
401 | アノテーション・クライアントは、認証証明を提供しなかったため、アノテーションの作成や削除などのリクエストされた操作を実行する承認を得られない。 |
403 | 提供された認証証明がアノテーションまたはアノテーション・コンテナに対する特定のアクセス・コントロール方針の要件を満たさなかったため、アノテーション・クライアントは、リクエストされた操作を実行する承認を得られない。 |
404 | リクエストされたアノテーションまたはアノテーション・コンテナは存在しない。 |
405 | アノテーション・コンテナ・ページにPOSTを試みたり、その機能がサポートされていない時にアノテーションにPATCHを試みたりするなど、リクエストされたHTTPメソッドは、資源に対して許されていない。 |
406 | 例えば、クライアントがRDF/XMLをリクエストしたが、サーバーがその(オプションの)変換をサポートしていないなど、アノテーションまたはアノテーション・コンテナの表現に対するリクエストされた形式は利用できない。 |
409 | アノテーション・クライアントは、アノテーション・コンテナの閉じ込めリストやサーバーの設定変更タイム・スタンプなどの、サーバーがクライアントに変更を許していない値を設定または変更しようとした。 |
410 | アノテーションは過去に存在していたことが知られているが削除された。 |
412 | アノテーション・クライアントは、変更されているアノテーションのETagと一致しないIf-Matchヘッダーを提供した。 |
415 | アノテーション・クライアントは、アノテーションではないものや認識されないコンテキストなど、サーバーが処理できないエンティティー・ボディを送信した。 |
この項は非規範的です。
この仕様を勧告案に進めるためには、下記の各機能の少なくとも2つの独立した実装がなければなりません。各機能は、異なる製品に実装でき、1つの製品がすべての機能を実装するという要件はありません。
機能終了基準を評価する目的では、下記の操作を機能とみなします。
個々の機能は、HTTPヘッダー、ステータス・コード、エンティティー・ボディに関して、仕様で示されている要件に従って実装されなければなりません。特定の機能の有無によってその動作を変更しないソフトウェアは、勧告候補段階を終了する目的でその機能を実装しているとはみなされません。
この項は非規範的です。
重要な変更はない。
2016年9月6日の勧告候補からのこの仕様の編集上の変更は、下記のとおりです。
2016年7月12日の勧告候補からのこの仕様の編集上の変更は、下記のとおりです。
Prefer
ヘッダーの適切な使用を説明草案公開2016年3月31日草案公開からのこの仕様の重要な技術的変更は、下記のとおりです。
ウェブ・アノテーション・ワーキンググループは、オープン・アノテーション・コミュニティ・グループの貢献に謝意を表します。コミュニティ・グループの成果が現在のデータ・モデルとプロトコルの基礎となりました。
この仕様の作成において、次の方々に、アイデア、フィードバック、レビュー、コンテンツ、批評およびインプットの提供でご協力いただきました。