LSL HTTP server/ja

== まえがき ==
これは llHTTPRequest の対となるものです。llHTTPRequest によって LSL スクリプトが HTTP でアクセスできる情報源にデータをリクエストすることができますが、 HTTP-in は外の情報源がセカンドライフ内のスクリプトにデータをリクエストできるようになります。その差は、llHTTPRequest が SL 内のスクリプトが欲しいときに情報交換するのに対し、HTTP-in は外の情報源の都合により SL 内のスクリプトとコミュニケーションすることができるということです。
HTTP-in ができるまでは、同じような機能はllHTTPRequest や llEmail や XML-RPC によるポーリングによって実現されていました。3 つとも扱いにくく、最後の 2 つは拡張性の上で深刻なボトルネックとなっていました。
気をつけたい重要な点は、LSL HTTP サーバが HTML を扱えないことです。詳細は、他の制約 を参照してください。
== 使用場面 ==
* LSL スクリプトからデータを取得し、外部ビューア、スクリプト、サーバに送ることが簡単にできます。
** ビジターカウンターやその他統計収集装置の Web フロントエンドに。
* 外部ビューア、スクリプト、サーバから LSL スクリプトにデータを送ることが簡単にできます。
** インワールドのオブジェクトと通信して、L$ やインベントリアイテムをやりとりする Web フロントエンドがある店舗。
** 外部プログラムがインワールドのアイテムを操作する必要のある重要なゲームロジックを握っているインワールドゲーム。
どろどろとした技術的な詳細は次項にて。もしくは、 Script Examples まで読み飛ばしてください。
== スクリプト API ==
* key llRequestURL()
: 新しい LSL サーバ公開 URL をリクエストします。
: 成功または失敗と、取得されたキーで、http_request イベントが発生します。
: 注意: URL は呼び出し元スクリプトに割り当てられています。http_request イベントは URL をリクエストしたスクリプトとは異なるスクリプトからは発生しません。
<lsl>request_id = llRequestURL();</lsl>
* key llRequestSecureURL()
: HTTPS / SSL URL をリクエストする点以外は、llRequestURL とほぼ同じです。
: 成功または失敗と、取得されたキーで、http_request イベントが発生します。
<lsl>request_id = llRequestSecureURL();</lsl>
* llReleaseURL(string url)
: 指定された URL を消去します。セキュアな URL にもセキュアでない URL にも使えます。
<lsl>llReleaseURL("http://sim3015.aditi.lindenlab.com:12046/cap/3ff4f3f2-ea08-76c1-cef6-a22b4a573a7c");</lsl>
* http_request(key id, string method, string body)
: URL がヒットしたときに発生するイベントです。
:* id はリクエストごとに違います。
:* サポートされるメソッドは、GET/POST/PUT/DELETE です。
:* body: リクエストの内容。
: イベントは llRequestURL や llRequestSecureURL へのレスポンスでも発生します。
:* id は llRequestURL や llRequestSecureURL で返却されたキーと一致します。
:* method == URL_REQUEST_GRANTED は成功していますが、 URL_REQUEST_DENIED は URL の取得に失敗しています。
:* body は公開 URL です。公開 URL の取得に失敗した場合は、空です。
* llHTTPResponse(key id, integer status, string body)
: リクエスト元の body にステータスコードを status で返します。
:* id は特定のリクエストに関連づけられた http_request の ID です。
:* リクエスト元にレスポンスを送信すると、リクエストを消去し、関連した情報を削除します。
* string llGetHTTPHeader(key id, string header)
: 指定されたリクエストの指定されたヘッダの文字列を返却します。受信されたヘッダは全て小文字に変換され、この関数は大文字小文字を区別します。返却される文字列は 255 文字までです。
:* サポートされるヘッダ:
::* "x-script-url": llRequestURL または llRequestSecureURLから取得したベース URL
::* "x-path-info": リクエスト先 URL の後続パスの情報
::* "x-query-string": クエリ引数、URL の最初に現れる "?" に続くテキスト文字列
::* "x-remote-ip": リクエストを生成したホストの IP アドレス
::* "user-agent": リクエスト元から通知された user-agent
:* llHTTPRequest() で送信されるサポートされるヘッダ
::* "x-secondlife-shard"
::* "x-secondlife-object-name"
::* "x-secondlife-object-key"
::* "x-secondlife-region"
::* "x-secondlife-local-position"
::* "x-secondlife-local-rotation"
::* "x-secondlife-local-velocity"
::* "x-secondlife-owner-name"
::* "x-secondlife-owner-key"
 requested url: https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322/foo/bar?arg=gra
 x-script-url: https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322
 x-path-info: /foo/bar
 x-query-string: arg=gra
