1. 序論
◎非規範的~web~appは、[ ~event/状態の更新/解析 ]を~serverへ報告するために,~HTTP要請を発行する必要があることが多い。 そのような要請には、 対する~HTTP応答を~client上で処理することは,概して要求されない (例: 応答の`状態s~code$【!~HTTP応答~code】は[ `204$st / `200$st ], `~message内容$は空)。 また、[ ~network資源/計算-資源 ]を他の高~優先度な演算 — ~criticalな資源を~fetchする, 入力に対し反応する, ~animationを稼働するなど — と競うべきでない。 しかしながら、 そのような片道な要請( ~beacon )には,~criticalな[ ~app/測定 ]~dataを送達する責務もあるので、 開発者は,送達を確保するために高価な~methodの利用を強いられている: ◎ Web applications often need to issue requests that report events, state updates, and analytics to one or more servers. Such requests typically do not require response processing on the client (e.g. result in 204, or 200 HTTP response codes with an empty response body), and should not compete for network and compute resources with other high priority operations such as fetching critical resources, reacting to input, running animations, and so on. However, such one-way requests (beacons), are also responsible for delivering critical application and measurement data, forcing developers to use costly methods to ensure their delivery:
- 開発者は、 送達~率を改善するために, 各~beaconを即時に送達することを選んでいる — それらの送達を[ 合体する/遅延する ]代わりに。 送達を遅延すると、 ~beacon要請を成功裡に完了するための時間が足りなくなり, 重要な~app~dataの喪失へ至らすこともある。 ◎ Developers opt for immediate delivery of each beacon, instead of coalescing and deferring their delivery because this provides improved delivery rates. Deferring delivery may mean that the beacon request may not have sufficient time to complete successfully, which leads to loss of important application data.
- 開発者が他を阻む( `blocking^en )要請の発行-法を選んでいる結果、 利用者~体験が害されている — ~UAによる時間厳守な演算 (例: `click^et, `unload^et, その他の~handler ) の実行ngを阻む技法 (同期的な `XMLHttpRequest$I を介する, 何もしない~loopを回す 【おそらく,`~UAを静止させる@~WAPI#pause$何か】 , その他) を利用して。 他を阻む挙動は、[ ~pageが~systemにより[ ~unload/休止-/~kill ]されても,~UA(または~OS)が要請を取消せない ]ようにして,送達~率を改善するために利用されている。 ◎ Developers opt for issuing blocking requests via synchronous XMLHttpRequest's, inserting no-op busy loops, or using other techniques that block the user agent from executing time-critical operations (e.g. click, unload, and other handlers) and hurt the user experience. The blocking behavior is used to provide improved delivery rate, as it prevents the user agent and the operating system from cancelling the request if the page is unloaded, suspended, or killed by the system.
上述のように,送達~要件と処理~要件に不一致があるため、 ほとんどの開発者たちは,蔓延している[ 利用者~体験を害するような,他を阻む技法 ]を渋々採用している。 この仕様は、 ~web開発者が[ そのような要請が処理され,宛先へ送達される ]ことを確保しながら[ 他の時間厳守な演算との資源~競合 ]も最小~化するような[ 非同期的かつ他を阻まない,~dataの送達 ]を~scheduleするために利用できる~interfaceを定義する: ◎ The mismatch between above delivery and processing requirements leaves most developers with a tough choice and widespread adoption of blocking techniques that hurt the user experience. This specification defines an interface that web developers can use to schedule asynchronous and non-blocking delivery of data that minimizes resource contention with other time-critical operations, while ensuring that such requests are still processed and delivered to destination:
- ~beacon要請は、[ 時間厳守な演算/高~優先度な~network要請 ]と競うことを避けるように優先度化される。 ◎ Beacon requests are prioritized to avoid competing with time-critical operations and higher priority network requests.
- ~UAは、 ~mobile機器~上の電力~利用を最適化するために,~beacon要請たちを効率的に合体することもできる。 ◎ Beacon requests may be efficiently coalesced by the user agent to optimize energy use on mobile devices.
- ~beacon要請は,~pageが~unloadされる前に起動されることが保証されるので、[ 他を阻む要請や,利用者~対話~eventの処理を阻むような他の技法 ]を要求することなく,完了まで走る( `run to completion^en )ことが許容される。 ◎ Beacon requests are guaranteed to be initiated before page is unloaded and are allowed to run to completion without requiring blocking requests or other techniques that block processing of user interactive events.
`sendBeacon()$m ~methodを利用して[ ~event, ~click, 解析 ]~dataを送達する例を示す: ◎ The following example shows use of the sendBeacon() method to deliver event, click, and analytics data:
<html> <script> /* ~client側の~eventを記録するために,他を阻まない~beaconを発する ◎ emit non-blocking beacon to record client-side event */ function reportEvent(%event) { var %data = JSON.stringify({ event: %event, time: performance.now() }); navigator.sendBeacon('/collector', %data); } /* ~pageが~background状態へ遷移する(`非可視になる@~HTMLinteraction#visibility-state$【!Page Visibility API】)に伴い,~session解析が伴われた他を阻まない~beaconを発する ◎ emit non-blocking beacon with session analytics as the page transitions to background state (Page Visibility API) */ document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'hidden') { var %sessionData = buildSessionReport(); navigator.sendBeacon('/collector', %sessionData); } }); </script> <body> <a href='http://www.w3.org/' onclick='reportEvent(this)'> <button onclick="reportEvent('some event')">Click me</button> </body> </html>
上の例は、 ~session~dataの送達を誘発するために, `PAGE-VISIBILITY-2$r に定義された 【が,今や `HTML$r にて`定義される@~HTMLinteraction#update-the-visibility-state$】 `visibilitychange$et ~eventを利用する。 ~mobile機器においては、 この~eventが,~pageが[ ~background状態へ遷移するとき (例:利用者が他の~appに切替えたとき, `homescreen^en へ戻ったとき, 等々)/ ~unloadされるとき ]に発火されることが保証される唯一の~eventである。 開発者は、 `unload^et ~eventに依拠するのは避けるべきである — それは,~pageが~background状態にあるとき (すなわち, `visibilityState$m は `hidden^l ) には発火されず、 ~mobile~OSにおいては,その処理nは終了されるので。 ◎ Above example uses visibilitychange event defined in [PAGE-VISIBILITY-2] to trigger delivery of session data. This event is the only event that is guaranteed to fire on mobile devices when the page transitions to background state (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded. Developers should avoid relying on unload event because it will not fire whenever a page is in a background state (i.e. visibilityState equal to hidden) and the process is terminated by the mobile OS.
`sendBeacon()$m ~methodを介して起動される要請は、 時間厳守な作業[ を阻む/と競う ]ことはない — ~UAは,~network効率を改善するように それを優先度化できるので、 ~beacon~dataの送達を確保するために他を阻む演算を利用する必要は排される。 ◎ The requests initiated via the sendBeacon() method do not block or compete with time-critical work, may be prioritized by the user agent to improve network efficiency, and eliminate the need to use blocking operations to ensure delivery of beacon data.
`sendBeacon()$m ~methodは、 次を意図するものではない: ◎ What sendBeacon() does not do and is not intended to solve:
- ~offlineな[ ~storage/送達 ]用の特別な取扱いを供するものではない。 ~beacon要請は,他の要請と同様であり、 ~offline機能性を供するために必要yな所では, `SERVICE-WORKERS$r と組合されてもよい。 ◎ The sendBeacon() method does not provide special handling for offline storage or delivery. A beacon request is like any other request and may be combined with [SERVICE-WORKERS] to provide offline functionality where necessary.
- ~backgroundな[ 同期法/転送~能力 ]を供するものではない。 ~beacon要請を素早くかつ適時に完了できることを確保するため、 ~UAは,受容する最大~payload~sizeを制約する。 ◎ The sendBeacon() method is not intended to provide background synchronization or transfer capabilities. The user agent restricts the maximum accepted payload size to ensure that beacon requests are able to complete quickly and in a timely manner.
- [ 要請~methodを~custom化する/ ~customな要請~headerを供する/ 要請や応答における他の`処理~prop@#sec-processing-model$を変更する ]ための能を供するものではない。 そのような要請~用に既定でない設定群を要求する~appは、 `FETCH$r ~APIを — 当の要請の`~keepaliveか$rqを ~T に設定して — 利用するべきである。 ◎ The sendBeacon() method does not provide ability to customize the request method, provide custom request headers, or change other processing properties of the request and response. Applications that require non-default settings for such requests should use the [FETCH] API with keep-alive flag set to true.
2. 適合性の要件
【 この節の内容は `~W3C日本語訳 共通~page@~W3Ccommon#conformance$に移譲 】
3. ~beacon
3.1. `sendBeacon()^m ~method
partial interface `Navigator$I { boolean `sendBeacon$m(`USVString$I %url, optional `BodyInit$I? %data = null); };
`sendBeacon(url, data)@m ~methodは、 次の規則に則って,[ %data 引数に供された~data ]を[ %url 引数に供された~URL ]へ向けて伝送する — ~UAは: ◎ The sendBeacon() method transmits data provided by the data parameter to the URL provided by the url parameter:
- ~beacon要請が素早くかつ適時に完了することを確保するため、 ~fetchを起動する際には, 当の要請の`~keepaliveか$rqを ~T に設定して, 要請が~queueできる %data 量を制約するモノトスル。 この量は、 `~HTTP~network-or-cache~fetch$にて定義される。 【具体的には、 64KiB】 ◎ The user agent MUST initiate a fetch with keepalive flag set, which restricts the amount of data that can be queued by such requests to ensure that beacon requests are able to complete quickly and in a timely manner.
- 文書の `visibilityState$m が `hidden^l へ遷移したときは、 すべての~beacon要請に対し,即時に伝送を~scheduleした上で、 そのような要請~すべてが他の[ 時間厳守な/高~優先度な ]作業を阻むことなく,完了まで走る( `run to completion^en )ことを許容するモノトスル。 ◎ The user agent MUST schedule immediate transmission of all beacon requests when the document visibilityState transitions to hidden, and must allow all such requests to run to completion without blocking other time-critical and high-priority work.
- 他の[ 時間厳守な/高~優先度な ]作業との(~CPUや~networkにおける)資源~競合を最小~化するよう, 供された~dataの伝送を~scheduleするベキである。 ◎ The user agent SHOULD schedule transmission of provided data to minimize resource (CPU and network) contention with other time-critical and high priority work.
- [ ~network/電力 ]効率を最適化するために,供された~dataの伝送を遅延してもヨイ — 例:~network~interfaceが作動中ならば即時に送達する, そうでなければ作動中になるまで待機するなど。 しかしながら、 伝送を不定期に遅延するベキでない — 他の~network活動がないときは、 処理待ちな伝送が定期的に消化されることを確保するベキである。 ◎ The user agent MAY delay transmission of provided data to optimize network and energy efficiency - e.g. deliver immediately if the network is active, or wait until network interface is active. However, the user agent SHOULD NOT delay transmission indefinitely and ensure that pending transmissions are periodically flushed even if there is no other network activity.
注記: `sendBeacon()^m ~APIは、 要請~callbackを供さない。 ~serverには、 そのような要請に対する応答の本体(`~message内容$)を省略することが奨励される (例: `204$st No Content で応答する)。 ◎ Note Beacon API does not provide a response callback. The server is encouraged to omit returning a response body for such requests (e.g. respond with 204 No Content).
`sendBeacon()$m ~methodは、[ ~UAが伝送d~dataを成功裡に~queueできたならば ~T / ~ELSE_ ~F ]を返す。 ◎ Parameters ◎ url ◎ The url parameter indicates the URL where the data is to be transmitted. data ◎ The data parameter is the BodyInit data that is to be transmitted. ◎ The sendBeacon() method returns true if the user agent is able to successfully queue the data for transfer. Otherwise it returns false.
注記: ~UAは、 この~APIを介して送信できる~data量に上限を課す: これは、 そのような要請を成功裡に送達しつつ,利用者や~browserによる他の活動への影響iを極力抑えることを確保し易くするためである。 ~queueされる~data量が`~UAによる上限$を超過することになる場合、 この~methodは ~F を返す。 返り値 ~T は、 ~browserが転送~用に~dataを~queueしたことを意味する。 しかしながら、 実際の~data転送は非同期的に行われる — この~methodは、 ~data転送が成功したか否かに関しては,何も情報を供さない。 ◎ Note The user agent imposes limits on the amount of data that can be sent via this API: this helps ensure that such requests are delivered successfully and with minimal impact on other user and browser activity. If the amount of data to be queued exceeds the user agent limit (as defined in HTTP-network-or-cache fetch), this method returns false; a return value of true implies the browser has queued the data for transfer. However, since the actual data transfer happens asynchronously, this method does not provide any information whether the data transfer has succeeded or not.
3.2. 処理~model
`sendBeacon(url, data)$m ~method手続きは: ◎ On calling the sendBeacon() method with url and optional data, the following steps must be run:
- %設定群 ~LET コレに`関連な設定群~obj$ ◎ ↓
- %基底~URL ~LET %設定群 の`~API用~基底~URL$enV ◎ Set base to this's relevant settings object's API base URL.
- %生成元 ~LET %設定群 の`生成元$ ◎ Set origin to this's relevant settings object's origin.
- %構文解析した~URL ~LET `~URL構文解析する$( %url , %基底~URL ) ◎ ↓
- ~IF[ %構文解析した~URL ~EQ `失敗^i ]~OR[ %構文解析した~URL の `~scheme$ ~NIN { `http^l, `https^l } ] ⇒ ~THROW `TypeError^E ◎ Set parsedUrl to the result of the URL parser steps with url and base. If the algorithm returns an error, or if parsedUrl's scheme is not "http" or "https", throw a "TypeError" exception and terminate these steps.
- %~header~list ~LET 空な`~header~list$ ◎ Let headerList be an empty list.
- %~CORS~mode ~LET `no-cors^l ◎ Let corsMode be "no-cors".
- ( %伝送d~data, %内容~型 ) ~LET ( ~NULL, ~NULL ) ◎ ↓
-
~IF[ %data ~NEQ ~NULL ]: ◎ If data is not null:
- ( %伝送d~data, %内容~型 ) ~SET `本体と型を抽出する$( %data, `~keepalive^i ) ◎ Set transmittedData and contentType to the result of extracting data's byte stream with the keepalive flag set.
-
~IF[ %伝送d~data の量は[ `~keepaliveか$rqが ~T をとる要請~用の`~UAによる上限$ ]を超過する ] ⇒ ~RET ~F ◎ If the amount of data that can be queued to be sent by keepalive enabled requests is exceeded by the size of transmittedData (as defined in HTTP-network-or-cache fetch), set the return value to false and terminate these steps.
注記: `sendBeacon()^m ~APIを介して起動された要請に対しては、 `~keepaliveか$rq は自動的に ~T に設定される。 類似に,開発者も、 ~Fetch~APIの利用-時に同じ~flagを手動で設定できる。 この~flagが ~T にされたすべての要請は、 ~Fetch~APIの中で施行される,同じ `in-flight^en な~quota制約を共有する。 【言い換えれば、上限は,これらの処理待ち要請たちの総~data量に課される。】 ◎ Note Requests initiated via the Beacon API automatically set the keepalive flag, and developers can similarly set the same flag manually when using the Fetch API. All requests with this flag set share the same in-flight quota restrictions that is enforced within the Fetch API.
-
~IF[ %内容~型 ~NEQ ~NULL ]: ◎ If contentType is not null:
- ~IF[ ( `Content-Type^bl, %内容~型 ) は`~CORS安全とされる要請~header$を成さない ] ⇒ %~CORS~mode ~SET `cors^l ◎ Set corsMode to "cors". ◎ If contentType value is a CORS-safelisted request-header value for the Content-Type header, set corsMode to "no-cors".
- %~header~list に`~headerを付加する$( ( `Content-Type^bl, %内容~型 ) ) ◎ Append a Content-Type header with value contentType to headerList.
-
この段は`並列的$に走らす: ◎ Set the return value to true, return the sendBeacon() call, and continue to run the following steps in parallel:
- %要請 ~LET 新たな`要請$ — その ⇒# `~method$rq ~SET `POST^M, `~client$rq ~SET %設定群, `~URL$rq ~SET %構文解析した~URL, `~header~list$rq ~SET %~header~list, `生成元$rq ~SET %生成元, `~keepaliveか$rq ~SET ~T, `本体$rq ~SET %伝送d~data, `~mode$rq ~SET %~CORS~mode, `資格証~mode$rq ~SET `include^l, `起動元~種別$rq ~SET `beacon^l ◎ Let req be a new request, initialized as follows: ◎ method • POST client • this's relevant settings object url • parsedUrl header list • headerList origin • origin keepalive • true body • transmittedData mode • corsMode credentials mode • include initiator type • "beacon"
- %要請 を`~fetchする$ ◎ Fetch req.
- ~RET ~T ◎ ↑
4. ~privacyと~security
`sendBeacon()^m は、 ~data送達~用の非同期的かつ他を阻まない仕組みを供する。 この~APIは、 次に利用できる: ◎ The sendBeacon() interface provides an asynchronous and non-blocking mechanism for delivery of data. This API can be used to:
- ~client側の~eventを~serverに報告する。 各~送達は、[ 他の対話的な作業を阻まない ]かつ[ ~system資源が効率的に利用される ]よう,~UAにより優先度化された上で~scheduleされる。 ◎ Report client-side events to the server. The delivery is prioritized and scheduled by the user agent such that it does not block other interactive work and makes efficient use of system resources.
- ~pageが[ ~background状態へ遷移する/~unloadされる ]ときに、 ~UAを阻むことなく,~session~dataを報告する。 ◎ Report session data when the page transitions to background state or is being unloaded, without blocking the user agent.
- [ 小さな~payloadの送達を要求するが,応答~callbackは期待しない ]ような,他の利用事例。 ◎ Other use cases that require delivery of small payloads and do not expect a response callback.
~serverへ送達される~dataは、 敏感になり得る情報を包含し得る — 例えば、 利用者の~web~page上での活動についての~dataなど。 これは,利用者の~privacyに対する含意を伴い得るが、 類似な能力を供する既存の~method — ~scriptによる~form提出-, 画像~beacon, XHR や~fetchによる要請など — も,その引き換えに様々かつ高価な処理能~costがついて来る。 そのような要請は、 開発者が[ ~UAによる他の~event処理 ]を阻まない限り (例:同期的な要請を呼出したり,何もしない~loopを回すなど), ~UAにより中止され得ることに加え、 ~UAは,[ そのような要請を優先度化する ]ことも[ それらを合体して~system資源の利用を最適化する ]こともできない。 ◎ The delivered data might contain potentially sensitive information, for example, data about a user's activity on a web page, to a server. While this can have privacy implications for the user, existing methods, such as scripted form-submit, image beacons, and XHR/fetch requests provide similar capabilities, but come with various and costly performance tradeoffs: the requests can be aborted by the user agent unless the developer blocks the user agent from processing other events (e.g. by invoking a synchronous request, or spinning in an empty loop), and the user agent is unable to prioritize and coalesce such requests to optimize use of system resources.
`sendBeacon()^m により起動される`要請$は、 次に挙げる~propertyの~subjectになる: ◎ A request initiated by sendBeacon() is subject to following properties:
- 要請は[ ~payloadを包含していない/ `Content-Type$h ~headerを伴っていて,それは`~CORS安全とされる要請~header$である ]場合、 要請の`~mode$rqは `no-cors^l になる — [ ~scriptによる~form提出-【!post】/ XHR や~fetchによる要請 ]と類似に。 ◎ If the request does not contain a payload, or the request Content-Type is a CORS-safelisted request-header, then the request mode is `no-cors`—similar to an image beacon or form-post respectively.
- 他の場合、 `~CORS予行~要請$が為される。 そのような要請に対しては、 ~serverは,先ず[ 次に挙げる適切な一式の~CORS~headerを返すことにより,それを許容する ]必要がある ⇒# `Access-Control-Allow-Credentials$h, `Access-Control-Allow-Origin$h, `Access-Control-Allow-Headers$h ◎ Otherwise, a CORS preflight is made and the server needs to first allow such requests by returning the appropriate set of CORS headers: Access-Control-Allow-Credentials, Access-Control-Allow-Origin, Access-Control-Allow-Headers.
そのようなわけで,~securityの観点からは、 `sendBeacon()^m ~APIを~subjectにする~security用の施策は, 開発者たちが利用-中にある現在の手法に対するそれと同じになる。 類似に,~privacyの観点からも、 結果の要請は[ ~APIが~callされる/ ~pageの可視性が変化する ]と同時に即時に起動され、 公開される情報(例: 利用者の~IP~address)を開発者から~access可能な既存の `lifecycle^en ~eventに制約する。 しかしながら,~UAは、 利用者に透明性を供するためとして, そのような要請を表面化するための代替な手法を考慮するかもしれない。 ◎ As such, from the security perspective, the Beacon API is subject to same security policies as the current methods in use by developers. Similarly, from the privacy perspective, the resulting requests are initiated immediately when the API is called, or upon a page visibility change, which restricts the exposed information (e.g. user's IP address) to existing lifecycle events accessible to the developers. However, user agents might consider alternative methods to surface such requests to provide transparency to users.
`sendBeacon()^m ~APIには、 上述した代替と比較して, 2 つの制約 — ~callback~methodは無いこと, ~UAは~payload~sizeを制約できること — が適用されるが、 その他に追加的な制約はない。 ~UAは、 `sendBeacon()^m ~callの処理を間引くべきでない — それらは~criticalな[ ~app状態/~event/解析~data ]を包含し得るので。 類似に,~UAは、 “私的~閲覧” に等価な~mode下にあるときは、[ ~appが非互換化される/ 利用者がそのような~mode下にあることが漏洩される ]のを避けるため, `sendBeacon()^m を不能化するべき( `ought^en )でない。 ◎ Compared to the alternatives, the sendBeacon() API does apply two restrictions: there is no callback method, and the payload size can be restricted by the user agent. Otherwise, the sendBeacon() API is not subject to any additional restrictions. The user agent ought not skip or throttle processing of sendBeacon() calls, as they can contain critical application state, events, and analytics data. Similarly, the user agent ought not disable sendBeacon() when in "private browsing" or equivalent mode, both to avoid breaking the application and to avoid leaking that the user is in such mode.
謝辞
この作業に貢献された次の方々に:
Thanks to Alois Reitbauer, Arvind Jain, Anne van Kesteren, Boris Zbarsky, Chase Douglas, Daniel Austin, Jatinder Mann, James Simonsen, Jason Weber, Jonas Sicking, Nick Doty, Philippe Le Hegaret, Todd Reifsteck, Tony Gentilcore, William Chan, and Yoav Weiss for their contributions to this work.