├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── 0-new-issue.yml │ ├── 1-new-feature.yml │ └── config.yml └── workflows │ └── build.yml ├── .gitignore ├── .pr-preview.json ├── LICENSE ├── Makefile ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── index.bs └── review-drafts ├── 2022-03.bs ├── 2022-09.bs └── 2023-09.bs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_size = 2 8 | indent_style = space 9 | trim_trailing_whitespace = true 10 | max_line_length = 100 11 | 12 | [Makefile] 13 | indent_style = tab 14 | 15 | [*.md] 16 | max_line_length = off 17 | 18 | [*.bs] 19 | indent_size = 1 20 | 21 | [*.py] 22 | indent_size = 4 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.bs diff=html linguist-language=HTML 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/0-new-issue.yml: -------------------------------------------------------------------------------- 1 | name: New issue 2 | description: File a new issue against the WebSockets Standard. 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: | 7 | Before filling out this form, please familiarize yourself with the [Code of Conduct](https://whatwg.org/code-of-conduct). You might also find the [FAQ](https://whatwg.org/faq) and [Working Mode](https://whatwg.org/working-mode) useful. 8 | 9 | If at any point you have questions, please reach out to us on [Chat](https://whatwg.org/chat). 10 | - type: textarea 11 | attributes: 12 | label: "What is the issue with the WebSockets Standard?" 13 | validations: 14 | required: true 15 | - type: markdown 16 | attributes: 17 | value: "Thank you for taking the time to improve the WebSockets Standard!" 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-new-feature.yml: -------------------------------------------------------------------------------- 1 | name: New feature 2 | description: Request a new feature in the WebSockets Standard. 3 | labels: ["addition/proposal", "needs implementer interest"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Before filling out this form, please familiarize yourself with the [Code of Conduct](https://whatwg.org/code-of-conduct), [FAQ](https://whatwg.org/faq), and [Working Mode](https://whatwg.org/working-mode). They help with setting expectations and making sure you know what is required. The FAQ ["How should I go about proposing new features to WHATWG standards?"](https://whatwg.org/faq#adding-new-features) is especially relevant. 9 | 10 | If at any point you have questions, please reach out to us on [Chat](https://whatwg.org/chat). 11 | - type: textarea 12 | attributes: 13 | label: "What problem are you trying to solve?" 14 | validations: 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: "What solutions exist today?" 19 | - type: textarea 20 | attributes: 21 | label: "How would you solve it?" 22 | - type: textarea 23 | attributes: 24 | label: "Anything else?" 25 | - type: markdown 26 | attributes: 27 | value: "Thank you for taking the time to improve the WebSockets Standard!" 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Chat 4 | url: https://whatwg.org/chat 5 | about: Please do reach out with questions and feedback! 6 | - name: Stack Overflow 7 | url: https://stackoverflow.com/ 8 | about: If you're having trouble building a web page, this is not the right repository. Consider asking your question on Stack Overflow instead. 9 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - main 10 | workflow_dispatch: 11 | 12 | jobs: 13 | build: 14 | name: Build 15 | runs-on: ubuntu-22.04 16 | steps: 17 | - uses: actions/checkout@v3 18 | with: 19 | fetch-depth: 2 20 | - uses: actions/setup-python@v4 21 | with: 22 | python-version: "3.11" 23 | - run: pip install bikeshed && bikeshed update 24 | # Note: `make deploy` will do a deploy dry run on PRs. 25 | - run: make deploy 26 | env: 27 | SERVER: ${{ secrets.MARQUEE_SERVER }} 28 | SERVER_PUBLIC_KEY: ${{ secrets.MARQUEE_PUBLIC_KEY }} 29 | SERVER_DEPLOY_KEY: ${{ secrets.MARQUEE_DEPLOY_KEY }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /websockets.spec.whatwg.org/ 2 | /deploy.sh 3 | /index.html 4 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1, 6 | "md-status": "LS-PR", 7 | "md-Text-Macro": "PR-NUMBER {{ pull_request.number }}" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). 2 | 3 | This work is licensed under a Creative Commons Attribution 4.0 International 4 | License. To the extent portions of it are incorporated into source code, 5 | such portions in the source code are licensed under the BSD 3-Clause License instead. 6 | 7 | - - - - 8 | 9 | Creative Commons Attribution 4.0 International Public License 10 | 11 | By exercising the Licensed Rights (defined below), You accept and agree 12 | to be bound by the terms and conditions of this Creative Commons 13 | Attribution 4.0 International Public License ("Public License"). To the 14 | extent this Public License may be interpreted as a contract, You are 15 | granted the Licensed Rights in consideration of Your acceptance of 16 | these terms and conditions, and the Licensor grants You such rights in 17 | consideration of benefits the Licensor receives from making the 18 | Licensed Material available under these terms and conditions. 19 | 20 | 21 | Section 1 -- Definitions. 22 | 23 | a. Adapted Material means material subject to Copyright and Similar 24 | Rights that is derived from or based upon the Licensed Material 25 | and in which the Licensed Material is translated, altered, 26 | arranged, transformed, or otherwise modified in a manner requiring 27 | permission under the Copyright and Similar Rights held by the 28 | Licensor. For purposes of this Public License, where the Licensed 29 | Material is a musical work, performance, or sound recording, 30 | Adapted Material is always produced where the Licensed Material is 31 | synched in timed relation with a moving image. 32 | 33 | b. Adapter's License means the license You apply to Your Copyright 34 | and Similar Rights in Your contributions to Adapted Material in 35 | accordance with the terms and conditions of this Public License. 36 | 37 | c. Copyright and Similar Rights means copyright and/or similar rights 38 | closely related to copyright including, without limitation, 39 | performance, broadcast, sound recording, and Sui Generis Database 40 | Rights, without regard to how the rights are labeled or 41 | categorized. For purposes of this Public License, the rights 42 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 43 | Rights. 44 | 45 | d. Effective Technological Measures means those measures that, in the 46 | absence of proper authority, may not be circumvented under laws 47 | fulfilling obligations under Article 11 of the WIPO Copyright 48 | Treaty adopted on December 20, 1996, and/or similar international 49 | agreements. 50 | 51 | e. Exceptions and Limitations means fair use, fair dealing, and/or 52 | any other exception or limitation to Copyright and Similar Rights 53 | that applies to Your use of the Licensed Material. 54 | 55 | f. Licensed Material means the artistic or literary work, database, 56 | or other material to which the Licensor applied this Public 57 | License. 58 | 59 | g. Licensed Rights means the rights granted to You subject to the 60 | terms and conditions of this Public License, which are limited to 61 | all Copyright and Similar Rights that apply to Your use of the 62 | Licensed Material and that the Licensor has authority to license. 63 | 64 | h. Licensor means the individual(s) or entity(ies) granting rights 65 | under this Public License. 66 | 67 | i. Share means to provide material to the public by any means or 68 | process that requires permission under the Licensed Rights, such 69 | as reproduction, public display, public performance, distribution, 70 | dissemination, communication, or importation, and to make material 71 | available to the public including in ways that members of the 72 | public may access the material from a place and at a time 73 | individually chosen by them. 74 | 75 | j. Sui Generis Database Rights means rights other than copyright 76 | resulting from Directive 96/9/EC of the European Parliament and of 77 | the Council of 11 March 1996 on the legal protection of databases, 78 | as amended and/or succeeded, as well as other essentially 79 | equivalent rights anywhere in the world. 80 | 81 | k. You means the individual or entity exercising the Licensed Rights 82 | under this Public License. Your has a corresponding meaning. 83 | 84 | 85 | Section 2 -- Scope. 86 | 87 | a. License grant. 88 | 89 | 1. Subject to the terms and conditions of this Public License, 90 | the Licensor hereby grants You a worldwide, royalty-free, 91 | non-sublicensable, non-exclusive, irrevocable license to 92 | exercise the Licensed Rights in the Licensed Material to: 93 | 94 | a. reproduce and Share the Licensed Material, in whole or 95 | in part; and 96 | 97 | b. produce, reproduce, and Share Adapted Material. 98 | 99 | 2. Exceptions and Limitations. For the avoidance of doubt, where 100 | Exceptions and Limitations apply to Your use, this Public 101 | License does not apply, and You do not need to comply with 102 | its terms and conditions. 103 | 104 | 3. Term. The term of this Public License is specified in Section 105 | 6(a). 106 | 107 | 4. Media and formats; technical modifications allowed. The 108 | Licensor authorizes You to exercise the Licensed Rights in 109 | all media and formats whether now known or hereafter created, 110 | and to make technical modifications necessary to do so. The 111 | Licensor waives and/or agrees not to assert any right or 112 | authority to forbid You from making technical modifications 113 | necessary to exercise the Licensed Rights, including 114 | technical modifications necessary to circumvent Effective 115 | Technological Measures. For purposes of this Public License, 116 | simply making modifications authorized by this Section 2(a) 117 | (4) never produces Adapted Material. 118 | 119 | 5. Downstream recipients. 120 | 121 | a. Offer from the Licensor -- Licensed Material. Every 122 | recipient of the Licensed Material automatically 123 | receives an offer from the Licensor to exercise the 124 | Licensed Rights under the terms and conditions of this 125 | Public License. 126 | 127 | b. No downstream restrictions. You may not offer or impose 128 | any additional or different terms or conditions on, or 129 | apply any Effective Technological Measures to, the 130 | Licensed Material if doing so restricts exercise of the 131 | Licensed Rights by any recipient of the Licensed 132 | Material. 133 | 134 | 6. No endorsement. Nothing in this Public License constitutes or 135 | may be construed as permission to assert or imply that You 136 | are, or that Your use of the Licensed Material is, connected 137 | with, or sponsored, endorsed, or granted official status by, 138 | the Licensor or others designated to receive attribution as 139 | provided in Section 3(a)(1)(A)(i). 140 | 141 | b. Other rights. 142 | 143 | 1. Moral rights, such as the right of integrity, are not 144 | licensed under this Public License, nor are publicity, 145 | privacy, and/or other similar personality rights; however, to 146 | the extent possible, the Licensor waives and/or agrees not to 147 | assert any such rights held by the Licensor to the limited 148 | extent necessary to allow You to exercise the Licensed 149 | Rights, but not otherwise. 150 | 151 | 2. Patent and trademark rights are not licensed under this 152 | Public License. 153 | 154 | 3. To the extent possible, the Licensor waives any right to 155 | collect royalties from You for the exercise of the Licensed 156 | Rights, whether directly or through a collecting society 157 | under any voluntary or waivable statutory or compulsory 158 | licensing scheme. In all other cases the Licensor expressly 159 | reserves any right to collect such royalties. 160 | 161 | 162 | Section 3 -- License Conditions. 163 | 164 | Your exercise of the Licensed Rights is expressly made subject to the 165 | following conditions. 166 | 167 | a. Attribution. 168 | 169 | 1. If You Share the Licensed Material (including in modified 170 | form), You must: 171 | 172 | a. retain the following if it is supplied by the Licensor 173 | with the Licensed Material: 174 | 175 | i. identification of the creator(s) of the Licensed 176 | Material and any others designated to receive 177 | attribution, in any reasonable manner requested by 178 | the Licensor (including by pseudonym if 179 | designated); 180 | 181 | ii. a copyright notice; 182 | 183 | iii. a notice that refers to this Public License; 184 | 185 | iv. a notice that refers to the disclaimer of 186 | warranties; 187 | 188 | v. a URI or hyperlink to the Licensed Material to the 189 | extent reasonably practicable; 190 | 191 | b. indicate if You modified the Licensed Material and 192 | retain an indication of any previous modifications; and 193 | 194 | c. indicate the Licensed Material is licensed under this 195 | Public License, and include the text of, or the URI or 196 | hyperlink to, this Public License. 197 | 198 | 2. You may satisfy the conditions in Section 3(a)(1) in any 199 | reasonable manner based on the medium, means, and context in 200 | which You Share the Licensed Material. For example, it may be 201 | reasonable to satisfy the conditions by providing a URI or 202 | hyperlink to a resource that includes the required 203 | information. 204 | 205 | 3. If requested by the Licensor, You must remove any of the 206 | information required by Section 3(a)(1)(A) to the extent 207 | reasonably practicable. 208 | 209 | 4. If You Share Adapted Material You produce, the Adapter's 210 | License You apply must not prevent recipients of the Adapted 211 | Material from complying with this Public License. 212 | 213 | 214 | Section 4 -- Sui Generis Database Rights. 215 | 216 | Where the Licensed Rights include Sui Generis Database Rights that 217 | apply to Your use of the Licensed Material: 218 | 219 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 220 | to extract, reuse, reproduce, and Share all or a substantial 221 | portion of the contents of the database; 222 | 223 | b. if You include all or a substantial portion of the database 224 | contents in a database in which You have Sui Generis Database 225 | Rights, then the database in which You have Sui Generis Database 226 | Rights (but not its individual contents) is Adapted Material; and 227 | 228 | c. You must comply with the conditions in Section 3(a) if You Share 229 | all or a substantial portion of the contents of the database. 230 | 231 | For the avoidance of doubt, this Section 4 supplements and does not 232 | replace Your obligations under this Public License where the Licensed 233 | Rights include other Copyright and Similar Rights. 234 | 235 | 236 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 237 | 238 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 239 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 240 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 241 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 242 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 243 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 244 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 245 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 246 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 247 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 248 | 249 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 250 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 251 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 252 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 253 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 254 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 255 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 256 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 257 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 258 | 259 | c. The disclaimer of warranties and limitation of liability provided 260 | above shall be interpreted in a manner that, to the extent 261 | possible, most closely approximates an absolute disclaimer and 262 | waiver of all liability. 263 | 264 | 265 | Section 6 -- Term and Termination. 266 | 267 | a. This Public License applies for the term of the Copyright and 268 | Similar Rights licensed here. However, if You fail to comply with 269 | this Public License, then Your rights under this Public License 270 | terminate automatically. 271 | 272 | b. Where Your right to use the Licensed Material has terminated under 273 | Section 6(a), it reinstates: 274 | 275 | 1. automatically as of the date the violation is cured, provided 276 | it is cured within 30 days of Your discovery of the 277 | violation; or 278 | 279 | 2. upon express reinstatement by the Licensor. 280 | 281 | For the avoidance of doubt, this Section 6(b) does not affect any 282 | right the Licensor may have to seek remedies for Your violations 283 | of this Public License. 284 | 285 | c. For the avoidance of doubt, the Licensor may also offer the 286 | Licensed Material under separate terms or conditions or stop 287 | distributing the Licensed Material at any time; however, doing so 288 | will not terminate this Public License. 289 | 290 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 291 | License. 292 | 293 | 294 | Section 7 -- Other Terms and Conditions. 295 | 296 | a. The Licensor shall not be bound by any additional or different 297 | terms or conditions communicated by You unless expressly agreed. 298 | 299 | b. Any arrangements, understandings, or agreements regarding the 300 | Licensed Material not stated herein are separate from and 301 | independent of the terms and conditions of this Public License. 302 | 303 | 304 | Section 8 -- Interpretation. 305 | 306 | a. For the avoidance of doubt, this Public License does not, and 307 | shall not be interpreted to, reduce, limit, restrict, or impose 308 | conditions on any use of the Licensed Material that could lawfully 309 | be made without permission under this Public License. 310 | 311 | b. To the extent possible, if any provision of this Public License is 312 | deemed unenforceable, it shall be automatically reformed to the 313 | minimum extent necessary to make it enforceable. If the provision 314 | cannot be reformed, it shall be severed from this Public License 315 | without affecting the enforceability of the remaining terms and 316 | conditions. 317 | 318 | c. No term or condition of this Public License will be waived and no 319 | failure to comply consented to unless expressly agreed to by the 320 | Licensor. 321 | 322 | d. Nothing in this Public License constitutes or may be interpreted 323 | as a limitation upon, or waiver of, any privileges and immunities 324 | that apply to the Licensor or You, including from the legal 325 | processes of any jurisdiction or authority. 326 | 327 | - - - - 328 | 329 | BSD 3-Clause License 330 | 331 | Redistribution and use in source and binary forms, with or without 332 | modification, are permitted provided that the following conditions are met: 333 | 334 | 1. Redistributions of source code must retain the above copyright notice, this 335 | list of conditions and the following disclaimer. 336 | 337 | 2. Redistributions in binary form must reproduce the above copyright notice, 338 | this list of conditions and the following disclaimer in the documentation 339 | and/or other materials provided with the distribution. 340 | 341 | 3. Neither the name of the copyright holder nor the names of its 342 | contributors may be used to endorse or promote products derived from 343 | this software without specific prior written permission. 344 | 345 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 346 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 347 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 348 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 349 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 350 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 351 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 352 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 353 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 354 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 355 | 356 | - - - - 357 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash -o pipefail 2 | .PHONY: local remote deploy 3 | 4 | remote: index.bs 5 | @ (HTTP_STATUS=$$(curl https://api.csswg.org/bikeshed/ \ 6 | --output index.html \ 7 | --write-out "%{http_code}" \ 8 | --header "Accept: text/plain, text/html" \ 9 | -F die-on=warning \ 10 | -F md-Text-Macro="COMMIT-SHA LOCAL COPY" \ 11 | -F file=@index.bs) && \ 12 | [[ "$$HTTP_STATUS" -eq "200" ]]) || ( \ 13 | echo ""; cat index.html; echo ""; \ 14 | rm -f index.html; \ 15 | exit 22 \ 16 | ); 17 | 18 | local: index.bs 19 | bikeshed spec index.bs index.html --md-Text-Macro="COMMIT-SHA LOCAL-COPY" 20 | 21 | deploy: index.bs 22 | curl --remote-name --fail https://resources.whatwg.org/build/deploy.sh 23 | bash ./deploy.sh 24 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | - [ ] At least two implementers are interested (and none opposed): 8 | * … 9 | * … 10 | - [ ] [Tests](https://github.com/web-platform-tests/wpt) are written and can be reviewed and commented upon at: 11 | * … 12 | - [ ] [Implementation bugs](https://github.com/whatwg/meta/blob/main/MAINTAINERS.md#handling-pull-requests) are filed: 13 | * Chromium: … 14 | * Gecko: … 15 | * WebKit: … 16 | * Deno: … 17 | - [ ] [MDN issue](https://github.com/whatwg/meta/blob/main/MAINTAINERS.md#handling-pull-requests) is filed: … 18 | - [ ] The top of this comment includes a [clear commit message](https://github.com/whatwg/meta/blob/main/COMMITTING.md) to use. 19 | 20 | (See [WHATWG Working Mode: Changes](https://whatwg.org/working-mode#changes) for more details.) 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository hosts the [WebSockets Standard](https://websockets.spec.whatwg.org/). 2 | 3 | ## Code of conduct 4 | 5 | We are committed to providing a friendly, safe, and welcoming environment for all. Please read and respect the [Code of Conduct](https://whatwg.org/code-of-conduct). 6 | 7 | ## Contribution opportunities 8 | 9 | Folks notice minor and larger issues with the WebSockets Standard all the time and we'd love your help fixing those. Pull requests for typographical and grammar errors are also most welcome. 10 | 11 | Issues labeled ["good first issue"](https://github.com/whatwg/websockets/labels/good%20first%20issue) are a good place to get a taste for editing the WebSockets Standard. Note that we don't assign issues and there's no reason to ask for availability either, just provide a pull request. 12 | 13 | If you are thinking of suggesting a new feature, read through the [FAQ](https://whatwg.org/faq) and [Working Mode](https://whatwg.org/working-mode) documents to get yourself familiarized with the process. 14 | 15 | We'd be happy to help you with all of this [on Chat](https://whatwg.org/chat). 16 | 17 | ## Pull requests 18 | 19 | In short, change `index.bs` and submit your patch, with a [good commit message](https://github.com/whatwg/meta/blob/main/COMMITTING.md). 20 | 21 | Please add your name to the Acknowledgments section in your first pull request, even for trivial fixes. The names are sorted lexicographically. 22 | 23 | To ensure your patch meets all the necessary requirements, please also see the [Contributor Guidelines](https://github.com/whatwg/meta/blob/main/CONTRIBUTING.md). Editors of the WebSockets Standard are expected to follow the [Maintainer Guidelines](https://github.com/whatwg/meta/blob/main/MAINTAINERS.md). 24 | 25 | ## Tests 26 | 27 | Tests are an essential part of the standardization process and will need to be created or adjusted as changes to the standard are made. Tests for the WebSockets Standard can be found in the `websockets/` directory of [`web-platform-tests/wpt`](https://github.com/web-platform-tests/wpt). 28 | 29 | A dashboard showing the tests running against browser engines can be seen at [wpt.fyi/results/websockets](https://wpt.fyi/results/websockets). 30 | 31 | ## Building "locally" 32 | 33 | For quick local iteration, run `make`; this will use a web service to build the standard, so that you don't have to install anything. See more in the [Contributor Guidelines](https://github.com/whatwg/meta/blob/main/CONTRIBUTING.md#building). 34 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 |
2 | Group: WHATWG 3 | H1: WebSockets 4 | Shortname: websockets 5 | Text Macro: TWITTER whatsockets 6 | Text Macro: LATESTRD 2023-09 7 | Abstract: This specification provides APIs to enable web applications to maintain bidirectional 8 | Abstract: communications with server-side processes. 9 | Translation: ja https://triple-underscore.github.io/WebSocket-ja.html 10 | Indent: 1 11 | Markup Shorthands: markdown yes 12 |13 | 14 |
15 | { 16 | "WSP": { 17 | "aliasOf": "RFC6455" 18 | }, 19 | "HSTS": { 20 | "aliasOf": "RFC6797" 21 | } 22 | } 23 |24 | 25 |
26 | spec:url; type:interface; 27 | text:URL 28 | spec:url; type:dfn; 29 | text:fragment 30 | text:scheme 31 | spec:html; type:dfn; 32 | text:task queues 33 | for:/; text:event loop 34 | spec:url; type:dfn; 35 | text:origin 36 | for:/; text:url 37 |38 | 39 |
40 | spec:RFC6455; urlPrefix: https://datatracker.ietf.org/doc/html/rfc6455 41 | type: dfn 42 | text:the WebSocket connection is established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 43 | text:extensions in use; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 44 | text:subprotocol in use; url:page-19:~:text=_Subprotocol%20In,Use_ 45 | text:a WebSocket message has been received; url:page-66:~:text=_A%20WebSocket%20Message%20Has%20Been%20Received_ 46 | text:send a WebSocket Message; url:page-66:~:text=needs%20to-,_Send%20a%20WebSocket%20Message_ 47 | text:fail the WebSocket connection; url:section-7.1.7 48 | text:close the WebSocket connection; url:section-7.1.1 49 | text:start the WebSocket closing handshake; url:section-7.1.2 50 | text:the WebSocket closing handshake is started; url:section-7.1.3 51 | text:the WebSocket connection is closed; url:section-7.1.4 52 | text:the WebSocket connection close code; url:section-7.1.5 53 | text:the WebSocket connection close reason; url:section-7.1.6 54 | text:established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 55 | text:ws; url:section-11.1.1 56 | text:wss; url:section-11.1.2 57 | text:cleanly; url:page-41:~:text=closed-,_cleanly_. 58 | type: http-header; text:Sec-WebSocket-Protocol; url:section-11.3.4 59 | spec:html; type:dfn; urlPrefix: https://html.spec.whatwg.org/multipage/webappapis.html 60 | for:event loop; text:step 1; url:step1 61 |62 | 63 | 64 | # Introduction # {#network-intro} 65 | 66 |
This interface does not allow for raw access to the underlying network. For 74 | example, this interface could not be used to implement an IRC client without proxying messages 75 | through a custom server.
76 |Although structured a little differently, carrying different properties, and 118 | therefore not shareable, a WebSocket connection is very close to identical to an "ordinary" 119 | [=connection=]. 120 | 121 |
This change of scheme is essential to integrate well with 135 | fetching. E.g., HSTS would not work without it. There is no real 136 | reason for WebSocket to have distinct schemes, it's a legacy artefact. 137 | [[!HSTS]] 138 | 139 | 1. Let |request| be a new request, whose URL is |requestURL|, 140 | client is |client|, [=service-workers mode=] is "`none`", 141 | referrer is "`no-referrer`", mode is "`websocket`", 142 | credentials mode is "`include`", cache mode is "`no-store`" 143 | , and redirect mode is "`error`". 144 | 145 | 1. Append (\``Upgrade`\`, \``websocket`\`) to |request|'s 146 | header list. 147 | 1. Append (\``Connection`\`, \``Upgrade`\`) to |request|'s 148 | header list. 149 | 1. Let |keyValue| be a nonce consisting of a randomly selected 16-byte value that has been 150 | forgiving-base64-encoded and [=isomorphic encoded=]. 151 | 152 |
If the randomly selected value was the byte sequence 0x01 153 | 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, |keyValue| would be 154 | forgiving-base64-encoded to "`AQIDBAUGBwgJCgsMDQ4PEC==`" and isomorphic encoded to 155 | \``AQIDBAUGBwgJCgsMDQ4PEC==`\`. 156 | 157 | 1. Append (\``Sec-WebSocket-Key`\`, |keyValue|) to |request|'s 158 | header list. 159 | 1. Append (\``Sec-WebSocket-Version`\`, \``13`\`) to |request|'s 160 | header list. 161 | 1. For each |protocol| in |protocols|, combine 162 | (\``Sec-WebSocket-Protocol`\`, |protocol|) in |request|'s header list. 163 | 164 | 1. Let |permessageDeflate| be a user-agent defined "`permessage-deflate`" extension 165 | header value. [[!WSP]] 166 | 167 |
\``permessage-deflate; client_max_window_bits`\` 168 | 169 | 1. Append (\``Sec-WebSocket-Extensions`\`, |permessageDeflate|) to 170 | |request|'s header list. 171 | 1. Fetch |request| with useParallelQueue set to true, 172 | and processResponse given |response| being these steps: 173 | 1. If |response| is a [=network error=] or its status is not 101, [=fail the 174 | WebSocket connection=]. 175 | 1. If |protocols| is not the empty list and [=extracting header list values=] given 176 | \``Sec-WebSocket-Protocol`\` and |response|'s header list 177 | results in null, failure, or the empty byte sequence, then [=fail the WebSocket connection=]. 178 | 179 |
This is different from the check on this header defined by The WebSocket Protocol. 180 | That only covers a subprotocol not requested by the client. This covers a subprotocol requested 181 | by the client, but not acknowledged by the server. 182 | 183 | 1. Follow the requirements stated step 2 to step 6, inclusive, of the last set of steps in 184 | section 4.1 of The WebSocket 185 | Protocol to validate |response|. This either results in [=fail the WebSocket connection=] 186 | or [=the WebSocket connection is established=]. 187 | 188 |
The reason redirects are not followed and this handshake is generally restricted is 194 | because it could introduce serious security problems in a web browser context. For example, consider 195 | a host with a WebSocket server at one path and an open HTTP redirector at another. Suddenly, any 196 | script that can be given a particular WebSocket URL can be tricked into communicating to (and 197 | potentially sharing secrets with) any host on the internet, even if the script checks that the URL 198 | has the right hostname. 199 | 200 | 201 | 202 | # The {{WebSocket}} interface # {#the-websocket-interface} 203 | ## Interface definition ## {#interface-definition} 204 | 205 | The Web IDL definition for the {{WebSocket}} class is given as follows: 206 | 207 |
|socket| = new {{WebSocket/constructor(url, protocols)|WebSocket}}(|url| [, |protocols| ])
260 | :: Creates a new {{WebSocket}} object, immediately establishing the associated WebSocket
261 | connection.
262 |
263 | |url| is a string giving the URL over which the connection is established.
264 | Only "`ws`", "`wss`", "`http`", and "`https`" schemes are allowed; others will cause a
265 | "{{SyntaxError}}" {{DOMException}}. URLs with [=fragments=] will always cause such an exception.
266 |
267 | |protocols| is either a string or an array of strings. If it is a string, it is equivalent to
268 | an array consisting of just that string; if it is omitted, it is equivalent to the empty array.
269 | Each string in the array is a subprotocol name. The connection will only be established if the
270 | server reports that it has selected one of these subprotocols. The subprotocol names have to
271 | match the requirements for elements that comprise the value of \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol.
273 | [[!WSP]]
274 |
275 | : |socket|.send(|data|)
276 | :: Transmits |data| using the WebSocket connection. |data| can be a string, a {{Blob}}, an
277 | {{ArrayBuffer}}, or an {{ArrayBufferView}}.
278 |
279 | : |socket|.close([ |code| ] [, |reason| ])
280 | :: Closes the WebSocket connection, optionally using |code| as [=the WebSocket connection
281 | close code=] and |reason| as [=the WebSocket connection close reason=].
282 |
283 | : |socket|.url
284 | :: Returns the URL that was used to establish the WebSocket connection.
285 |
286 | : |socket|.readyState
287 | :: Returns the state of the WebSocket connection. It can have the values described above.
288 |
289 | : |socket|.bufferedAmount
290 | :: Returns the number of bytes of application data (UTF-8 text and binary data) that have been
291 | queued using {{WebSocket/send()}} but not yet been transmitted to the network.
292 |
293 | If the WebSocket connection is closed, this attribute's value will only increase with each call
294 | to the {{WebSocket/send()}} method. (The number does not reset to zero once the connection
295 | closes.)
296 |
297 | : |socket|.extensions
298 | :: Returns the extensions selected by the server, if any.
299 |
300 | : |socket|.protocol
301 | :: Returns the subprotocol selected by the server, if any. It can be used in conjunction with the
302 | array form of the constructor's second argument to perform subprotocol negotiation.
303 |
304 | : |socket|.binaryType
305 | :: Returns a string that indicates how binary data from |socket| is exposed to scripts:
306 |
307 | : "{{BinaryType/blob}}"
308 | :: Binary data is returned in {{Blob}} form.
309 | : "{{BinaryType/arraybuffer}}"
310 | :: Binary data is returned in {{ArrayBuffer}} form.
311 |
312 | The default is "{{BinaryType/blob}}".
313 |
314 | : |socket|.binaryType = value
315 | :: Changes how binary data is returned.
316 | new
320 | WebSocket(|url|, |protocols|)
321 | constructor steps are:
322 |
323 | 1. Let |baseURL| be [=this=]'s [=relevant settings object=]'s [=API base URL=].
324 | 1. Let |urlRecord| be the result of applying the [=URL parser=] to |url| with |baseURL|.
325 | 1. If |urlRecord| is failure, then throw a "{{SyntaxError}}" {{DOMException}}.
326 | 1. If |urlRecord|'s [=url/scheme=] is "`http`", then set |urlRecord|'s [=url/scheme=] to "`ws`".
327 | 1. Otherwise, if |urlRecord|'s [=url/scheme=] is "`https`", set |urlRecord|'s [=url/scheme=] to
328 | "`wss`".
329 | 1. If |urlRecord|'s [=scheme=] is not "[=ws=]
" or "[=wss=]
", then throw a
330 | "{{SyntaxError}}" {{DOMException}}.
331 | 1. If |urlRecord|'s [=fragment=] is non-null, then throw a "{{SyntaxError}}" {{DOMException}}.
332 | 1. If |protocols| is a string, set |protocols| to a sequence consisting of just that string.
333 | 1. If any of the values in |protocols| occur more than once or otherwise fail to match the
334 | requirements for elements that comprise the value of
335 | \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol,
336 | then throw a "{{SyntaxError}}" {{DOMException}}. [[!WSP]]
337 | 1. Set [=this=]'s [=WebSocket/internal-url|url=] to |urlRecord|.
338 | 1. Let |client| be [=this=]'s [=relevant settings object=].
339 | 1. Run this step [=in parallel=]:
340 | 1. [=Establish a WebSocket connection=] given |urlRecord|, |protocols|, and |client|. [[!FETCH]]
341 |
342 | If the [=establish a WebSocket connection=] algorithm 343 | fails, it triggers the [=fail the WebSocket connection=] algorithm, which 344 | then invokes the [=close the WebSocket connection=] algorithm, which then 345 | establishes that [=the WebSocket connection is closed=], which fires the 346 | {{WebSocket/close}} event as described below. 347 |
The connection is already closing or is already closed. If it has not already, a 378 | {{WebSocket/close}} event will eventually fire as described below. 379 | 380 | : If the WebSocket connection is not yet [=established=] [[!WSP]] 381 | :: [=Fail the WebSocket connection=] and set [=this=]'s [=WebSocket/ready state=] to 382 | {{WebSocket/CLOSING}} (2). [[!WSP]] 383 | 384 |
The [=fail the WebSocket connection=] algorithm invokes the [=close the 385 | WebSocket connection=] algorithm, which then establishes that [=the WebSocket connection is 386 | closed=], which fires the {{WebSocket/close}} event as described 387 | below. 388 | 389 | : If the WebSocket closing handshake has not yet been started [[!WSP]] 391 | :: [=Start the WebSocket closing handshake=] and set [=this=]'s [=WebSocket/ready state=] to 392 | {{WebSocket/CLOSING}} (2). [[!WSP]] 393 | 394 | If neither |code| nor |reason| is present, the WebSocket Close message must not have a body. 395 | 396 |
The WebSocket Protocol erroneously states that the status code is required for the [=start the WebSocket closing handshake=] algorithm.
398 |
399 |
400 | If |code| is present, then the status code to use in the WebSocket Close
401 | message must be the integer given by |code|. [[!WSP]]
402 |
403 | If |reason| is also present, then |reasonBytes| must be provided in the Close message after the
404 | status code. [[!WSP]]
405 |
406 | The [=start the WebSocket closing handshake=] algorithm eventually invokes the
407 | [=close the WebSocket connection=] algorithm, which then establishes that [=the WebSocket
408 | connection is closed=], which fires the {{WebSocket/close}} event as
409 | described below.
410 |
411 | : Otherwise
412 | :: Set [=this=]'s [=WebSocket/ready state=] to {{WebSocket/CLOSING}} (2).
413 |
414 | [=The WebSocket closing handshake is started=], and will eventually invoke the
415 | [=close the WebSocket connection=] algorithm, which will establish that [=the WebSocket
416 | connection is closed=], and thus the {{WebSocket/close}} event will fire, as described below.
418 |
The {{WebSocket/close()}} method does not discard previously sent messages before 422 | starting the WebSocket closing handshake — even if, in practice, the user agent is still busy 423 | sending those messages, the handshake will only start after the messages are sent. 426 | 427 |
User agents can use the [=WebSocket/binary type=] as a hint for how to handle 468 | incoming binary data: if it is "{{BinaryType/blob}}", it is safe to spool it to disk, and if it is 469 | "{{BinaryType/arraybuffer}}", it is likely more efficient to keep the data in memory. Naturally, 470 | user agents are encouraged to use more subtle heuristics to decide whether to keep incoming data in 471 | memory or not, e.g. based on how big the data is or how common it is for a script to change the 472 | attribute at the last minute. This latter aspect is important in particular because it is quite 473 | possible for the attribute to be changed after the user agent has received the data but before the 474 | user agent has fired the event for it. 475 | 476 |
[=Event handler=] | [=Event handler event type=] 542 | |
---|---|
onopen | {{WebSocket/open}} 544 | |
onmessage | {{WebSocket/message}} 545 | |
onerror | {{WebSocket/error}} 546 | |
onclose | {{WebSocket/close}} 547 | |
Since the algorithm above is queued as a task, there is no 565 | race condition between the WebSocket connection 566 | being established and the script setting up an event listener for the {{WebSocket/open}} 567 | event. 568 | 569 |
User agents are encouraged to check if they can perform the above steps efficiently 602 | before they run the task, picking tasks from other [=task queues=] while they prepare the buffers 603 | if not. For example, if the [=WebSocket/binary type=] is "{{BinaryType/blob}}" when the data 604 | arrived, and the user agent spooled all the data to disk, but just before running the above 605 | [=task=] for this particular message the script switched [=WebSocket/binary type=] to 606 | "{{BinaryType/arraybuffer}}", the user agent would want to page the data back to RAM before running 607 | this [=task=] so as to avoid stalling the main thread while it created the {{ArrayBuffer}} object. 608 | 609 |
When [=the WebSocket connection is closed=], possibly [=cleanly=], the user 640 | agent must [=queue a task=] to run the following substeps: 641 | 642 |
In particular, this means the code 1015 is not used by the user agent (unless the 681 | server erroneously uses it in its close frame, of course). 682 | 683 |
2 | Group: WHATWG 3 | Date: 2022-03-21 4 | H1: WebSockets 5 | Shortname: websockets 6 | Text Macro: TWITTER whatsockets 7 | Text Macro: LATESTRD 2022-03 8 | Abstract: This specification provides APIs to enable web applications to maintain bidirectional 9 | Abstract: communications with server-side processes. 10 | Translation: ja https://triple-underscore.github.io/WebSocket-ja.html 11 | Indent: 1 12 | Markup Shorthands: markdown yes 13 |14 | 15 |
16 | { 17 | "WSP": { 18 | "aliasOf": "RFC6455" 19 | }, 20 | "HSTS": { 21 | "aliasOf": "RFC6797" 22 | } 23 | } 24 |25 | 26 |
27 | spec:url; type:interface; 28 | text:URL 29 | spec:url; type:dfn; 30 | text:fragment 31 | text:scheme 32 | spec:html; type:dfn; 33 | text:task queues 34 | for:/; text:event loop 35 | spec:url; type:dfn; 36 | text:origin 37 | for:/; text:url 38 |39 | 40 |
41 | spec:RFC6455; urlPrefix: https://tools.ietf.org/html/rfc6455 42 | type: dfn 43 | text:the WebSocket connection is established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 44 | text:extensions in use; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 45 | text:subprotocol in use; url:page-19:~:text=_Subprotocol%20In,Use_ 46 | text:a WebSocket message has been received; url:page-66:~:text=_A%20WebSocket%20Message%20Has%20Been%20Received_ 47 | text:send a WebSocket Message; url:page-66:~:text=needs%20to-,_Send%20a%20WebSocket%20Message_ 48 | text:fail the WebSocket connection; url:section-7.1.7 49 | text:close the WebSocket connection; url:section-7.1.1 50 | text:start the WebSocket closing handshake; url:section-7.1.2 51 | text:the WebSocket closing handshake is started; url:section-7.1.3 52 | text:the WebSocket connection is closed; url:section-7.1.4 53 | text:the WebSocket connection close code; url:section-7.1.5 54 | text:the WebSocket connection close reason; url:section-7.1.6 55 | text:established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 56 | text:ws; url:section-11.1.1 57 | text:wss; url:section-11.1.2 58 | text:cleanly; url:page-41:~:text=closed-,_cleanly_. 59 | type: http-header; text:Sec-WebSocket-Protocol; url:section-11.3.4 60 | spec:html; type:dfn; urlPrefix: https://html.spec.whatwg.org/multipage/webappapis.html 61 | for:event loop; text:step 1; url:step1 62 |63 | 64 | 65 | # Introduction # {#network-intro} 66 | 67 |
This interface does not allow for raw access to the underlying network. For 75 | example, this interface could not be used to implement an IRC client without proxying messages 76 | through a custom server.
77 |Although structured a little differently, carrying different properties, and 119 | therefore not shareable, a WebSocket connection is very close to identical to an "ordinary" 120 | [=connection=]. 121 | 122 |
This change of scheme is essential to integrate well with 136 | fetching. E.g., HSTS would not work without it. There is no real 137 | reason for WebSocket to have distinct schemes, it's a legacy artefact. 138 | [[!HSTS]] 139 | 140 | 1. Let |request| be a new request, whose URL is |requestURL|, 141 | client is |client|, [=service-workers mode=] is "`none`", 142 | referrer is "`no-referrer`", mode is "`websocket`", 143 | credentials mode is "`include`", cache mode is "`no-store`" 144 | , and redirect mode is "`error`". 145 | 146 | 1. Append (\``Upgrade`\`, \``websocket`\`) to |request|'s 147 | header list. 148 | 1. Append (\``Connection`\`, \``Upgrade`\`) to |request|'s 149 | header list. 150 | 1. Let |keyValue| be a nonce consisting of a randomly selected 16-byte value that has been 151 | forgiving-base64-encoded and [=isomorphic encoded=]. 152 | 153 |
If the randomly selected value was the byte sequence 0x01 154 | 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, |keyValue| would be 155 | forgiving-base64-encoded to "`AQIDBAUGBwgJCgsMDQ4PEC==`" and isomorphic encoded to 156 | \``AQIDBAUGBwgJCgsMDQ4PEC==`\`. 157 | 158 | 1. Append (\``Sec-WebSocket-Key`\`, |keyValue|) to |request|'s 159 | header list. 160 | 1. Append (\``Sec-WebSocket-Version`\`, \``13`\`) to |request|'s 161 | header list. 162 | 1. For each |protocol| in |protocols|, combine 163 | (\``Sec-WebSocket-Protocol`\`, |protocol|) in |request|'s header list. 164 | 165 | 1. Let |permessageDeflate| be a user-agent defined "`permessage-deflate`" extension 166 | header value. [[!WSP]] 167 | 168 |
\``permessage-deflate; client_max_window_bits`\` 169 | 170 | 1. Append (\``Sec-WebSocket-Extensions`\`, |permessageDeflate|) to 171 | |request|'s header list. 172 | 1. Fetch |request| with useParallelQueue set to true, 173 | and processResponse given |response| being these steps: 174 | 1. If |response| is a [=network error=] or its status is not 101, [=fail the 175 | WebSocket connection=]. 176 | 1. If |protocols| is not the empty list and [=extracting header list values=] given 177 | \``Sec-WebSocket-Protocol`\` and |response|'s header list 178 | results in null, failure, or the empty byte sequence, then [=fail the WebSocket connection=]. 179 | 180 |
This is different from the check on this header defined by The WebSocket Protocol. 181 | That only covers a subprotocol not requested by the client. This covers a subprotocol requested 182 | by the client, but not acknowledged by the server. 183 | 184 | 1. Follow the requirements stated step 2 to step 6, inclusive, of the last set of steps in 185 | section 4.1 of The WebSocket Protocol 186 | to validate |response|. This either results in [=fail the WebSocket connection=] 187 | or [=the WebSocket connection is established=]. 188 | 189 |
The reason redirects are not followed and this handshake is generally restricted is 195 | because it could introduce serious security problems in a web browser context. For example, consider 196 | a host with a WebSocket server at one path and an open HTTP redirector at another. Suddenly, any 197 | script that can be given a particular WebSocket URL can be tricked into communicating to (and 198 | potentially sharing secrets with) any host on the internet, even if the script checks that the URL 199 | has the right hostname. 200 | 201 | 202 | 203 | # The {{WebSocket}} interface # {#the-websocket-interface} 204 | ## Interface definition ## {#interface-definition} 205 | 206 | The Web IDL definition for the {{WebSocket}} class is given as follows: 207 | 208 |
|socket| = new {{WebSocket/constructor(url, protocols)|WebSocket}}(|url| [, |protocols| ])
261 | :: Creates a new {{WebSocket}} object, immediately establishing the associated WebSocket
262 | connection.
263 |
264 | |url| is a string giving the URL over which the connection is established.
265 | Only "`ws`" or "`wss`" schemes are allowed; others will cause a "{{SyntaxError}}"
266 | {{DOMException}}. URLs with [=fragments=] will also cause such an exception.
267 |
268 | |protocols| is either a string or an array of strings. If it is a string, it is equivalent to
269 | an array consisting of just that string; if it is omitted, it is equivalent to the empty array.
270 | Each string in the array is a subprotocol name. The connection will only be established if the
271 | server reports that it has selected one of these subprotocols. The subprotocol names have to
272 | match the requirements for elements that comprise the value of \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol.
274 | [[!WSP]]
275 |
276 | : |socket|.send(|data|)
277 | :: Transmits |data| using the WebSocket connection. |data| can be a string, a {{Blob}}, an
278 | {{ArrayBuffer}}, or an {{ArrayBufferView}}.
279 |
280 | : |socket|.close([ |code| ] [, |reason| ])
281 | :: Closes the WebSocket connection, optionally using |code| as [=the WebSocket connection
282 | close code=] and |reason| as the [=the WebSocket connection close reason=].
283 |
284 | : |socket|.url
285 | :: Returns the URL that was used to establish the WebSocket connection.
286 |
287 | : |socket|.readyState
288 | :: Returns the state of the WebSocket connection. It can have the values described above.
289 |
290 | : |socket|.bufferedAmount
291 | :: Returns the number of bytes of application data (UTF-8 text and binary data) that have been
292 | queued using {{WebSocket/send()}} but not yet been transmitted to the network.
293 |
294 | If the WebSocket connection is closed, this attribute's value will only increase with each call
295 | to the {{WebSocket/send()}} method. (The number does not reset to zero once the connection
296 | closes.)
297 |
298 | : |socket|.extensions
299 | :: Returns the extensions selected by the server, if any.
300 |
301 | : |socket|.protocol
302 | :: Returns the subprotocol selected by the server, if any. It can be used in conjunction with the
303 | array form of the constructor's second argument to perform subprotocol negotiation.
304 |
305 | : |socket|.binaryType
306 | :: Returns a string that indicates how binary data from |socket| is exposed to scripts:
307 |
308 | : "{{BinaryType/blob}}"
309 | :: Binary data is returned in {{Blob}} form.
310 | : "{{BinaryType/arraybuffer}}"
311 | :: Binary data is returned in {{ArrayBuffer}} form.
312 |
313 | The default is "{{BinaryType/blob}}".
314 |
315 | : |socket|.binaryType = value
316 | :: Changes how binary data is returned.
317 | new
321 | WebSocket(|url|, |protocols|)
322 | constructor steps are:
323 |
324 | 1. Let |urlRecord| be the result of applying the [=URL parser=] to |url|.
325 | 1. If |urlRecord| is failure, then throw a "{{SyntaxError}}" {{DOMException}}.
326 | 1. If |urlRecord|'s [=scheme=] is not "[=ws=]
" or "[=wss=]
", then throw a
327 | "{{SyntaxError}}" {{DOMException}}.
328 | 1. If |urlRecord|'s [=fragment=] is non-null, then throw a "{{SyntaxError}}" {{DOMException}}.
329 | 1. If |protocols| is a string, set |protocols| to a sequence consisting of just that string.
330 | 1. If any of the values in |protocols| occur more than once or otherwise fail to match the
331 | requirements for elements that comprise the value of
332 | \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol,
333 | then throw a "{{SyntaxError}}" {{DOMException}}. [[!WSP]]
334 | 1. Set [=this=]'s [=WebSocket/internal-url|url=] to |urlRecord|.
335 | 1. Let |client| be [=this=]'s [=relevant settings object=].
336 | 1. Run this step [=in parallel=]:
337 | 1. [=Establish a WebSocket connection=] given |urlRecord|, |protocols|, and |client|. [[!FETCH]]
338 |
339 | If the [=establish a WebSocket connection=] algorithm 340 | fails, it triggers the [=fail the WebSocket connection=] algorithm, which 341 | then invokes the [=close the WebSocket connection=] algorithm, which then 342 | establishes that [=the WebSocket connection is closed=], which fires the 343 | {{WebSocket/close}} event as described below. 344 |
The connection is already closing or is already closed. If it has not already, a 375 | {{WebSocket/close}} event will eventually fire as described below. 376 | 377 | : If the WebSocket connection is not yet [=established=] [[!WSP]] 378 | :: [=Fail the WebSocket connection=] and set [=this=]'s [=WebSocket/ready state=] to 379 | {{WebSocket/CLOSING}} (2). [[!WSP]] 380 | 381 |
The [=fail the WebSocket connection=] algorithm invokes the [=close the 382 | WebSocket connection=] algorithm, which then establishes that [=the WebSocket connection is 383 | closed=], which fires the {{WebSocket/close}} event as described 384 | below. 385 | 386 | : If the WebSocket closing handshake has not yet been started [[!WSP]] 388 | :: [=Start the WebSocket closing handshake=] and set [=this=]'s [=WebSocket/ready state=] to 389 | {{WebSocket/CLOSING}} (2). [[!WSP]] 390 | 391 | If neither |code| nor |reason| is present, the WebSocket Close message must not have a body. 392 | 393 |
The WebSocket Protocol erroneously states that the status code is required for the [=start the WebSocket closing handshake=] algorithm.
395 |
396 |
397 | If |code| is present, then the status code to use in the WebSocket Close
398 | message must be the integer given by |code|. [[!WSP]]
399 |
400 | If |reason| is also present, then |reasonBytes| must be provided in the Close message after the
401 | status code. [[!WSP]]
402 |
403 | The [=start the WebSocket closing handshake=] algorithm eventually invokes the
404 | [=close the WebSocket connection=] algorithm, which then establishes that [=the WebSocket
405 | connection is closed=], which fires the {{WebSocket/close}} event as
406 | described below.
407 |
408 | : Otherwise
409 | :: Set [=this=]'s [=WebSocket/ready state=] to {{WebSocket/CLOSING}} (2).
410 |
411 | [=The WebSocket closing handshake is started=], and will eventually invoke the
412 | [=close the WebSocket connection=] algorithm, which will establish that [=the WebSocket
413 | connection is closed=], and thus the {{WebSocket/close}} event will fire, as described below.
415 |
The {{WebSocket/close()}} method does not discard previously sent messages before 419 | starting the WebSocket closing handshake — even if, in practice, the user agent is still busy 420 | sending those messages, the handshake will only start after the messages are sent. 423 | 424 |
User agents can use the [=WebSocket/binary type=] as a hint for how to handle 465 | incoming binary data: if it is "{{BinaryType/blob}}", it is safe to spool it to disk, and if it is 466 | "{{BinaryType/arraybuffer}}", it is likely more efficient to keep the data in memory. Naturally, 467 | user agents are encouraged to use more subtle heuristics to decide whether to keep incoming data in 468 | memory or not, e.g. based on how big the data is or how common it is for a script to change the 469 | attribute at the last minute. This latter aspect is important in particular because it is quite 470 | possible for the attribute to be changed after the user agent has received the data but before the 471 | user agent has fired the event for it. 472 | 473 |
[=Event handler=] | [=Event handler event type=] 539 | |
---|---|
onopen | {{WebSocket/open}} 541 | |
onmessage | {{WebSocket/message}} 542 | |
onerror | {{WebSocket/error}} 543 | |
onclose | {{WebSocket/close}} 544 | |
Since the algorithm above is queued as a task, there is no 562 | race condition between the WebSocket connection 563 | being established and the script setting up an event listener for the {{WebSocket/open}} 564 | event. 565 | 566 |
User agents are encouraged to check if they can perform the above steps efficiently 599 | before they run the task, picking tasks from other [=task queues=] while they prepare the buffers 600 | if not. For example, if the [=WebSocket/binary type=] is "{{BinaryType/blob}}" when the data 601 | arrived, and the user agent spooled all the data to disk, but just before running the above 602 | [=task=] for this particular message the script switched [=WebSocket/binary type=] to 603 | "{{BinaryType/arraybuffer}}", the user agent would want to page the data back to RAM before running 604 | this [=task=] so as to avoid stalling the main thread while it created the {{ArrayBuffer}} object. 605 | 606 |
When [=the WebSocket connection is closed=], possibly [=cleanly=], the user 637 | agent must [=queue a task=] to run the following substeps: 638 | 639 |
In particular, this means the code 1015 is not used by the user agent (unless the 678 | server erroneously uses it in its close frame, of course). 679 | 680 |
2 | Group: WHATWG 3 | Status: RD 4 | Date: 2022-09-19 5 | H1: WebSockets 6 | Shortname: websockets 7 | Text Macro: TWITTER whatsockets 8 | Text Macro: LATESTRD 2022-09 9 | Abstract: This specification provides APIs to enable web applications to maintain bidirectional 10 | Abstract: communications with server-side processes. 11 | Translation: ja https://triple-underscore.github.io/WebSocket-ja.html 12 | Indent: 1 13 | Markup Shorthands: markdown yes 14 |15 | 16 |
17 | { 18 | "WSP": { 19 | "aliasOf": "RFC6455" 20 | }, 21 | "HSTS": { 22 | "aliasOf": "RFC6797" 23 | } 24 | } 25 |26 | 27 |
28 | spec:url; type:interface; 29 | text:URL 30 | spec:url; type:dfn; 31 | text:fragment 32 | text:scheme 33 | spec:html; type:dfn; 34 | text:task queues 35 | for:/; text:event loop 36 | spec:url; type:dfn; 37 | text:origin 38 | for:/; text:url 39 |40 | 41 |
42 | spec:RFC6455; urlPrefix: https://datatracker.ietf.org/doc/html/rfc6455 43 | type: dfn 44 | text:the WebSocket connection is established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 45 | text:extensions in use; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 46 | text:subprotocol in use; url:page-19:~:text=_Subprotocol%20In,Use_ 47 | text:a WebSocket message has been received; url:page-66:~:text=_A%20WebSocket%20Message%20Has%20Been%20Received_ 48 | text:send a WebSocket Message; url:page-66:~:text=needs%20to-,_Send%20a%20WebSocket%20Message_ 49 | text:fail the WebSocket connection; url:section-7.1.7 50 | text:close the WebSocket connection; url:section-7.1.1 51 | text:start the WebSocket closing handshake; url:section-7.1.2 52 | text:the WebSocket closing handshake is started; url:section-7.1.3 53 | text:the WebSocket connection is closed; url:section-7.1.4 54 | text:the WebSocket connection close code; url:section-7.1.5 55 | text:the WebSocket connection close reason; url:section-7.1.6 56 | text:established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 57 | text:ws; url:section-11.1.1 58 | text:wss; url:section-11.1.2 59 | text:cleanly; url:page-41:~:text=closed-,_cleanly_. 60 | type: http-header; text:Sec-WebSocket-Protocol; url:section-11.3.4 61 | spec:html; type:dfn; urlPrefix: https://html.spec.whatwg.org/multipage/webappapis.html 62 | for:event loop; text:step 1; url:step1 63 |64 | 65 | 66 | # Introduction # {#network-intro} 67 | 68 |
This interface does not allow for raw access to the underlying network. For 76 | example, this interface could not be used to implement an IRC client without proxying messages 77 | through a custom server.
78 |Although structured a little differently, carrying different properties, and 120 | therefore not shareable, a WebSocket connection is very close to identical to an "ordinary" 121 | [=connection=]. 122 | 123 |
This change of scheme is essential to integrate well with 137 | fetching. E.g., HSTS would not work without it. There is no real 138 | reason for WebSocket to have distinct schemes, it's a legacy artefact. 139 | [[!HSTS]] 140 | 141 | 1. Let |request| be a new request, whose URL is |requestURL|, 142 | client is |client|, [=service-workers mode=] is "`none`", 143 | referrer is "`no-referrer`", mode is "`websocket`", 144 | credentials mode is "`include`", cache mode is "`no-store`" 145 | , and redirect mode is "`error`". 146 | 147 | 1. Append (\``Upgrade`\`, \``websocket`\`) to |request|'s 148 | header list. 149 | 1. Append (\``Connection`\`, \``Upgrade`\`) to |request|'s 150 | header list. 151 | 1. Let |keyValue| be a nonce consisting of a randomly selected 16-byte value that has been 152 | forgiving-base64-encoded and [=isomorphic encoded=]. 153 | 154 |
If the randomly selected value was the byte sequence 0x01 155 | 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, |keyValue| would be 156 | forgiving-base64-encoded to "`AQIDBAUGBwgJCgsMDQ4PEC==`" and isomorphic encoded to 157 | \``AQIDBAUGBwgJCgsMDQ4PEC==`\`. 158 | 159 | 1. Append (\``Sec-WebSocket-Key`\`, |keyValue|) to |request|'s 160 | header list. 161 | 1. Append (\``Sec-WebSocket-Version`\`, \``13`\`) to |request|'s 162 | header list. 163 | 1. For each |protocol| in |protocols|, combine 164 | (\``Sec-WebSocket-Protocol`\`, |protocol|) in |request|'s header list. 165 | 166 | 1. Let |permessageDeflate| be a user-agent defined "`permessage-deflate`" extension 167 | header value. [[!WSP]] 168 | 169 |
\``permessage-deflate; client_max_window_bits`\` 170 | 171 | 1. Append (\``Sec-WebSocket-Extensions`\`, |permessageDeflate|) to 172 | |request|'s header list. 173 | 1. Fetch |request| with useParallelQueue set to true, 174 | and processResponse given |response| being these steps: 175 | 1. If |response| is a [=network error=] or its status is not 101, [=fail the 176 | WebSocket connection=]. 177 | 1. If |protocols| is not the empty list and [=extracting header list values=] given 178 | \``Sec-WebSocket-Protocol`\` and |response|'s header list 179 | results in null, failure, or the empty byte sequence, then [=fail the WebSocket connection=]. 180 | 181 |
This is different from the check on this header defined by The WebSocket Protocol. 182 | That only covers a subprotocol not requested by the client. This covers a subprotocol requested 183 | by the client, but not acknowledged by the server. 184 | 185 | 1. Follow the requirements stated step 2 to step 6, inclusive, of the last set of steps in 186 | section 4.1 of The WebSocket 187 | Protocol to validate |response|. This either results in [=fail the WebSocket connection=] 188 | or [=the WebSocket connection is established=]. 189 | 190 |
The reason redirects are not followed and this handshake is generally restricted is 196 | because it could introduce serious security problems in a web browser context. For example, consider 197 | a host with a WebSocket server at one path and an open HTTP redirector at another. Suddenly, any 198 | script that can be given a particular WebSocket URL can be tricked into communicating to (and 199 | potentially sharing secrets with) any host on the internet, even if the script checks that the URL 200 | has the right hostname. 201 | 202 | 203 | 204 | # The {{WebSocket}} interface # {#the-websocket-interface} 205 | ## Interface definition ## {#interface-definition} 206 | 207 | The Web IDL definition for the {{WebSocket}} class is given as follows: 208 | 209 |
|socket| = new {{WebSocket/constructor(url, protocols)|WebSocket}}(|url| [, |protocols| ])
262 | :: Creates a new {{WebSocket}} object, immediately establishing the associated WebSocket
263 | connection.
264 |
265 | |url| is a string giving the URL over which the connection is established.
266 | Only "`ws`" or "`wss`" schemes are allowed; others will cause a "{{SyntaxError}}"
267 | {{DOMException}}. URLs with [=fragments=] will also cause such an exception.
268 |
269 | |protocols| is either a string or an array of strings. If it is a string, it is equivalent to
270 | an array consisting of just that string; if it is omitted, it is equivalent to the empty array.
271 | Each string in the array is a subprotocol name. The connection will only be established if the
272 | server reports that it has selected one of these subprotocols. The subprotocol names have to
273 | match the requirements for elements that comprise the value of \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol.
275 | [[!WSP]]
276 |
277 | : |socket|.send(|data|)
278 | :: Transmits |data| using the WebSocket connection. |data| can be a string, a {{Blob}}, an
279 | {{ArrayBuffer}}, or an {{ArrayBufferView}}.
280 |
281 | : |socket|.close([ |code| ] [, |reason| ])
282 | :: Closes the WebSocket connection, optionally using |code| as [=the WebSocket connection
283 | close code=] and |reason| as [=the WebSocket connection close reason=].
284 |
285 | : |socket|.url
286 | :: Returns the URL that was used to establish the WebSocket connection.
287 |
288 | : |socket|.readyState
289 | :: Returns the state of the WebSocket connection. It can have the values described above.
290 |
291 | : |socket|.bufferedAmount
292 | :: Returns the number of bytes of application data (UTF-8 text and binary data) that have been
293 | queued using {{WebSocket/send()}} but not yet been transmitted to the network.
294 |
295 | If the WebSocket connection is closed, this attribute's value will only increase with each call
296 | to the {{WebSocket/send()}} method. (The number does not reset to zero once the connection
297 | closes.)
298 |
299 | : |socket|.extensions
300 | :: Returns the extensions selected by the server, if any.
301 |
302 | : |socket|.protocol
303 | :: Returns the subprotocol selected by the server, if any. It can be used in conjunction with the
304 | array form of the constructor's second argument to perform subprotocol negotiation.
305 |
306 | : |socket|.binaryType
307 | :: Returns a string that indicates how binary data from |socket| is exposed to scripts:
308 |
309 | : "{{BinaryType/blob}}"
310 | :: Binary data is returned in {{Blob}} form.
311 | : "{{BinaryType/arraybuffer}}"
312 | :: Binary data is returned in {{ArrayBuffer}} form.
313 |
314 | The default is "{{BinaryType/blob}}".
315 |
316 | : |socket|.binaryType = value
317 | :: Changes how binary data is returned.
318 | new
322 | WebSocket(|url|, |protocols|)
323 | constructor steps are:
324 |
325 | 1. Let |urlRecord| be the result of applying the [=URL parser=] to |url|.
326 | 1. If |urlRecord| is failure, then throw a "{{SyntaxError}}" {{DOMException}}.
327 | 1. If |urlRecord|'s [=scheme=] is not "[=ws=]
" or "[=wss=]
", then throw a
328 | "{{SyntaxError}}" {{DOMException}}.
329 | 1. If |urlRecord|'s [=fragment=] is non-null, then throw a "{{SyntaxError}}" {{DOMException}}.
330 | 1. If |protocols| is a string, set |protocols| to a sequence consisting of just that string.
331 | 1. If any of the values in |protocols| occur more than once or otherwise fail to match the
332 | requirements for elements that comprise the value of
333 | \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol,
334 | then throw a "{{SyntaxError}}" {{DOMException}}. [[!WSP]]
335 | 1. Set [=this=]'s [=WebSocket/internal-url|url=] to |urlRecord|.
336 | 1. Let |client| be [=this=]'s [=relevant settings object=].
337 | 1. Run this step [=in parallel=]:
338 | 1. [=Establish a WebSocket connection=] given |urlRecord|, |protocols|, and |client|. [[!FETCH]]
339 |
340 | If the [=establish a WebSocket connection=] algorithm 341 | fails, it triggers the [=fail the WebSocket connection=] algorithm, which 342 | then invokes the [=close the WebSocket connection=] algorithm, which then 343 | establishes that [=the WebSocket connection is closed=], which fires the 344 | {{WebSocket/close}} event as described below. 345 |
The connection is already closing or is already closed. If it has not already, a 376 | {{WebSocket/close}} event will eventually fire as described below. 377 | 378 | : If the WebSocket connection is not yet [=established=] [[!WSP]] 379 | :: [=Fail the WebSocket connection=] and set [=this=]'s [=WebSocket/ready state=] to 380 | {{WebSocket/CLOSING}} (2). [[!WSP]] 381 | 382 |
The [=fail the WebSocket connection=] algorithm invokes the [=close the 383 | WebSocket connection=] algorithm, which then establishes that [=the WebSocket connection is 384 | closed=], which fires the {{WebSocket/close}} event as described 385 | below. 386 | 387 | : If the WebSocket closing handshake has not yet been started [[!WSP]] 389 | :: [=Start the WebSocket closing handshake=] and set [=this=]'s [=WebSocket/ready state=] to 390 | {{WebSocket/CLOSING}} (2). [[!WSP]] 391 | 392 | If neither |code| nor |reason| is present, the WebSocket Close message must not have a body. 393 | 394 |
The WebSocket Protocol erroneously states that the status code is required for the [=start the WebSocket closing handshake=] algorithm.
396 |
397 |
398 | If |code| is present, then the status code to use in the WebSocket Close
399 | message must be the integer given by |code|. [[!WSP]]
400 |
401 | If |reason| is also present, then |reasonBytes| must be provided in the Close message after the
402 | status code. [[!WSP]]
403 |
404 | The [=start the WebSocket closing handshake=] algorithm eventually invokes the
405 | [=close the WebSocket connection=] algorithm, which then establishes that [=the WebSocket
406 | connection is closed=], which fires the {{WebSocket/close}} event as
407 | described below.
408 |
409 | : Otherwise
410 | :: Set [=this=]'s [=WebSocket/ready state=] to {{WebSocket/CLOSING}} (2).
411 |
412 | [=The WebSocket closing handshake is started=], and will eventually invoke the
413 | [=close the WebSocket connection=] algorithm, which will establish that [=the WebSocket
414 | connection is closed=], and thus the {{WebSocket/close}} event will fire, as described below.
416 |
The {{WebSocket/close()}} method does not discard previously sent messages before 420 | starting the WebSocket closing handshake — even if, in practice, the user agent is still busy 421 | sending those messages, the handshake will only start after the messages are sent. 424 | 425 |
User agents can use the [=WebSocket/binary type=] as a hint for how to handle 466 | incoming binary data: if it is "{{BinaryType/blob}}", it is safe to spool it to disk, and if it is 467 | "{{BinaryType/arraybuffer}}", it is likely more efficient to keep the data in memory. Naturally, 468 | user agents are encouraged to use more subtle heuristics to decide whether to keep incoming data in 469 | memory or not, e.g. based on how big the data is or how common it is for a script to change the 470 | attribute at the last minute. This latter aspect is important in particular because it is quite 471 | possible for the attribute to be changed after the user agent has received the data but before the 472 | user agent has fired the event for it. 473 | 474 |
[=Event handler=] | [=Event handler event type=] 540 | |
---|---|
onopen | {{WebSocket/open}} 542 | |
onmessage | {{WebSocket/message}} 543 | |
onerror | {{WebSocket/error}} 544 | |
onclose | {{WebSocket/close}} 545 | |
Since the algorithm above is queued as a task, there is no 563 | race condition between the WebSocket connection 564 | being established and the script setting up an event listener for the {{WebSocket/open}} 565 | event. 566 | 567 |
User agents are encouraged to check if they can perform the above steps efficiently 600 | before they run the task, picking tasks from other [=task queues=] while they prepare the buffers 601 | if not. For example, if the [=WebSocket/binary type=] is "{{BinaryType/blob}}" when the data 602 | arrived, and the user agent spooled all the data to disk, but just before running the above 603 | [=task=] for this particular message the script switched [=WebSocket/binary type=] to 604 | "{{BinaryType/arraybuffer}}", the user agent would want to page the data back to RAM before running 605 | this [=task=] so as to avoid stalling the main thread while it created the {{ArrayBuffer}} object. 606 | 607 |
When [=the WebSocket connection is closed=], possibly [=cleanly=], the user 638 | agent must [=queue a task=] to run the following substeps: 639 | 640 |
In particular, this means the code 1015 is not used by the user agent (unless the 679 | server erroneously uses it in its close frame, of course). 680 | 681 |
2 | Group: WHATWG 3 | Status: RD 4 | Date: 2023-09-18 5 | H1: WebSockets 6 | Shortname: websockets 7 | Text Macro: TWITTER whatsockets 8 | Text Macro: LATESTRD 2023-09 9 | Abstract: This specification provides APIs to enable web applications to maintain bidirectional 10 | Abstract: communications with server-side processes. 11 | Translation: ja https://triple-underscore.github.io/WebSocket-ja.html 12 | Indent: 1 13 | Markup Shorthands: markdown yes 14 |15 | 16 |
17 | { 18 | "WSP": { 19 | "aliasOf": "RFC6455" 20 | }, 21 | "HSTS": { 22 | "aliasOf": "RFC6797" 23 | } 24 | } 25 |26 | 27 |
28 | spec:url; type:interface; 29 | text:URL 30 | spec:url; type:dfn; 31 | text:fragment 32 | text:scheme 33 | spec:html; type:dfn; 34 | text:task queues 35 | for:/; text:event loop 36 | spec:url; type:dfn; 37 | text:origin 38 | for:/; text:url 39 |40 | 41 |
42 | spec:RFC6455; urlPrefix: https://datatracker.ietf.org/doc/html/rfc6455 43 | type: dfn 44 | text:the WebSocket connection is established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 45 | text:extensions in use; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 46 | text:subprotocol in use; url:page-19:~:text=_Subprotocol%20In,Use_ 47 | text:a WebSocket message has been received; url:page-66:~:text=_A%20WebSocket%20Message%20Has%20Been%20Received_ 48 | text:send a WebSocket Message; url:page-66:~:text=needs%20to-,_Send%20a%20WebSocket%20Message_ 49 | text:fail the WebSocket connection; url:section-7.1.7 50 | text:close the WebSocket connection; url:section-7.1.1 51 | text:start the WebSocket closing handshake; url:section-7.1.2 52 | text:the WebSocket closing handshake is started; url:section-7.1.3 53 | text:the WebSocket connection is closed; url:section-7.1.4 54 | text:the WebSocket connection close code; url:section-7.1.5 55 | text:the WebSocket connection close reason; url:section-7.1.6 56 | text:established; url:page-19:~:text=_The%20WebSocket%20Connection%20is%20Established_,-and 57 | text:ws; url:section-11.1.1 58 | text:wss; url:section-11.1.2 59 | text:cleanly; url:page-41:~:text=closed-,_cleanly_. 60 | type: http-header; text:Sec-WebSocket-Protocol; url:section-11.3.4 61 | spec:html; type:dfn; urlPrefix: https://html.spec.whatwg.org/multipage/webappapis.html 62 | for:event loop; text:step 1; url:step1 63 |64 | 65 | 66 | # Introduction # {#network-intro} 67 | 68 |
This interface does not allow for raw access to the underlying network. For 76 | example, this interface could not be used to implement an IRC client without proxying messages 77 | through a custom server.
78 |Although structured a little differently, carrying different properties, and 120 | therefore not shareable, a WebSocket connection is very close to identical to an "ordinary" 121 | [=connection=]. 122 | 123 |
This change of scheme is essential to integrate well with 137 | fetching. E.g., HSTS would not work without it. There is no real 138 | reason for WebSocket to have distinct schemes, it's a legacy artefact. 139 | [[!HSTS]] 140 | 141 | 1. Let |request| be a new request, whose URL is |requestURL|, 142 | client is |client|, [=service-workers mode=] is "`none`", 143 | referrer is "`no-referrer`", mode is "`websocket`", 144 | credentials mode is "`include`", cache mode is "`no-store`" 145 | , and redirect mode is "`error`". 146 | 147 | 1. Append (\``Upgrade`\`, \``websocket`\`) to |request|'s 148 | header list. 149 | 1. Append (\``Connection`\`, \``Upgrade`\`) to |request|'s 150 | header list. 151 | 1. Let |keyValue| be a nonce consisting of a randomly selected 16-byte value that has been 152 | forgiving-base64-encoded and [=isomorphic encoded=]. 153 | 154 |
If the randomly selected value was the byte sequence 0x01 155 | 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, |keyValue| would be 156 | forgiving-base64-encoded to "`AQIDBAUGBwgJCgsMDQ4PEC==`" and isomorphic encoded to 157 | \``AQIDBAUGBwgJCgsMDQ4PEC==`\`. 158 | 159 | 1. Append (\``Sec-WebSocket-Key`\`, |keyValue|) to |request|'s 160 | header list. 161 | 1. Append (\``Sec-WebSocket-Version`\`, \``13`\`) to |request|'s 162 | header list. 163 | 1. For each |protocol| in |protocols|, combine 164 | (\``Sec-WebSocket-Protocol`\`, |protocol|) in |request|'s header list. 165 | 166 | 1. Let |permessageDeflate| be a user-agent defined "`permessage-deflate`" extension 167 | header value. [[!WSP]] 168 | 169 |
\``permessage-deflate; client_max_window_bits`\` 170 | 171 | 1. Append (\``Sec-WebSocket-Extensions`\`, |permessageDeflate|) to 172 | |request|'s header list. 173 | 1. Fetch |request| with useParallelQueue set to true, 174 | and processResponse given |response| being these steps: 175 | 1. If |response| is a [=network error=] or its status is not 101, [=fail the 176 | WebSocket connection=]. 177 | 1. If |protocols| is not the empty list and [=extracting header list values=] given 178 | \``Sec-WebSocket-Protocol`\` and |response|'s header list 179 | results in null, failure, or the empty byte sequence, then [=fail the WebSocket connection=]. 180 | 181 |
This is different from the check on this header defined by The WebSocket Protocol. 182 | That only covers a subprotocol not requested by the client. This covers a subprotocol requested 183 | by the client, but not acknowledged by the server. 184 | 185 | 1. Follow the requirements stated step 2 to step 6, inclusive, of the last set of steps in 186 | section 4.1 of The WebSocket 187 | Protocol to validate |response|. This either results in [=fail the WebSocket connection=] 188 | or [=the WebSocket connection is established=]. 189 | 190 |
The reason redirects are not followed and this handshake is generally restricted is 196 | because it could introduce serious security problems in a web browser context. For example, consider 197 | a host with a WebSocket server at one path and an open HTTP redirector at another. Suddenly, any 198 | script that can be given a particular WebSocket URL can be tricked into communicating to (and 199 | potentially sharing secrets with) any host on the internet, even if the script checks that the URL 200 | has the right hostname. 201 | 202 | 203 | 204 | # The {{WebSocket}} interface # {#the-websocket-interface} 205 | ## Interface definition ## {#interface-definition} 206 | 207 | The Web IDL definition for the {{WebSocket}} class is given as follows: 208 | 209 |
|socket| = new {{WebSocket/constructor(url, protocols)|WebSocket}}(|url| [, |protocols| ])
262 | :: Creates a new {{WebSocket}} object, immediately establishing the associated WebSocket
263 | connection.
264 |
265 | |url| is a string giving the URL over which the connection is established.
266 | Only "`ws`", "`wss`", "`http`", and "`https`" schemes are allowed; others will cause a
267 | "{{SyntaxError}}" {{DOMException}}. URLs with [=fragments=] will always cause such an exception.
268 |
269 | |protocols| is either a string or an array of strings. If it is a string, it is equivalent to
270 | an array consisting of just that string; if it is omitted, it is equivalent to the empty array.
271 | Each string in the array is a subprotocol name. The connection will only be established if the
272 | server reports that it has selected one of these subprotocols. The subprotocol names have to
273 | match the requirements for elements that comprise the value of \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol.
275 | [[!WSP]]
276 |
277 | : |socket|.send(|data|)
278 | :: Transmits |data| using the WebSocket connection. |data| can be a string, a {{Blob}}, an
279 | {{ArrayBuffer}}, or an {{ArrayBufferView}}.
280 |
281 | : |socket|.close([ |code| ] [, |reason| ])
282 | :: Closes the WebSocket connection, optionally using |code| as [=the WebSocket connection
283 | close code=] and |reason| as [=the WebSocket connection close reason=].
284 |
285 | : |socket|.url
286 | :: Returns the URL that was used to establish the WebSocket connection.
287 |
288 | : |socket|.readyState
289 | :: Returns the state of the WebSocket connection. It can have the values described above.
290 |
291 | : |socket|.bufferedAmount
292 | :: Returns the number of bytes of application data (UTF-8 text and binary data) that have been
293 | queued using {{WebSocket/send()}} but not yet been transmitted to the network.
294 |
295 | If the WebSocket connection is closed, this attribute's value will only increase with each call
296 | to the {{WebSocket/send()}} method. (The number does not reset to zero once the connection
297 | closes.)
298 |
299 | : |socket|.extensions
300 | :: Returns the extensions selected by the server, if any.
301 |
302 | : |socket|.protocol
303 | :: Returns the subprotocol selected by the server, if any. It can be used in conjunction with the
304 | array form of the constructor's second argument to perform subprotocol negotiation.
305 |
306 | : |socket|.binaryType
307 | :: Returns a string that indicates how binary data from |socket| is exposed to scripts:
308 |
309 | : "{{BinaryType/blob}}"
310 | :: Binary data is returned in {{Blob}} form.
311 | : "{{BinaryType/arraybuffer}}"
312 | :: Binary data is returned in {{ArrayBuffer}} form.
313 |
314 | The default is "{{BinaryType/blob}}".
315 |
316 | : |socket|.binaryType = value
317 | :: Changes how binary data is returned.
318 | new
322 | WebSocket(|url|, |protocols|)
323 | constructor steps are:
324 |
325 | 1. Let |baseURL| be [=this=]'s [=relevant settings object=]'s [=API base URL=].
326 | 1. Let |urlRecord| be the result of applying the [=URL parser=] to |url| with |baseURL|.
327 | 1. If |urlRecord| is failure, then throw a "{{SyntaxError}}" {{DOMException}}.
328 | 1. If |urlRecord|'s [=url/scheme=] is "`http`", then set |urlRecord|'s [=url/scheme=] to "`ws`".
329 | 1. Otherwise, if |urlRecord|'s [=url/scheme=] is "`https`", set |urlRecord|'s [=url/scheme=] to
330 | "`wss`".
331 | 1. If |urlRecord|'s [=scheme=] is not "[=ws=]
" or "[=wss=]
", then throw a
332 | "{{SyntaxError}}" {{DOMException}}.
333 | 1. If |urlRecord|'s [=fragment=] is non-null, then throw a "{{SyntaxError}}" {{DOMException}}.
334 | 1. If |protocols| is a string, set |protocols| to a sequence consisting of just that string.
335 | 1. If any of the values in |protocols| occur more than once or otherwise fail to match the
336 | requirements for elements that comprise the value of
337 | \``Sec-WebSocket-Protocol`\` fields as defined by The WebSocket protocol,
338 | then throw a "{{SyntaxError}}" {{DOMException}}. [[!WSP]]
339 | 1. Set [=this=]'s [=WebSocket/internal-url|url=] to |urlRecord|.
340 | 1. Let |client| be [=this=]'s [=relevant settings object=].
341 | 1. Run this step [=in parallel=]:
342 | 1. [=Establish a WebSocket connection=] given |urlRecord|, |protocols|, and |client|. [[!FETCH]]
343 |
344 | If the [=establish a WebSocket connection=] algorithm 345 | fails, it triggers the [=fail the WebSocket connection=] algorithm, which 346 | then invokes the [=close the WebSocket connection=] algorithm, which then 347 | establishes that [=the WebSocket connection is closed=], which fires the 348 | {{WebSocket/close}} event as described below. 349 |
The connection is already closing or is already closed. If it has not already, a 380 | {{WebSocket/close}} event will eventually fire as described below. 381 | 382 | : If the WebSocket connection is not yet [=established=] [[!WSP]] 383 | :: [=Fail the WebSocket connection=] and set [=this=]'s [=WebSocket/ready state=] to 384 | {{WebSocket/CLOSING}} (2). [[!WSP]] 385 | 386 |
The [=fail the WebSocket connection=] algorithm invokes the [=close the 387 | WebSocket connection=] algorithm, which then establishes that [=the WebSocket connection is 388 | closed=], which fires the {{WebSocket/close}} event as described 389 | below. 390 | 391 | : If the WebSocket closing handshake has not yet been started [[!WSP]] 393 | :: [=Start the WebSocket closing handshake=] and set [=this=]'s [=WebSocket/ready state=] to 394 | {{WebSocket/CLOSING}} (2). [[!WSP]] 395 | 396 | If neither |code| nor |reason| is present, the WebSocket Close message must not have a body. 397 | 398 |
The WebSocket Protocol erroneously states that the status code is required for the [=start the WebSocket closing handshake=] algorithm.
400 |
401 |
402 | If |code| is present, then the status code to use in the WebSocket Close
403 | message must be the integer given by |code|. [[!WSP]]
404 |
405 | If |reason| is also present, then |reasonBytes| must be provided in the Close message after the
406 | status code. [[!WSP]]
407 |
408 | The [=start the WebSocket closing handshake=] algorithm eventually invokes the
409 | [=close the WebSocket connection=] algorithm, which then establishes that [=the WebSocket
410 | connection is closed=], which fires the {{WebSocket/close}} event as
411 | described below.
412 |
413 | : Otherwise
414 | :: Set [=this=]'s [=WebSocket/ready state=] to {{WebSocket/CLOSING}} (2).
415 |
416 | [=The WebSocket closing handshake is started=], and will eventually invoke the
417 | [=close the WebSocket connection=] algorithm, which will establish that [=the WebSocket
418 | connection is closed=], and thus the {{WebSocket/close}} event will fire, as described below.
420 |
The {{WebSocket/close()}} method does not discard previously sent messages before 424 | starting the WebSocket closing handshake — even if, in practice, the user agent is still busy 425 | sending those messages, the handshake will only start after the messages are sent. 428 | 429 |
User agents can use the [=WebSocket/binary type=] as a hint for how to handle 470 | incoming binary data: if it is "{{BinaryType/blob}}", it is safe to spool it to disk, and if it is 471 | "{{BinaryType/arraybuffer}}", it is likely more efficient to keep the data in memory. Naturally, 472 | user agents are encouraged to use more subtle heuristics to decide whether to keep incoming data in 473 | memory or not, e.g. based on how big the data is or how common it is for a script to change the 474 | attribute at the last minute. This latter aspect is important in particular because it is quite 475 | possible for the attribute to be changed after the user agent has received the data but before the 476 | user agent has fired the event for it. 477 | 478 |
[=Event handler=] | [=Event handler event type=] 544 | |
---|---|
onopen | {{WebSocket/open}} 546 | |
onmessage | {{WebSocket/message}} 547 | |
onerror | {{WebSocket/error}} 548 | |
onclose | {{WebSocket/close}} 549 | |
Since the algorithm above is queued as a task, there is no 567 | race condition between the WebSocket connection 568 | being established and the script setting up an event listener for the {{WebSocket/open}} 569 | event. 570 | 571 |
User agents are encouraged to check if they can perform the above steps efficiently 604 | before they run the task, picking tasks from other [=task queues=] while they prepare the buffers 605 | if not. For example, if the [=WebSocket/binary type=] is "{{BinaryType/blob}}" when the data 606 | arrived, and the user agent spooled all the data to disk, but just before running the above 607 | [=task=] for this particular message the script switched [=WebSocket/binary type=] to 608 | "{{BinaryType/arraybuffer}}", the user agent would want to page the data back to RAM before running 609 | this [=task=] so as to avoid stalling the main thread while it created the {{ArrayBuffer}} object. 610 | 611 |
When [=the WebSocket connection is closed=], possibly [=cleanly=], the user 642 | agent must [=queue a task=] to run the following substeps: 643 | 644 |
In particular, this means the code 1015 is not used by the user agent (unless the 683 | server erroneously uses it in its close frame, of course). 684 | 685 |