: ヘッダ情報は 30 秒間か、llHTTPResponse が呼び出されるまで有効です。
* changed(integer change)
:* CHANGED_REGION_START: 地域が再起動されたときに呼び出される新しい changed() イベントです。
* integer llGetFreeURLs()
: スクリプトで使用できる URL の数を返します。
== URL 生存時間の制約 ==
* URL は 一時的 なものです！
* URL は以下の場合は消えることがあります。併記したスクリプトイベントで全て検出可能です。
** オブジェクトを設置／撤去した場合: on_rez
** スクリプトを保存／リセットした場合: default state_entry() (複数のステートがあるスクリプトでは要注意)
** 地域をまたがったり TP (アタッチメント) した場合: changed() , CHANGED_REGION と CHANGED_TELEPORT
** 地域が再起動された場合: changed() イベント、new フラグ CHANGED_REGION_START
* URL が「消失」した場合、スクリプトの全ての公開 URL が消失しています。新しい URL をリクエストする必要があり、新しい URL は以前のと 似ても似つかない ものになります。
* URL を永続化するには、Dynamic DNS がドメイン名と動的 IP アドレスを関連づけるのと同じような仕組みで動くような外部サービスを構築するか利用する必要が出てきます。
寄贈された HTTP-in URL マッピングの実装やサービス: 
* Google App Engine 上で動作する動的 DNS サービス (サンプルとして提供されました)。ここのフォーラムで見つけることができます。
* Virtual ID URLMap service はユーザが選んだ固定サブドメインのマッピングを REST API (一部無料 Apez Corp web-services API) を通じて行ってくれます。
* まだ他には、GAE の上で、パスワードで保護されたプライベートドメインで運用する方法があります。http://wiki.secondlife.com/wiki/Public_Object_DNS
== リソースの制約 ==
* それぞれの地域で使用できる URL の数に制限があります。ちょうどプリム数制限のように土地によって切り分けられています。
** llGetFreeURLs を使用してスクリプトで使用可能な URL の正確な数を取得してください。
** 使用可能な URL の数はオブジェクトが置かれている土地で使用可能なプリム数と同じです。
**: オブジェクトの持ち主が誰かにかかわらず、土地の上に置かれているオブジェクトはその土地のリソースプールを使用することになります。
**: プリムのように、同じ地域の中で同じ持ち主が所有している土地は全て同じリソースプールを共有します。
**: もし地域の中に 2 つの土地を持っており、それぞれが 100 個の URL をサポートするとすると、1 つの土地に置かれた (複数の) オブジェクトの中で、全部で 200 個使用することができます。
** 地域ののオブジェクトのボーナスは使用可能な URL の数に適用されません。
**: 土地のプリム数上限が 300 で、地域に 2 倍のプリムボーナスがついているとすると、150 個の URL だけが使用可能となります。
* それぞれの人はそれぞれの使用可能な URL のプールをもっていて、1 人あたりの最大 URL 数は 38 個です。
** 装着ポイントあたり 1 個ということになりますが、例えば 38 個全てを 1 個のアタッチメントで使用しても構いません。
* 乗り物は特別で、以下のロジックでぬらぬらと住民のプールを渡り歩くことになります。
** 「乗り物」ですから、オブジェクトには必ずそれに乗っている人がいます。
** 乗り物は、土地の境界線をまたがるまでは、今いる土地の URL リソースを使用します。
**: 具体的には、これにより、他人の自販機の上に乗っかってぶっ壊し、「乗り物」にするようなことはできません。
** URL リソースを使用していて、かつ人間が上に座っているオブジェクトが土地の境界線を越えると、リソースは最初に座った充分なリソースのある人に切り替わります。もしだれも充分なリソースを持っていなければ、土地のリソースが吸い上げられて使用されます。もしも土地にも充分なリソースがなければ、乗り物は移動できなくなります。
**: つまり、乗り物が必要とするリソースを提供するプールを探すのにあらゆる手段を尽くしますが、見つからなかった場合は移動できなくなります。
* 土地の販売: 土地が販売され、それぞれの住民 (売主または買主) の使用可能な URL の合計が変わり、現在使用中の URL 数が使用可能な数を上回った場合は、オブジェクトがいくつか返却されることになります。
** リターンされるオブジェクトは、同じカテゴリの中では URL を使用している新しいものから古いものの順で、カテゴリでは臨時、他人による所有、グループに設定、区画オーナーによる所有、選択済み／決定済みの順です。
**: オブジェクトがリターンされる可能性のある 唯一の タイミングは、土地の持ち主が変更になったときで、かつ使用可能なリソースを超過している場合のみです。
**: もっとも新しい臨時オブジェクトはそれよりも古い臨時オブジェクトよりも先に返却され、そのあとで、新しい「他人による所有」 (グループに設定されていなく、区画オーナーでもない) オブジェクトなどが返却されます。
== 他の制約 ==
* リクエストのボディ部のサイズは 2K バイト に 制限 されます。
* リクエストのヘッダ部のサイズは 255 バイトに制限されます。これはヘッダ 1 行あたりで、合計ではありません。
* リクエストに対するレスポンスのサイズは現在のところ制限はありませんが、テストの過程で見直しされます。
* 返却データのコンテンツ・タイプは常に「text/plain; charset=utf-8」です。
*: 将来的には他のコンテンツ・タイプが使用できるようになる可能性がありますが、保証はできません。
* スクリプトごとに 64 までは受信待ちのリクエストをためておけます。これは、LSL の保留イベントの最大数をもとにしています。64 リクエストの制限に達すると、シミュレータはサーバに蓋をして、受信したリクエストに対して「503 Service Unavailable」を返します。
* サーバに蓋がされている状態で受け入れるリクエスト数も調整される可能性があります。たぶんそうなりますが、まだ決定されていません。
* 外部パーサーを使用しない限り HTML は使用できません。全ての出力がテキストだからです。パーサーを作成する場合は、帯域が奪われないように、Linden Lab の HTML URL からのみのアクセスに制限しないといけなくなるのではないかということを心に留めておいておいてください。
* 重要なのは、クエリ文字列を URL の最後に付加する場合は、最後尾とクエリ文字列の '?' の間にスラッシュをつけなければならないということです。例えば、
https://sim123.agni.lindenlab.com/cap/f73b4b94-012d-44f2-bd0c-16c328321221?arg=gra は HTTP 500 エラーを返しますが、 https://sim123.agni.lindenlab.com/cap/f73b4b94-012d-44f2-bd0c-16c328321221/?arg=gra は成功します (正しくないように見えますが)
== リンク ==
* Script Examples
* Design Document
* Jira の設計書: