-
Notifications
You must be signed in to change notification settings - Fork 133
/
xhr.bs
2025 lines (1528 loc) · 73 KB
/
xhr.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class=metadata>
Group: WHATWG
H1: XMLHttpRequest
Shortname: xhr
Text Macro: TWITTER xhrstandard
Text Macro: LATESTRD 2024-02
Abstract: The XMLHttpRequest Standard defines an API that provides scripted client functionality for transferring data between a client and a server.
Translation: ja https://triple-underscore.github.io/XHR-ja.html
Translate IDs: enumdef-xmlhttprequestresponsetype xmlhttprequestresponsetype,dictdef-progresseventinit progresseventinit,typedefdef-formdataentryvalue formdataentryvalue
</pre>
<!-- Temporary: https://github.com/w3c/webdriver-bidi/issues/358 -->
<pre class=link-defaults>
spec:webdriver-bidi; type:dfn; text:event
spec:fetch; type:dfn; for:/; text:credentials
</pre>
<h2 id=introduction>Introduction</h2>
<p><em>This section is non-normative.</em>
<p>The {{XMLHttpRequest}} object is an API for <a for=/>fetching</a> resources.
<p>The name {{XMLHttpRequest}} is historical and has no bearing on its functionality.
<div id=example-xhr class=example>
<p>Some simple code to do something with data from an XML document
fetched over the network:
<pre><code class=lang-javascript>
function processData(data) {
// taking care of data
}
function handler() {
if(this.status == 200 &&
this.responseXML != null &&
this.responseXML.getElementById('test').textContent) {
// success!
processData(this.responseXML.getElementById('test').textContent);
} else {
// something went wrong
…
}
}
var client = new XMLHttpRequest();
client.onload = handler;
client.open("GET", "unicorn.xml");
client.send();</code></pre>
<p>If you just want to log a message to the server:
<pre><code class=lang-javascript>
function log(message) {
var client = new XMLHttpRequest();
client.open("POST", "/log");
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send(message);
}</code></pre>
<p>Or if you want to check the status of a document on the server:
<pre><code class=lang-javascript>
function fetchStatus(address) {
var client = new XMLHttpRequest();
client.onload = function() {
// in case of network errors this might not give reliable results
returnStatus(this.status);
}
client.open("HEAD", address);
client.send();
}</code></pre>
</div>
<h3 id=specification-history>Specification history</h3>
<p>The {{XMLHttpRequest}} object was initially defined as part of
the WHATWG's HTML effort. (Based on Microsoft's implementation many years prior.)
It moved to the W3C in 2006. Extensions (e.g., progress events and
cross-origin requests) to {{XMLHttpRequest}} were developed in a
separate draft (XMLHttpRequest Level 2) until end of 2011, at which point
the two drafts were merged and {{XMLHttpRequest}} became a single
entity again from a standards perspective. End of 2012 it moved back to the
WHATWG.
<p>Discussion that led to the current draft can be found in the following mailing list
archives:
<ul class=brief>
<li><a href=https://lists.w3.org/Archives/Public/public-whatwg-archive/>[email protected]</a>
<li><a href=https://lists.w3.org/Archives/Public/public-webapps/>[email protected]</a>
<li><a href=https://lists.w3.org/Archives/Public/public-webapi/>[email protected]</a>
<li><a href=https://lists.w3.org/Archives/Public/public-appformats/>[email protected]</a>
</ul>
<h2 id=terminology>Terminology</h2>
<p>This specification depends on the Infra Standard. [[!INFRA]]
<p>This specification uses terminology from DOM, DOM Parsing and Serialization, Encoding,
Fetch, File API, HTML, URL, Web IDL, and XML.
[[!DOM]]
[[!DOM-PARSING]]
[[!ENCODING]]
[[!FETCH]]
[[!FILEAPI]]
[[!HTML]]
[[!URL]]
[[!WEBIDL]]
[[!XML]] [[!XML-NAMES]]
<h2 id=interface-xmlhttprequest>Interface {{XMLHttpRequest}}</h2>
<pre class=idl>
[Exposed=(Window,DedicatedWorker,SharedWorker)]
interface XMLHttpRequestEventTarget : EventTarget {
// event handlers
attribute EventHandler onloadstart;
attribute EventHandler onprogress;
attribute EventHandler onabort;
attribute EventHandler onerror;
attribute EventHandler onload;
attribute EventHandler ontimeout;
attribute EventHandler onloadend;
};
[Exposed=(Window,DedicatedWorker,SharedWorker)]
interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
};
enum XMLHttpRequestResponseType {
"",
"arraybuffer",
"blob",
"document",
"json",
"text"
};
[Exposed=(Window,DedicatedWorker,SharedWorker)]
interface XMLHttpRequest : XMLHttpRequestEventTarget {
constructor();
// event handler
attribute EventHandler onreadystatechange;
// states
const unsigned short UNSENT = 0;
const unsigned short OPENED = 1;
const unsigned short HEADERS_RECEIVED = 2;
const unsigned short LOADING = 3;
const unsigned short DONE = 4;
readonly attribute unsigned short readyState;
// request
undefined open(ByteString method, USVString url);
undefined open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null);
undefined setRequestHeader(ByteString name, ByteString value);
attribute unsigned long timeout;
attribute boolean withCredentials;
[SameObject] readonly attribute XMLHttpRequestUpload upload;
undefined send(optional (Document or XMLHttpRequestBodyInit)? body = null);
undefined abort();
// response
readonly attribute USVString responseURL;
readonly attribute unsigned short status;
readonly attribute ByteString statusText;
ByteString? getResponseHeader(ByteString name);
ByteString getAllResponseHeaders();
undefined overrideMimeType(DOMString mime);
attribute XMLHttpRequestResponseType responseType;
readonly attribute any response;
readonly attribute USVString responseText;
[Exposed=Window] readonly attribute Document? responseXML;
};
</pre>
<p>An {{XMLHttpRequest}} object has an associated:
<dl>
<dt><dfn>upload object</dfn>
<dd>An {{XMLHttpRequestUpload}} object.
<dt><dfn id=concept-xmlhttprequest-state>state</dfn>
<dd>One of <i>unsent</i>, <i>opened</i>, <i>headers received</i>, <i>loading</i>, and <i>done</i>;
initially <i>unsent</i>.
<dt><dfn id=send-flag><code>send()</code> flag</dfn>
<dd>A flag, initially unset.
<dt><dfn>timeout</dfn>
<dd>An unsigned integer, initially 0.
<dt><dfn>cross-origin credentials</dfn>
<dd>A boolean, initially false.
<dt><dfn>request method</dfn>
<dd>A <a for=/>method</a>.
<dt><dfn>request URL</dfn>
<dd>A <a for=/>URL</a>.
<dt><dfn id=author-request-headers>author request headers</dfn>
<dd>A <a for=/>header list</a>, initially empty.
<dt><dfn>request body</dfn>
<dd>Initially null.
<dt><dfn>synchronous flag</dfn>
<dd>A flag, initially unset.
<dt><dfn id=upload-complete-flag>upload complete flag</dfn>
<dd>A flag, initially unset.
<dt><dfn>upload listener flag</dfn>
<dd>A flag, initially unset.
<dt><dfn>timed out flag</dfn>
<dd>A flag, initially unset.
<dt><dfn id=response for=XMLHttpRequest>response</dfn>
<dd>A <a for=/>response</a>, initially a <a>network error</a>.
<dt><dfn>received bytes</dfn>
<dd>A <a for=/>byte sequence</a>, initially the empty byte sequence.
<dt><dfn>response type</dfn>
<dd>One of the empty string, "<code>arraybuffer</code>", "<code>blob</code>",
"<code>document</code>", "<code>json</code>", and "<code>text</code>"; initially the empty string.
<dt><dfn>response object</dfn>
<dd>An object, failure, or null, initially null.
<dt><dfn for=XMLHttpRequest>fetch controller</dfn>
<dd>A <a for=/>fetch controller</a>, initially a new <a for=/>fetch controller</a>.
<span class=note>The <a><code>send()</code></a> method sets it to a useful
<a for=/>fetch controller</a>, but for simplicity it always holds a
<a for=/>fetch controller</a>.</span>
<dt><dfn id=override-mime-type>override MIME type</dfn>
<dd>A <a for=/>MIME type</a> or null, initially null. <span class=note>Can get a value when
{{overrideMimeType()}} is invoked.</span>
</dl>
<h3 id=constructors>Constructors</h3>
<dl class=domintro>
<dt><code><var>client</var> = new <a constructor for=XMLHttpRequest>XMLHttpRequest()</a></code>
<dd>Returns a new {{XMLHttpRequest}} object.
</dl>
<p>The
<dfn id=dom-xmlhttprequest constructor for=XMLHttpRequest lt="XMLHttpRequest()"><code>new XMLHttpRequest()</code></dfn>
constructor steps are:
<ol>
<li><p>Set <a>this</a>'s <a>upload object</a> to a <a for=/>new</a>
<code>XMLHttpRequestUpload</code> object.
</ol>
<h3 id=garbage-collection>Garbage collection</h3>
<!-- Based on EventSource and WebSocket. Not sure what I am doing. -->
<p>An {{XMLHttpRequest}} object must not be garbage collected if its
<a>state</a> is either
<i>opened</i> with the <a><code>send()</code> flag</a> set,
<i>headers received</i>, or <i>loading</i>, and it has one or more
<a>event listeners</a>
registered whose <b>type</b> is one of
{{XMLHttpRequest/readystatechange}},
{{XMLHttpRequestEventTarget/progress}},
{{XMLHttpRequestEventTarget/abort}},
{{XMLHttpRequestEventTarget/error}},
{{XMLHttpRequestEventTarget/load}},
{{XMLHttpRequestEventTarget/timeout!!event}}, and
{{XMLHttpRequestEventTarget/loadend}}.
<!-- No need to mention upload event listeners as they happen during /opened/. -->
<p>If an {{XMLHttpRequest}} object is garbage collected while its connection is still open, the user
agent must <a for="fetch controller">terminate</a> the {{XMLHttpRequest}} object's
<a for=XMLHttpRequest>fetch controller</a>.
<h3 id=event-handlers>Event handlers</h3>
<p>The following are the
<a>event handlers</a> (and their corresponding
<a>event handler event types</a>)
that must be supported on objects implementing an interface that inherits
from {{XMLHttpRequestEventTarget}} as attributes:
<table>
<thead>
<tr>
<th><a lt="event handlers">event handler</a>
<th><a>event handler event type</a>
<tbody>
<tr>
<td><dfn id=handler-xhr-onloadstart attribute for=XMLHttpRequestEventTarget><code>onloadstart</code></dfn>
<td>{{XMLHttpRequestEventTarget/loadstart}}
<tr>
<td><dfn id=handler-xhr-onprogress attribute for=XMLHttpRequestEventTarget><code>onprogress</code></dfn>
<td>{{XMLHttpRequestEventTarget/progress}}
<tr>
<td><dfn id=handler-xhr-onabort attribute for=XMLHttpRequestEventTarget><code>onabort</code></dfn>
<td>{{XMLHttpRequestEventTarget/abort}}
<tr>
<td><dfn id=handler-xhr-onerror attribute for=XMLHttpRequestEventTarget><code>onerror</code></dfn>
<td>{{XMLHttpRequestEventTarget/error}}
<tr>
<td><dfn id=handler-xhr-onload attribute for=XMLHttpRequestEventTarget><code>onload</code></dfn>
<td>{{XMLHttpRequestEventTarget/load}}
<tr>
<td><dfn id=handler-xhr-ontimeout attribute for=XMLHttpRequestEventTarget><code>ontimeout</code></dfn>
<td>{{XMLHttpRequestEventTarget/timeout!!event}}
<tr>
<td><dfn id=handler-xhr-onloadend attribute for=XMLHttpRequestEventTarget><code>onloadend</code></dfn>
<td>{{XMLHttpRequestEventTarget/loadend}}
</table>
<p>The following is the
<a lt="event handlers">event handler</a>
(and its corresponding
<a>event handler event type</a>) that must be
supported as attribute solely by the
{{XMLHttpRequest}} object:
<table>
<thead>
<tr>
<th><a lt="event handlers">event handler</a>
<th><a>event handler event type</a>
<tbody>
<tr>
<td><dfn id=handler-xhr-onreadystatechange attribute for=XMLHttpRequest><code>onreadystatechange</code></dfn>
<td><a event><code>readystatechange</code></a>
</table>
<h3 id=states>States</h3>
<dl class=domintro>
<dt><code><var>client</var> . <a attribute for=XMLHttpRequest>readyState</a></code>
<dd><p>Returns <var>client</var>'s
<a>state</a>.
</dl>
<p>The <dfn attribute for=XMLHttpRequest><code>readyState</code></dfn> getter steps are to return
the value from the table below in the cell of the second column, from the row where the value in the
cell in the first column is <a>this</a>'s <a>state</a>:
<table>
<tbody><tr>
<td><i>unsent</i>
<td><dfn const for=XMLHttpRequest><code>UNSENT</code></dfn> (numeric value 0)
<td>The object has been constructed.
<tr>
<td><i>opened</i>
<td><dfn const for=XMLHttpRequest><code>OPENED</code></dfn> (numeric value 1)
<td>The <a method for=XMLHttpRequest lt="open(method, url)"><code>open()</code></a> method has
been successfully invoked. During this state request headers can be set using
<a><code>setRequestHeader()</code></a> and the fetch can be initiated using the
<a><code>send()</code></a> method.
<tr>
<td><i>headers received</i>
<td><dfn const for=XMLHttpRequest><code>HEADERS_RECEIVED</code></dfn> (numeric value 2)
<td>All redirects (if any) have been followed and all headers of a response have been received.
<tr>
<td><i>loading</i>
<td><dfn const for=XMLHttpRequest><code>LOADING</code></dfn> (numeric value 3)
<td>The response body is being received.
<tr>
<td><i>done</i>
<td><dfn const for=XMLHttpRequest><code>DONE</code></dfn> (numeric value 4)
<td>The data transfer has been completed or something went wrong during the transfer (e.g.,
infinite redirects).
</table>
<h3 id=request>Request</h3>
<p class=note id=event-listeners-and-preflight>Registering one or more event listeners on an
{{XMLHttpRequestUpload}} object will result in a <a>CORS-preflight request</a>. (That is because
registering an event listener causes the <a>upload listener flag</a> to be set, which in turn causes
the <a>use-CORS-preflight flag</a> to be set.)
<h4 id=the-open()-method>The <code>open()</code> method</h4>
<dl class=domintro>
<dt><code><var>client</var> . <a method for=XMLHttpRequest lt="open(method, url)">open(<var>method</var>, <var>url</var> [, <var>async</var> = true [, <var>username</var> = null [, <var>password</var> = null]]])</a></code>
<dd>
<p>Sets the <a>request method</a>, <a>request URL</a>, and
<a>synchronous flag</a>.
<p>Throws a "{{SyntaxError!!exception}}" {{DOMException}} if either <var>method</var> is not a
valid method or <var>url</var> cannot be parsed.
<p>Throws a "{{SecurityError!!exception}}" {{DOMException}} if <var>method</var> is a
case-insensitive match for `<code>CONNECT</code>`, `<code>TRACE</code>`, or `<code>TRACK</code>`.
<p>Throws an "{{InvalidAccessError!!exception}}" {{DOMException}} if <var>async</var> is false,
the <a>current global object</a> is a {{Window}} object, and the
{{XMLHttpRequest/timeout!!attribute}} attribute is not zero or the {{XMLHttpRequest/responseType}}
attribute is not the empty string.
</dl>
<p class=critical id=sync-warning>Synchronous {{XMLHttpRequest}} outside of workers is in the
process of being removed from the web platform as it has detrimental effects to the end user's
experience. (This is a long process that takes many years.) Developers must not pass false for the
<var>async</var> argument when the <a>current global object</a> is a {{Window}} object. User agents
are strongly encouraged to warn about such usage in developer tools and may experiment with
<a lt=throw>throwing</a> an "{{InvalidAccessError!!exception}}" {{DOMException}} when it occurs.
<p>The
<dfn id=dom-xmlhttprequest-open method for=XMLHttpRequest><code>open(<var>method</var>, <var>url</var>)</code></dfn>
and
<dfn method for=XMLHttpRequest><code>open(<var>method</var>, <var>url</var>, <var>async</var>, <var>username</var>, <var>password</var>)</code></dfn>
method steps are:
<ol>
<li><p>If <a>this</a>'s <a>relevant global object</a> is a {{Window}} object and its
<a>associated <code>Document</code></a> is not <a>fully active</a>, then <a>throw</a> an
"{{InvalidStateError!!exception}}" {{DOMException}}.
<li><p>If <var>method</var> is not a <a for=/>method</a>, then <a>throw</a> a
"{{SyntaxError!!exception}}" {{DOMException}}.
<li><p>If <var>method</var> is a <a>forbidden method</a>, then <a>throw</a> a
"{{SecurityError!!exception}}" {{DOMException}}.
<li><p><a for=method>Normalize</a> <var>method</var>.
<li><p>Let <var>parsedURL</var> be the result of
<a lt="encoding-parse a URL">encoding-parsing a URL</a> <var>url</var>, relative to <a>this</a>'s
<a>relevant settings object</a>.
<li><p>If <var>parsedURL</var> is failure, then <a>throw</a> a "{{SyntaxError!!exception}}"
{{DOMException}}.
<li>
<p>If the <var>async</var> argument is omitted, set <var>async</var> to true, and set
<var>username</var> and <var>password</var> to null.
<p class=note>Unfortunately legacy content prevents treating the <var>async</var>
argument being <code>undefined</code> identical from it being omitted.
<li>
<p>If <var>parsedURL</var>'s <a for=url>host</a> is non-null, then:
<ol>
<li><p>If the <var>username</var> argument is not null,
<a>set the username</a> given <var>parsedURL</var> and
<var>username</var>.
<li><p>If the <var>password</var> argument is not null,
<a>set the password</a> given <var>parsedURL</var> and
<var>password</var>.
</ol>
<li><p>If <var>async</var> is false, the <a>current global object</a> is a {{Window}} object, and
either <a>this</a>'s <a>timeout</a> is not 0 or <a>this</a>'s <a>response type</a> is not
the empty string, then <a>throw</a> an "{{InvalidAccessError!!exception}}" {{DOMException}}.
<li>
<p><a for="fetch controller">Terminate</a> <a>this</a>'s
<a for=XMLHttpRequest>fetch controller</a>.
<p class=note>A <a for=/>fetch</a> can be ongoing at this point.
<li>
<p>Set variables associated with the object as follows:
<ul>
<li><p>Unset <a>this</a>'s <a><code>send()</code> flag</a>.
<li><p>Unset <a>this</a>'s <a>upload listener flag</a>.
<li><p>Set <a>this</a>'s <a>request method</a> to <var>method</var>.
<li><p>Set <a>this</a>'s <a>request URL</a> to <var>parsedURL</var>.
<li><p>Set <a>this</a>'s <a>synchronous flag</a> if <var>async</var> is false; otherwise unset
<a>this</a>'s <a>synchronous flag</a>.
<li><p><a for=list>Empty</a> <a>this</a>'s <a>author request headers</a>.
<li><p>Set <a>this</a>'s <a for=XMLHttpRequest>response</a> to a <a>network error</a>.
<li><p>Set <a>this</a>'s <a>received bytes</a> to the empty byte sequence.
<li><p>Set <a>this</a>'s <a>response object</a> to null.
</ul>
<p class=note><a>Override MIME type</a> is not overridden here as the
<code>overrideMimeType()</code> method can be invoked before the <code>open()</code> method.
<li>
<p>If <a>this</a>'s <a>state</a> is not <i>opened</i>, then:
<ol>
<li><p>Set <a>this</a>'s <a>state</a> to <i>opened</i>.
<li><p><a>Fire an event</a> named <a event><code>readystatechange</code></a> at <a>this</a>.
</ol>
</ol>
<p class=note>The reason there are two <code>open()</code> methods defined is due to a limitation of
the editing software used to write the XMLHttpRequest Standard.
<h4 id=the-setrequestheader()-method>The <code>setRequestHeader()</code> method</h4>
<dl class=domintro>
<dt><code><var>client</var> . <a method for=XMLHttpRequest>setRequestHeader(<var>name</var>, <var>value</var>)</a></code>
<dd>
<p>Appends a value to an existing request header or adds a new request header.
<p>Throws an "{{InvalidStateError!!exception}}" {{DOMException}} if either <a>state</a> is not
<i>opened</i> or the <a><code>send()</code> flag</a> is set.
<p>Throws a "{{SyntaxError!!exception}}" {{DOMException}} if <var>name</var> is not a header name
or if <var>value</var> is not a header value.
</dl>
<p>The
<dfn id=dom-xmlhttprequest-setrequestheader method for=XMLHttpRequest><code>setRequestHeader(<var>name</var>, <var>value</var>)</code></dfn>
method must run these steps:
<ol>
<li><p>If <a>this</a>'s <a>state</a> is not <i>opened</i>, then <a>throw</a> an
"{{InvalidStateError!!exception}}" {{DOMException}}.
<li><p>If <a>this</a>'s <a><code>send()</code> flag</a> is set, then <a>throw</a> an
"{{InvalidStateError!!exception}}" {{DOMException}}.
<li><p><a for="header value">Normalize</a> <var>value</var>.
<li>
<p>If <var>name</var> is not a <a>header name</a> or <var>value</var> is not a
<a>header value</a>, then <a>throw</a> a "{{SyntaxError!!exception}}" {{DOMException}}.
<p class=note>An empty byte sequence represents an empty <a>header value</a>.
<li><p>If (<var>name</var>, <var>value</var>) is a <a>forbidden request-header</a>, then return.
<li><p><a for="header list">Combine</a> (<var>name</var>, <var>value</var>) in <a>this</a>'s
<a>author request headers</a>.
</ol>
<div id=example-setting-header-twice class=example>
<p>Some simple code demonstrating what happens when setting the same
header twice:
<pre><code class=lang-javascript>
// The following script:
var client = new XMLHttpRequest();
client.open('GET', 'demo.cgi');
client.setRequestHeader('X-Test', 'one');
client.setRequestHeader('X-Test', 'two');
client.send();
// …results in the following header being sent:
// X-Test: one, two</code></pre>
</div>
<h4 id=the-timeout-attribute>The <code>timeout</code> getter and setter</h4>
<dl class=domintro>
<dt><code><var>client</var> . <a attribute for=XMLHttpRequest>timeout</a></code>
<dd>
<p>Can be set to a time in milliseconds. When set to a non-zero value will cause
<a for=/>fetching</a> to terminate after the given time has passed. When the time has passed, the
request has not yet completed, and <a>this</a>'s <a>synchronous flag</a> is unset, a
<a event><code>timeout</code></a> event will then be <a>dispatched</a>, or a
"{{TimeoutError!!exception}}" {{DOMException}} will be <a lt=throw>thrown</a> otherwise (for the
<a><code>send()</code></a> method).
<p>When set: throws an "{{InvalidAccessError!!exception}}" {{DOMException}} if the
<a>synchronous flag</a> is set and the <a>current global object</a> is a {{Window}} object.
</dl>
<p>The <dfn attribute for=XMLHttpRequest><code>timeout</code></dfn> getter steps are to return
<a>this</a>'s <a>timeout</a>.
<p>The {{XMLHttpRequest/timeout!!attribute}} setter steps are:
<ol>
<li><p>If the <a>current global object</a> is a {{Window}} object and <a>this</a>'s
<a>synchronous flag</a> is set, then <a>throw</a> an "{{InvalidAccessError!!exception}}"
{{DOMException}}.
<li><p>Set <a>this</a>'s <a>timeout</a> to the given value.
</ol>
<p class=note>This implies that the
{{XMLHttpRequest/timeout!!attribute}} attribute can be
set while <a for=/>fetching</a> is in
progress. If that occurs it will still be measured relative to the start
of <a for=/>fetching</a>.
<h4 id=the-withcredentials-attribute>The <code>withCredentials</code> getter and setter</h4>
<dl class=domintro>
<dt><code><var>client</var> . <a attribute for=XMLHttpRequest>withCredentials</a></code>
<dd>
<p>True when <a>credentials</a> are to be included in a cross-origin request. False when they are
to be excluded in a cross-origin request and when cookies are to be ignored in its response.
Initially false.
<p>When set: throws an "{{InvalidStateError!!exception}}" {{DOMException}} if <a>state</a> is not
<i>unsent</i> or <i>opened</i>, or if the <a><code>send()</code> flag</a> is set.
</dl>
<p>The <dfn attribute for=XMLHttpRequest><code>withCredentials</code></dfn> getter steps are to
return <a>this</a>'s <a>cross-origin credentials</a>.
<p>The {{XMLHttpRequest/withCredentials}} setter steps are:
<ol>
<li><p>If <a>this</a>'s <a>state</a> is not <i>unsent</i> or <i>opened</i>, then <a>throw</a> an
"{{InvalidStateError!!exception}}" {{DOMException}}.
<li><p>If <a>this</a>'s <a><code>send()</code> flag</a> is set, then <a>throw</a> an
"{{InvalidStateError!!exception}}" {{DOMException}}.
<li><p>Set <a>this</a>'s <a>cross-origin credentials</a> to the given value.
</ol>
<h4 id=the-upload-attribute>The <code>upload</code> getter</h4>
<dl class=domintro>
<dt><code><var>client</var> . <a attribute for=XMLHttpRequest>upload</a></code>
<dd><p>Returns the associated {{XMLHttpRequestUpload}}
object. It can be used to gather transmission information when data is
transferred to a server.
</dl>
<p>The <dfn attribute for=XMLHttpRequest><code>upload</code></dfn> getter steps are to return
<a>this</a>'s <a>upload object</a>.
<h4 id=the-send()-method>The <code>send()</code> method</h4>
<dl class=domintro>
<dt><code><var>client</var> . <a method for=XMLHttpRequest lt="send(body)">send([<var>body</var> = null])</a></code>
<dd>
<p>Initiates the request. The <var>body</var> argument provides the <a>request body</a>, if any,
and is ignored if the <a>request method</a> is <code>GET</code> or <code>HEAD</code>.
<p>Throws an "{{InvalidStateError!!exception}}" {{DOMException}} if either <a>state</a> is not
<i>opened</i> or the <a><code>send()</code> flag</a> is set.
</dl>
<p>The <dfn method for=XMLHttpRequest><code>send(<var>body</var>)</code></dfn> method steps are:
<ol>
<li><p>If <a>this</a>'s <a>state</a> is not <i>opened</i>, then <a>throw</a> an
"{{InvalidStateError!!exception}}" {{DOMException}}.
<li><p>If <a>this</a>'s <a><code>send()</code> flag</a> is set, then <a>throw</a> an
"{{InvalidStateError!!exception}}" {{DOMException}}.
<li><p>If <a>this</a>'s <a>request method</a> is `<code>GET</code>` or `<code>HEAD</code>`, then
set <var>body</var> to null.
<li>
<p>If <var>body</var> is not null, then:
<ol>
<li><p>Let <var>extractedContentType</var> be null.
<li><p>If <var>body</var> is a {{Document}}, then set <a>this</a>'s <a>request body</a> to
<var>body</var>, <a lt="fragment serializing algorithm steps">serialized</a>,
<a for=string>converted</a>, and <a lt="UTF-8 encode">UTF-8 encoded</a>.
<li>
<p>Otherwise:
<ol>
<li><p>Let <var>bodyWithType</var> be the result of
<a for=BodyInit lt="safely extract">safely extracting</a> <var>body</var>.
<li><p>Set <a>this</a>'s <a>request body</a> to <var>bodyWithType</var>'s
<a for="body with type">body</a>.
<li><p>Set <var>extractedContentType</var> to <var>bodyWithType</var>'s
<a for="body with type">type</a>.
</ol>
</li>
<li><p>Let <var>originalAuthorContentType</var> be the result of <a for="header list">getting</a>
`<code>Content-Type</code>` from <a>this</a>'s <a>author request headers</a>.
<li>
<p>If <var>originalAuthorContentType</var> is non-null, then:
<ol>
<li>
<p>If <var>body</var> is a {{Document}} or a {{USVString}}, then:
<ol>
<li><p>Let <var>contentTypeRecord</var> be the result of
<a lt="parse a MIME type from bytes">parsing</a> <var>originalAuthorContentType</var>.
<li>
<p>If <var>contentTypeRecord</var> is not failure, <var>contentTypeRecord</var>'s
<a for="MIME type">parameters</a>["<code>charset</code>"] <a for=map>exists</a>, and
<a for="MIME type">parameters</a>["<code>charset</code>"] is not an
<a>ASCII case-insensitive</a> match for "<code>UTF-8</code>", then:
<ol>
<li><p><a for=map>Set</a> <var>contentTypeRecord</var>'s
<a for="MIME type">parameters</a>["<code>charset</code>"] to "<code>UTF-8</code>".
<li><p>Let <var>newContentTypeSerialized</var> be the result of
<a lt="serialize a MIME type to bytes">serializing</a> <var>contentTypeRecord</var>.
<li><p><a for="header list">Set</a> (`<code>Content-Type</code>`,
<var>newContentTypeSerialized</var>) in <a>this</a>'s <a>author request headers</a>.
</ol>
</ol>
</ol>
<li>
<p>Otherwise:
<ol>
<li><p>If <var>body</var> is an <a>HTML document</a>, then <a for="header list">set</a>
(`<code>Content-Type</code>`, `<code>text/html;charset=UTF-8</code>`) in <a>this</a>'s
<a>author request headers</a>.
<li><p>Otherwise, if <var>body</var> is an <a>XML document</a>, <a for="header list">set</a>
(`<code>Content-Type</code>`, `<code>application/xml;charset=UTF-8</code>`) in <a>this</a>'s
<a>author request headers</a>.
<li><p>Otherwise, if <var>extractedContentType</var> is not null, <a for="header list">set</a>
(`<code>Content-Type</code>`, <var>extractedContentType</var>) in <a>this</a>'s
<a>author request headers</a>.
</ol>
</ol>
<li><p>If one or more event listeners are registered on <a>this</a>'s <a>upload object</a>, then
set <a>this</a>'s <a>upload listener flag</a>.
<li>
<p>Let <var>req</var> be a new
<a for=/>request</a>, initialized as
follows:
<dl>
<dt><a for=request>method</a>
<dd><a>This</a>'s <a>request method</a>.
<dt><a for=request>URL</a>
<dd><a>This</a>'s <a>request URL</a>.
<dt><a for=request>header list</a>
<dd><a>This</a>'s <a>author request headers</a>.
<dt><a for=request>unsafe-request flag</a>
<dd>Set.
<dt><a for=request>body</a>
<dd><a>This</a>'s <a>request body</a>.
<dt><a for=request>client</a>
<dd><a>This</a>'s <a>relevant settings object</a>.
<dt><a for=request>mode</a>
<dd>"<code>cors</code>".
<dt><a for=request>use-CORS-preflight flag</a>
<dd>Set if <a>this</a>'s <a>upload listener flag</a> is set.
<dt><a for=request>credentials mode</a>
<dd>If <a>this</a>'s <a>cross-origin credentials</a> is true, then "<code>include</code>";
otherwise "<code>same-origin</code>".
<dt><a for=request>use-URL-credentials flag</a>
<dd>Set if <a>this</a>'s <a>request URL</a> <a>includes credentials</a>.
<dt><a for=request>initiator type</a>
<dd>"<code>xmlhttprequest</code>".
</dl>
<li><p>Unset <a>this</a>'s <a>upload complete flag</a>.
<li><p>Unset <a>this</a>'s <a>timed out flag</a>.
<li><p>If <var>req</var>'s <a for=request>body</a> is null, then set <a>this</a>'s
<a>upload complete flag</a>.
<li><p>Set <a>this</a>'s <a><code>send()</code> flag</a>.
<li>
<p>If <a>this</a>'s <a>synchronous flag</a> is unset, then:
<ol>
<li><p><a>Fire a progress event</a> named <a event><code>loadstart</code></a> at <a>this</a>
with 0 and 0.
<li><p>Let <var>requestBodyTransmitted</var> be 0.
<li><p>Let <var>requestBodyLength</var> be <var>req</var>'s <a for=request>body</a>'s
<a for=body>length</a>, if <var>req</var>'s <a for=request>body</a> is non-null; otherwise 0.
<li><p>Assert: <var>requestBodyLength</var> is an integer.
<li><p>If <a>this</a>'s <a>upload complete flag</a> is unset and <a>this</a>'s
<a>upload listener flag</a> is set, then <a>fire a progress event</a> named
<a event><code>loadstart</code></a> at <a>this</a>'s <a>upload object</a> with
<var>requestBodyTransmitted</var> and <var>requestBodyLength</var>.
<li><p>If <a>this</a>'s <a>state</a> is not <i>opened</i> or <a>this</a>'s
<a><code>send()</code> flag</a> is unset, then return.
<li>
<p>Let <var>processRequestBodyChunkLength</var>, given a <var>bytesLength</var>, be these steps:
<ol>
<li><p>Increase <var>requestBodyTransmitted</var> by <var>bytesLength</var>.
<li><p>If not roughly 50ms have passed since these steps were last invoked, then return.
<li><p>If <a>this</a>'s <a>upload listener flag</a> is set, then <a>fire a progress event</a>
named <a event><code>progress</code></a> at <a>this</a>'s <a>upload object</a> with
<var>requestBodyTransmitted</var> and <var>requestBodyLength</var>.
<!-- upload complete flag can never be set here I hope -->
</ol>
<p class=note>These steps are only invoked when new bytes are transmitted.
<li>
<p>Let <var>processRequestEndOfBody</var> be these steps:
<ol>
<li><p>Set <a>this</a>'s <a>upload complete flag</a>.
<li><p>If <a>this</a>'s <a>upload listener flag</a> is unset, then return.
<li><p><a>Fire a progress event</a> named <a event><code>progress</code></a> at <a>this</a>'s
<a>upload object</a> with <var>requestBodyTransmitted</var> and <var>requestBodyLength</var>.
<li><p><a>Fire a progress event</a> named <a event><code>load</code></a> at <a>this</a>'s
<a>upload object</a> with <var>requestBodyTransmitted</var> and <var>requestBodyLength</var>.
<li><p><a>Fire a progress event</a> named <a event><code>loadend</code></a> at <a>this</a>'s
<a>upload object</a> with <var>requestBodyTransmitted</var> and <var>requestBodyLength</var>.
</ol>
<!-- upload complete flag can never be set here I hope -->
<li>
<p>Let <var>processResponse</var>, given a <var>response</var>, be these steps:
<ol>
<li><p>Set <a>this</a>'s <a for=XMLHttpRequest>response</a> to <var>response</var>.
<li><p><a>Handle errors</a> for <a>this</a>.
<li><p>If <a>this</a>'s <a for=XMLHttpRequest>response</a> is a <a>network error</a>, then
return.
<li><p>Set <a>this</a>'s <a>state</a> to <i>headers received</i>.
<li><p><a>Fire an event</a> named <a event><code>readystatechange</code></a> at <a>this</a>.
<li><p>If <a>this</a>'s <a>state</a> is not <i>headers received</i>, then return.
<li><p>If <a>this</a>'s <a for=XMLHttpRequest>response</a>'s <a for=response>body</a> is null,
then run <a>handle response end-of-body</a> for <a>this</a> and return.
<li><p>Let <var>length</var> be the result of <a for="header list">extracting a length</a> from
<a>this</a>'s <a for=XMLHttpRequest>response</a>'s <a for=response>header list</a>.
<li><p>If <var>length</var> is not an integer, then set it to 0.
<li>
<p>Let <var>processBodyChunk</var> given <var>bytes</var> be these steps:
<ol>
<li><p>Append <var>bytes</var> to <a>this</a>'s <a>received bytes</a>.
<li><p>If not roughly 50ms have passed since these steps were last invoked, then return.
<li><p>If <a>this</a>'s <a>state</a> is <i>headers received</i>, then set <a>this</a>'s
<a>state</a> to <i>loading</i>.
<li>
<p><a>Fire an event</a> named <a event><code>readystatechange</code></a> at <a>this</a>.
<p class=note>Web compatibility is the reason <a event><code>readystatechange</code></a>
fires more often than <a>this</a>'s <a>state</a> changes.
<li><p><a>Fire a progress event</a> named <a event><code>progress</code></a> at <a>this</a>
with <a>this</a>'s <a>received bytes</a>'s <a for="byte sequence">length</a> and
<var>length</var>.
</ol>
<li><p>Let <var>processEndOfBody</var> be this step: run <a>handle response end-of-body</a> for
<a>this</a>.
<li>
<p>Let <var>processBodyError</var> be these steps:
<ol>
<li><p>Set <a>this</a>'s <a for=XMLHttpRequest>response</a> to a <a for=/>network error</a>.
<li><p>Run <a>handle errors</a> for <a>this</a>.
</ol>
<li><p><a for=body>Incrementally read</a> <a>this</a>'s <a for=XMLHttpRequest>response</a>'s
<a for=response>body</a>, given <var>processBodyChunk</var>, <var>processEndOfBody</var>,
<var>processBodyError</var>, and <a>this</a>'s <a>relevant global object</a>.
</ol>
<li><p>Set <a>this</a>'s <a for=XMLHttpRequest>fetch controller</a> to the result of
<a for=/ lt=fetch>fetching</a> <var>req</var> with
<a for=fetch><i>processRequestBodyChunkLength</i></a> set to
<var>processRequestBodyChunkLength</var>, <a for=fetch><i>processRequestEndOfBody</i></a> set to
<var>processRequestEndOfBody</var>, and <a for=fetch><i>processResponse</i></a> set to
<var>processResponse</var>.
<li><p>Let <var>now</var> be the present time.
<!-- Eventually this should use some kind of time standard. -->
<li>
<p>Run these steps <a>in parallel</a>:
<ol>
<li><p>Wait until either <var>req</var>'s <a for=request>done flag</a> is set or <a>this</a>'s
<a>timeout</a> is not 0 and <a>this</a>'s <a>timeout</a> milliseconds have passed since
<var>now</var>.
<li><p>If <var>req</var>'s <a for=request>done flag</a> is unset, then set <a>this</a>'s
<a>timed out flag</a> and <a for="fetch controller">terminate</a> <a>this</a>'s
<a for=XMLHttpRequest>fetch controller</a>.
</ol>
</ol>
<li>
<p>Otherwise, if <a>this</a>'s <a>synchronous flag</a> is set:
<ol>
<li><p>Let <var>processedResponse</var> be false.
<li>
<p>Let <var>processResponseConsumeBody</var>, given a <var>response</var> and
<var>nullOrFailureOrBytes</var>, be these steps:
<ol>
<li><p>If <var>nullOrFailureOrBytes</var> is not failure, then set <a>this</a>'s
<a for=XMLHttpRequest>response</a> to <var>response</var>.
<li><p>If <var>nullOrFailureOrBytes</var> is a <a for=/>byte sequence</a>, then append
<var>nullOrFailureOrBytes</var> to <a>this</a>'s <a>received bytes</a>.
<li><p>Set <var>processedResponse</var> to true.
</ol>
<li><p>Set <a>this</a>'s <a for=XMLHttpRequest>fetch controller</a> to the result of
<a for=/ lt=fetch>fetching</a> <var>req</var> with
<a for=fetch><i>processResponseConsumeBody</i></a> set to <var>processResponseConsumeBody</var>
and <a for=fetch><i>useParallelQueue</i></a> set to true.
<li><p>Let <var>now</var> be the present time.
<!-- Eventually this should use some kind of time standard. -->
<li><p><a>Pause</a> until either <var>processedResponse</var> is true or <a>this</a>'s
<a>timeout</a> is not 0 and <a>this</a>'s <a>timeout</a> milliseconds have passed since
<var>now</var>.
<li><p>If <var>processedResponse</var> is false, then set <a>this</a>'s <a>timed out flag</a> and
<a for="fetch controller">terminate</a> <a>this</a>'s <a for=XMLHttpRequest>fetch controller</a>.
<li><p><a for="fetch controller">Report timing</a> for <a>this</a>'s
<a for=XMLHttpRequest>fetch controller</a> given the <a>current global object</a>.
<li><p>Run <a>handle response end-of-body</a> for <a>this</a>.
</ol>
</ol>
<p id=handle-response-end-of-file>To <dfn>handle response end-of-body</dfn> for an
{{XMLHttpRequest}} object <var>xhr</var>, run these steps:
<ol>
<li><p><a>Handle errors</a> for <var>xhr</var>.
<li><p>If <var>xhr</var>'s <a for=XMLHttpRequest>response</a> is a <a>network error</a>, then
return.
<li><p>Let <var>transmitted</var> be <var>xhr</var>'s <a>received bytes</a>'s
<a for="byte sequence">length</a>.
<li><p>Let <var>length</var> be the result of <a for="header list">extracting a length</a> from
<a>this</a>'s <a for=XMLHttpRequest>response</a>'s <a for=response>header list</a>.
<li><p>If <var>length</var> is not an integer, then set it to 0.
<li><p>If <var>xhr</var>'s <a>synchronous flag</a> is unset, then <a>fire a progress event</a>