idnits 2.17.00 (12 Aug 2021) /tmp/idnits54654/draft-nottingham-httpbis-retry-00.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) ** There are 16 instances of too long lines in the document, the longest one being 10 characters in excess of 72. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (August 11, 2016) is 2108 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Informational ---------------------------------------------------------------------------- -- Looks like a reference, but probably isn't: '4' on line 458 -- Looks like a reference, but probably isn't: '5' on line 463 -- Looks like a reference, but probably isn't: '1' on line 450 -- Looks like a reference, but probably isn't: '2' on line 452 -- Looks like a reference, but probably isn't: '3' on line 455 -- Looks like a reference, but probably isn't: '6' on line 509 -- Looks like a reference, but probably isn't: '7' on line 550 -- Looks like a reference, but probably isn't: '8' on line 610 -- Looks like a reference, but probably isn't: '9' on line 644 -- Looks like a reference, but probably isn't: '10' on line 667 -- Looks like a reference, but probably isn't: '11' on line 672 -- Looks like a reference, but probably isn't: '12' on line 692 == Outdated reference: draft-ietf-tls-tls13 has been published as RFC 8446 Summary: 2 errors (**), 0 flaws (~~), 2 warnings (==), 14 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group M. Nottingham 3 Internet-Draft August 11, 2016 4 Intended status: Informational 5 Expires: February 12, 2017 7 Retrying HTTP Requests 8 draft-nottingham-httpbis-retry-00 10 Abstract 12 HTTP allows requests to be automatically retried under certain 13 circumstances. This draft explores how this is implemented, 14 requirements for similar functionality from other parts of the stack, 15 and potential future improvements. 17 Note to Readers 19 This draft is not intended to be published as an RFC. 21 The issues list for this draft can be found at 22 https://github.com/mnot/I-D/labels/httpbis-retry . 24 The most recent (often, unpublished) draft is at 25 https://mnot.github.io/I-D/httpbis-retry/ . 27 Recent changes are listed at https://github.com/mnot/I-D/commits/gh- 28 pages/httpbis-retry . 30 Status of This Memo 32 This Internet-Draft is submitted in full conformance with the 33 provisions of BCP 78 and BCP 79. 35 Internet-Drafts are working documents of the Internet Engineering 36 Task Force (IETF). Note that other groups may also distribute 37 working documents as Internet-Drafts. The list of current Internet- 38 Drafts is at http://datatracker.ietf.org/drafts/current/. 40 Internet-Drafts are draft documents valid for a maximum of six months 41 and may be updated, replaced, or obsoleted by other documents at any 42 time. It is inappropriate to use Internet-Drafts as reference 43 material or to cite them other than as "work in progress." 45 This Internet-Draft will expire on February 12, 2017. 47 Copyright Notice 49 Copyright (c) 2016 IETF Trust and the persons identified as the 50 document authors. All rights reserved. 52 This document is subject to BCP 78 and the IETF Trust's Legal 53 Provisions Relating to IETF Documents 54 (http://trustee.ietf.org/license-info) in effect on the date of 55 publication of this document. Please review these documents 56 carefully, as they describe your rights and restrictions with respect 57 to this document. Code Components extracted from this document must 58 include Simplified BSD License text as described in Section 4.e of 59 the Trust Legal Provisions and are provided without warranty as 60 described in the Simplified BSD License. 62 Table of Contents 64 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 65 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 3 66 2. Background . . . . . . . . . . . . . . . . . . . . . . . . . 3 67 2.1. Retries and Replays: A Taxonomy of Repetition . . . . . . 3 68 2.2. What the Spec Says: Automatic Retries . . . . . . . . . . 4 69 2.3. What the Specs Say: Replay . . . . . . . . . . . . . . . 5 70 2.3.1. TCP Fast Open . . . . . . . . . . . . . . . . . . . . 5 71 2.3.2. TLS 1.3 . . . . . . . . . . . . . . . . . . . . . . . 5 72 2.3.3. QUIC . . . . . . . . . . . . . . . . . . . . . . . . 6 73 3. Discussion . . . . . . . . . . . . . . . . . . . . . . . . . 6 74 3.1. Automatic Retries In Practice . . . . . . . . . . . . . . 6 75 3.2. Replays Are Different . . . . . . . . . . . . . . . . . . 7 76 4. Possible Areas of Work . . . . . . . . . . . . . . . . . . . 8 77 4.1. Updating HTTP's Requirements for Retries . . . . . . . . 8 78 4.2. Protocol Extensions . . . . . . . . . . . . . . . . . . . 8 79 4.3. Feedback to Transport 0RT Efforts . . . . . . . . . . . . 9 80 5. Security Considerations . . . . . . . . . . . . . . . . . . . 9 81 6. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 9 82 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 9 83 7.1. Normative References . . . . . . . . . . . . . . . . . . 9 84 7.2. Informative References . . . . . . . . . . . . . . . . . 10 85 7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 10 86 Appendix A. When Clients Retry . . . . . . . . . . . . . . . . . 11 87 A.1. Squid . . . . . . . . . . . . . . . . . . . . . . . . . . 11 88 A.2. Traffic Server . . . . . . . . . . . . . . . . . . . . . 11 89 A.3. Firefox . . . . . . . . . . . . . . . . . . . . . . . . . 14 90 A.4. Chromium . . . . . . . . . . . . . . . . . . . . . . . . 15 91 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 16 93 1. Introduction 95 One of the benefits of HTTP's well-defined method semantics is that 96 they allow failed requests to be retried, under certain 97 circumstances. 99 However, interest in extending, redefining or just clarifying HTTP's 100 retry semantics is increasing, for a number of reasons: 102 o Since HTTP/1.1's requirements were written, there has been a 103 substantial amount of experience deploying and using HTTP, leading 104 implementations to refine their behaviour, arguably diverging from 105 the specification. 107 o Likewise, changes such as HTTP/2 [RFC7540] might change the 108 underlying assumptions that these requirements were based upon. 110 o Emerging lower-layer developments such as TCP Fast Open [RFC7413], 111 TLS/1.3 [I-D.ietf-tls-tls13] and QUIC 112 [I-D.hamilton-early-deployment-quic] introduce the possibility of 113 replayed requests in the beginning of a connection, thanks to Zero 114 Round Trip (0RT) modes. In some ways, these are similar to 115 retries - but not completely. 117 o Applications sometimes want requests to be retried by 118 infrastructure, but can't easily express them in a non-idempotent 119 request (such as GET). 121 This draft gives some background in Section 2, discusses aspects of 122 these issues in Section 3, suggesting possible areas of work in 123 Section 4, and cataloguing current implementation behaviours in 124 Appendix A. 126 1.1. Notational Conventions 128 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 129 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 130 document are to be interpreted as described in [RFC2119]. 132 2. Background 134 2.1. Retries and Replays: A Taxonomy of Repetition 136 In HTTP, there are three similar but separate phenomena that deserve 137 consideration for the purposes of this document: 139 1. *User Retries* happen when a user initiates an action that 140 results in a duplicate request being emitted. For example, a 141 user retry might occur when a "reload" button is pressed, a URL 142 is typed in again, "return" is pressed in the URL bar again, or a 143 navigation link or form button is pressed twice while still on 144 screen. 146 2. *Automatic Retries* happen when an HTTP client implementation 147 resends a previous request without user intervention or 148 initiation. This might happen when a GET request fails to return 149 a complete response, or when a connection drops before the 150 request is sent. Note that automatic retries can (and are) 151 performed both by user agents and intermediary clients. 153 3. *Replays* happen when the packet(s) containing a request are re- 154 sent on the network, either automatically as part of transport 155 protocol operation, or by an attacker. The closest upstream HTTP 156 client might not have any indication that a replay has occurred. 158 Note that retries initiated by code shipped to the client by the 159 server (e.g., in JavaScript) occupy a grey area here; however, 160 because they are not initiated by the generic HTTP client 161 implementation itself, we will consider them user retries for the 162 time being. 164 Also, this document doesn't include TCP-layer loss recovery (i.e., 165 retransmission). 167 2.2. What the Spec Says: Automatic Retries 169 [RFC7230], Section 6.3.1 allows HTTP requests to be retried in 170 certain circumstances: 172 When an inbound connection is closed prematurely, a client MAY 173 open a new connection and automatically retransmit an aborted 174 sequence of requests if all of those requests have idempotent 175 methods (Section 4.2.2 of [RFC7231]). A proxy MUST NOT 176 automatically retry non-idempotent requests. 178 A user agent MUST NOT automatically retry a request with a non- 179 idempotent method unless it has some means to know that the 180 request semantics are actually idempotent, regardless of the 181 method, or some means to detect that the original request was 182 never applied. For example, a user agent that knows (through 183 design or configuration) that a POST request to a given resource 184 is safe can repeat that request automatically. Likewise, a user 185 agent designed specifically to operate on a version control 186 repository might be able to recover from partial failure 187 conditions by checking the target resource revision(s) after a 188 failed connection, reverting or fixing any changes that were 189 partially applied, and then automatically retrying the requests 190 that failed. 192 A client SHOULD NOT automatically retry a failed automatic retry. 194 Note that the complete list of idempotent methods is maintained in 195 the IANA HTTP Method Registry [4]. 197 2.3. What the Specs Say: Replay 199 2.3.1. TCP Fast Open 201 [RFC7413], Section 6.3.1 addresses HTTP Request Replay with TCP Fast 202 Open: 204 While TFO is motivated by Web applications, the browser should not 205 use TFO to send requests in SYNs if those requests cannot tolerate 206 replays. One example is POST requests without application-layer 207 transaction protection (e.g., a unique identifier in the request 208 header). 210 On the other hand, TFO is particularly useful for GET requests. 211 GET request replay could happen across striped TCP connections: 212 after a server receives an HTTP request but before the ACKs of the 213 requests reach the browser, the browser may time out and retry the 214 same request on another (possibly new) TCP connection. This 215 differs from a TFO replay only in that the replay is initiated by 216 the browser, not by the TCP stack. 218 The same specification addresses HTTP over TLS in Section 6.3.2: 220 For Transport Layer Security (TLS) over TCP, it is safe and useful 221 to include a TLS client_hello in the SYN packet to save one RTT in 222 the TLS handshake. There is no concern about violating 223 idempotency. In particular, it can be used alone with the 224 speculative connection above. 226 2.3.2. TLS 1.3 228 [I-D.ietf-tls-tls13], Section 2.3 explains the properties of Zero-RTT 229 Data in TLS 1.3: 231 IMPORTANT NOTE: The security properties for 0-RTT data (regardless 232 of the cipher suite) are weaker than those for other kinds of TLS 233 data. Specifically: 235 1. This data is not forward secret, because it is encrypted 236 solely with the PSK. 238 2. There are no guarantees of non-replay between connections. 239 Unless the server takes special measures outside those 240 provided by TLS, the server has no guarantee that the same 241 0-RTT data was not transmitted on multiple 0-RTT connections 242 (See Section 4.2.6.2 for more details). This is especially 243 relevant if the data is authenticated either with TLS client 244 authentication or inside the application layer protocol. 245 However, 0-RTT data cannot be duplicated within a connection 246 (i.e., the server will not process the same data twice for the 247 same connection) and an attacker will not be able to make 248 0-RTT data appear to be 1-RTT data (because it is protected 249 with different keys.) 251 Section 4.2.6 defines a mechanism to limit the exposure to replay. 253 2.3.3. QUIC 255 The QUIC specifications don't say anything about the replay risk of 256 0RTT. 258 3. Discussion 260 3.1. Automatic Retries In Practice 262 In practice, it has been observed (see Appendix A) that some client 263 (both user agent and intermediary) implementations do automatically 264 retry requests. However, they do not do so consistently, and 265 arguably not in the spirit of the specification, unless this vague 266 catch-all: 268 some means to detect that the original request was never applied 270 is interpreted very broadly. 272 On the server side, it has been widely observed that content on the 273 Web doesn't always honour HTTP idemotency semantics, with many GET 274 requests incurring side effects, and with some sites even requiring 275 browsers to retry POST requests in order to properly interoperate. 276 (TODO: refs / details from Patrick and Artur). 278 Despite this situation, the Web seems to work reasonably well to date 279 (with notable exceptions [5]). 281 The status quo, therefore, is that no Web application can read HTTP's 282 retry requirements as a guarantee that any given request won't be 283 retried, even for methods that are not idempotent. As a result, 284 applications that care about avoiding duplicate requests need to 285 build a way to detect not only user retries but also automatic 286 retries into the application "above" HTTP itself. 288 3.2. Replays Are Different 290 TCP Fast Open [RFC7413], TLS/1.3 [I-D.ietf-tls-tls13] and QUIC 291 [I-D.hamilton-early-deployment-quic] all have mechanisms to carry 292 application data on the first packet sent by a client, to avoid the 293 latency of connection setup. 295 The request(s) in this first packet might be _replayed_, either 296 because the first packet is lost and retransmitted by the transport 297 protocol in use, or because an attacker observes the packet and sends 298 a duplicate at some point in the future. 300 At first glance, it seems as if the idempotency semantics of HTTP 301 request methods could be used to determine what requests are suitable 302 for inclusion in the first packet of various 0RT mechanisms being 303 discussed (as suggested by TCP Fast Open). For example, we could 304 disallow POST (and other non-idempotent methods) in 0RT data. 306 Upon reflection, though, the observations above lead us to believe 307 that since any request might be retried (automatically or by users), 308 applications will need to have a means of detecting duplicate 309 requests, thereby preventing side effects from replays as well as 310 retries. Thus, any HTTP request can be included in the first packet 311 of a 0RT, despite the risk of replay. 313 Two types of attack specific to replayed HTTP requests need to be 314 taken into account, however: 316 1. A replay is a potential Denial of Service vector. An attacker 317 that can replay a request many times can probe for weaknesses in 318 retry protections, and can bring a server that needs to do any 319 substantial processing down. 321 2. An attacker might use a replayed request to leak information 322 about the response over time. If they can observe the encrypted 323 payload on the wire, they can infer the size of the response 324 (e.g., it might get bigger if the user's bank account has more in 325 it). 327 The first attack cannot be mitigated by HTTP; the 0RT mechanism 328 itself needs some transport-layer means of scoping the usability of 329 the first packet on a connection so that it cannot be reused broadly. 330 For example, this might be by time, network location. 332 The second attack is more difficult to mitigate; scoping the 333 usability of the first packet helps, but does not completely prevent 334 the attack. If the replayed request is state-changing, the 335 application's retry detection should kick in and prevent information 336 leakage (since the response will likely contain an error, instead of 337 the desired information). 339 If it is not (e.g., a GET), the information being targeted is 340 vulnerable as long as both the first packet and the credentials in 341 the request (if any) are valid. 343 4. Possible Areas of Work 345 4.1. Updating HTTP's Requirements for Retries 347 The currently language in [RFC7230] about retries is vague about the 348 conditions under which a request can be retried, leading to 349 significant variance in implementation behaviour. For example, it's 350 been observed that many automated clients fail under circumstances 351 when browsers succeed, because they do not retry in the same way. 353 As a result, more carefully specifying the conditions under which a 354 request can be retried would be helpful. Such work would need to 355 take into account varying conditions, such as: 357 o Connection closes 359 o TCP RST 361 o Connection timeouts 363 o Whether or not any part of the response has been received 365 o Whether or not it is the first request on the connection 367 o Variance due to use of HTTP/2, TLS/1.3 and TCP Fast Open. 369 Furthermore, readers might mistake the language in RFC7230 as 370 guaranteeing that some requests (e.g., POST) are never automatically 371 retried; this should be clarified. 373 4.2. Protocol Extensions 375 A number of mechanisms have been mooted at various times, e.g.: 377 o Adding a header to automatically retried requests, to aid de- 378 duplication by servers 380 o Defining a request header to by added by intermediaries when they 381 have received a request in a way that could have been replayed 383 o Defining a status code to allow servers to indicate that the 384 request needs to be sent in a way that can't be replayed 386 4.3. Feedback to Transport 0RT Efforts 388 If the observations above hold, we should disabuse any notion that 389 HTTP method idempotency is a useful way to avoid problems with replay 390 attacks. Instead, we should encourage development of mechanisms to 391 mitigate the aspects of replay that are different than retries (e.g., 392 potential for DOS attacks). 394 5. Security Considerations 396 Yep. 398 6. Acknowledgements 400 Thanks to Brad Fitzpatrick, Leif Hedstrom, Subodh Iyengar, Amos 401 Jeffries, Patrick McManus, Matt Menke, Miroslav Ponec and Martin 402 Thomson for their input and feedback. 404 Thanks also to the participants in the 2016 HTTP Workshop for their 405 lively discussion of this topic. 407 7. References 409 7.1. Normative References 411 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 412 Requirement Levels", BCP 14, RFC 2119, 413 DOI 10.17487/RFC2119, March 1997, 414 . 416 [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 417 Protocol (HTTP/1.1): Message Syntax and Routing", 418 RFC 7230, DOI 10.17487/RFC7230, June 2014, 419 . 421 [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 422 Protocol (HTTP/1.1): Semantics and Content", RFC 7231, 423 DOI 10.17487/RFC7231, June 2014, 424 . 426 [RFC7413] Cheng, Y., Chu, J., Radhakrishnan, S., and A. Jain, "TCP 427 Fast Open", RFC 7413, DOI 10.17487/RFC7413, December 2014, 428 . 430 7.2. Informative References 432 [I-D.hamilton-early-deployment-quic] 433 Hamilton, R., Iyengar, J., Swett, I., and A. Wilk, "QUIC: 434 A UDP-Based Secure and Reliable Transport for HTTP/2", 435 draft-hamilton-early-deployment-quic-00 (work in 436 progress), July 2016. 438 [I-D.ietf-tls-tls13] 439 Rescorla, E., "The Transport Layer Security (TLS) Protocol 440 Version 1.3", draft-ietf-tls-tls13-14 (work in progress), 441 July 2016. 443 [RFC7540] Belshe, M., Peon, R., and M. Thomson, Ed., "Hypertext 444 Transfer Protocol Version 2 (HTTP/2)", RFC 7540, 445 DOI 10.17487/RFC7540, May 2015, 446 . 448 7.3. URIs 450 [1] https://www.iana.org/assignments/http-methods/http-methods.xhtml 452 [2] https://signalvnoise.com/archives2/google_web_accelerator_hey_not 453 _so_fast_an_alert_for_web_app_designers.php 455 [3] http://bazaar.launchpad.net/~squid/squid/trunk/view/head:/src/ 456 FwdState.cc#L594 458 [4] https://git-wip- 459 us.apache.org/repos/asf?p=trafficserver.git;a=blob;f=proxy/http/H 460 ttpTransact.cc;h=8a1f5364d47654b118296a07a2a95284f119d84b;hb=HEAD 461 #l6408 463 [5] https://git-wip- 464 us.apache.org/repos/asf?p=trafficserver.git;a=blob;f=proxy/http/ 465 HttpTransact.cc;hb=48d7b25ba8a8229b0471d37cdaa6ef24cc634bb0#l3634 467 [6] http://mxr.mozilla.org/mozilla- 468 release/source/netwerk/protocol/http/nsHttpTransaction.cpp#938 470 [7] http://mxr.mozilla.org/mozilla- 471 release/source/netwerk/protocol/http/nsHttpRequestHead.cpp#67 473 [8] https://www.fxsitecompat.com/en-CA/docs/2016/post-request-fails- 474 on-certain-sites-showing-connection-reset-page/ 476 [9] https://chromium.googlesource.com/chromium/src.git/+/master/net/ 477 http/http_network_transaction.cc#1657 479 Appendix A. When Clients Retry 481 In implementations, clients have been observed to retry requests in a 482 number of circumstances. 484 _Note: This section is intended to inform the discussion, not to be 485 published as a standard. If you have relevant information about 486 these or other implementations (open or closed), please get in 487 touch._ 489 A.1. Squid 491 Squid is a caching proxy server that retries requests that it 492 considers safe *or* idempotent, as long as there is not a request 493 body: 495 /// Whether we may try sending this request again after a failure. 496 bool 497 FwdState::checkRetriable() 498 { 499 // Optimize: A compliant proxy may retry PUTs, but Squid lacks the [rather 500 // complicated] code required to protect the PUT request body from being 501 // nibbled during the first try. Thus, Squid cannot retry some PUTs today. 502 if (request->body_pipe != NULL) 503 return false; 505 // RFC2616 9.1 Safe and Idempotent Methods 506 return (request->method.isHttpSafe() || request->method.isIdempotent()); 507 } 509 (source [6]) 511 Currently, it considers GET, HEAD, OPTIONS, REPORT, PROPFIND, SEARCH 512 and PRI to be safe, and GET, HEAD, PUT, DELETE, OPTIONS, TRACE, 513 PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, UNLOCK, and PRI to be 514 idempotent. 516 A.2. Traffic Server 518 Apache Traffic Server, a caching proxy server, ties retry-ability to 519 whether the request required a "tunnel" - i.e., forward to the next 520 server. This is indicated by "request_body_start", which is set when 521 a POST tunnel is used. 523 // bool HttpTransact::is_request_retryable 524 // 525 // If we started a POST/PUT tunnel then we can 526 // not retry failed requests 527 // 528 bool 529 HttpTransact::is_request_retryable(State *s) 530 { 531 if (s->hdr_info.request_body_start == true) { 532 return false; 533 } 535 if (s->state_machine->plugin_tunnel_type != HTTP_NO_PLUGIN_TUNNEL) { 536 // API can override 537 if (s->state_machine->plugin_tunnel_type == HTTP_PLUGIN_AS_SERVER && 538 s->api_info.retry_intercept_failures == true) { 539 // This used to be an == comparison, which made no sense. Changed 540 // to be an assignment, hoping the state is correct. 541 s->state_machine->plugin_tunnel_type = HTTP_NO_PLUGIN_TUNNEL; 542 } else { 543 return false; 544 } 545 } 547 return true; 548 } 550 (source [7]) 552 When connected to an origin server, Traffic Server attempts to retry 553 under a number of failure conditions: 555 ///////////////////////////////////////////////////////////////////////// 556 // Name : handle_response_from_server 557 // Description: response is from the origin server 558 // 559 // Details : 560 // 561 // response from the origin server. one of three things can happen now. 562 // if the response is bad, then we can either retry (by first downgrading 563 // the request, maybe making it non-keepalive, etc.), or we can give up. 564 // the latter case is handled by handle_server_connection_not_open and 565 // sends an error response back to the client. if the response is good 566 // handle_forward_server_connection_open is called. 567 // 568 // 569 // Possible Next States From Here: 570 // 571 ///////////////////////////////////////////////////////////////////////// 572 void 573 HttpTransact::handle_response_from_server(State *s) 574 { 576 [...] 578 switch (s->current.state) { 579 case CONNECTION_ALIVE: 580 DebugTxn("http_trans", "[hrfs] connection alive"); 581 SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_SUCCESS); 582 s->current.server->clear_connect_fail(); 583 handle_forward_server_connection_open(s); 584 break; 586 [...] 588 case OPEN_RAW_ERROR: 589 /* fall through */ 590 case CONNECTION_ERROR: 591 /* fall through */ 592 case STATE_UNDEFINED: 593 /* fall through */ 594 case INACTIVE_TIMEOUT: 595 // Set to generic I/O error if not already set specifically. 596 if (!s->current.server->had_connect_fail()) 597 s->current.server->set_connect_fail(EIO); 599 if (is_server_negative_cached(s)) { 600 max_connect_retries = s->txn_conf->connect_attempts_max_retries_dead_server; 601 } else { 602 // server not yet negative cached - use default number of retries 603 max_connect_retries = s->txn_conf->connect_attempts_max_retries; 604 } 605 if (s->pCongestionEntry != NULL) 606 max_connect_retries = s->pCongestionEntry->connect_retries(); 608 if (is_request_retryable(s) && s->current.attempts < max_connect_retries) { 610 (source [8]) 612 A.3. Firefox 614 Firefox is a Web browser that retries under the following conditions: 616 // if the connection was reset or closed before we wrote any part of the 617 // request or if we wrote the request but didn't receive any part of the 618 // response and the connection was being reused, then we can (and really 619 // should) assume that we wrote to a stale connection and we must therefore 620 // repeat the request over a new connection. 621 // 622 // We have decided to retry not only in case of the reused connections, but 623 // all safe methods(bug 1236277). 624 // 625 // NOTE: the conditions under which we will automatically retry the HTTP 626 // request have to be carefully selected to avoid duplication of the 627 // request from the point-of-view of the server. such duplication could 628 // have dire consequences including repeated purchases, etc. 629 // 630 // NOTE: because of the way SSL proxy CONNECT is implemented, it is 631 // possible that the transaction may have received data without having 632 // sent any data. for this reason, mSendData == FALSE does not imply 633 // mReceivedData == FALSE. (see bug 203057 for more info.) 634 // 636 [...] 638 if (!mReceivedData && 639 ((mRequestHead && mRequestHead->IsSafeMethod()) || 640 !reallySentData || connReused)) { 641 // if restarting fails, then we must proceed to close the pipe, 642 // which will notify the channel that the transaction failed. 644 (source [9]) 646 ... and it considers GET, HEAD, OPTIONS, TRACE, PROPFIND, REPORT, and 647 SEARCH to be safe: 649 bool 650 nsHttpRequestHead::IsSafeMethod() const 651 { 652 // This code will need to be extended for new safe methods, otherwise 653 // they'll default to "not safe". 654 if (IsGet() || IsHead() || IsOptions() || IsTrace()) { 655 return true; 656 } 658 if (mParsedMethod != kMethod_Custom) { 659 return false; 660 } 662 return (!strcmp(mMethod.get(), "PROPFIND") || 663 !strcmp(mMethod.get(), "REPORT") || 664 !strcmp(mMethod.get(), "SEARCH")); 665 } 667 (source [10]) 669 Note that "connReused" is tested; if a connection has been used 670 before, Firefox will retry _any_ request, safe or not. A recent 671 change attempted to remove this behaviour, but it caused 672 compatibility problems [11], and is being backed out. 674 A.4. Chromium 676 Chromium is a Web browser that appears to retry any request when a 677 connection is broken, as long as it's successfully used the 678 connection before, and hasn't received any response headers yet: 680 bool HttpNetworkTransaction::ShouldResendRequest() const { 681 bool connection_is_proven = stream_->IsConnectionReused(); 682 bool has_received_headers = GetResponseHeaders() != NULL; 684 // NOTE: we resend a request only if we reused a keep-alive connection. 685 // This automatically prevents an infinite resend loop because we'll run 686 // out of the cached keep-alive connections eventually. 687 if (connection_is_proven && !has_received_headers) 688 return true; 689 return false; 690 } 692 (source [12]) 694 Author's Address 696 Mark Nottingham 698 Email: mnot@mnot.net 699 URI: https://www.mnot.net/