Draft: draft-ietf-quic-http

Commentary: A client initiated GOAWAY contains a Push ID . The Push ID can be 2 ^ 62 - 1 if the client does n't care how many more pushes the server wants to initiate before graceful shutdown . It can be a smaller value if the client wishes to limit the pushes . 
 Did n't mean to close this . 
 you have n't approved and you had reservations before . Is this PR in a state you can live with ? 
 At the moment , the recommended way of gracefully shutting down an H3 connection is , according to : It is my understanding that the reason we suggest sending " the maximum value allowed by QUIC 's MAXSTREAMS " is because , unlike HTTP/2 , we can not send GOAWAY frame with an identifier value that is greater than any possible client - generated bidirectional stream ID . However , the downside is that the current text assumes tight integration with the QUIC stack that might be unnecessary - let the QUIC stack provide current MAXSTREAMS value , and also stop giving the client new credits . I am not against the status quo , but I think we might want to give practical advice . The minimum change can be to state " a server that is attempting to gracefully shutdown a connection SHOULD send an Initial GOAWAY frame with the last Stream ID set to the maximum value currently allowed by QUIC 's MAXSTREAMS or any value above that . " Such change would imply that sending 2 < sup62</sup-4 ( the maximum stream ID for a request stream ) assuming that the client would not send that much of requests on a single connection . Note that it is trivial for a server to make sure that the stream ID would not become that big - the server can always gracefully shutdown a connection well before the stream ID becomes that big . 
 PS . The alternative is to change the value carried by the GOAWAY frame from stream ID to " stream ID / 4 " ( i.e. the value we send using MAX_STREAMS ) , but IIRC we have rejected that approach , because it is another way of tightly coupling QUICv1 and HTTP/3 . 
 Smells editorial . do you want to suggest text ? 
 Thank you for the suggestion . Filed . PS . The label should be http , not transport . 
 In , points out that we can drop the recommendation to stop sending MAXSTREAMS once the server sends the first GOAWAY . Reading his comment , I now think that it might be better simply stop recommending the server sending GOAWAY with last Stream ID set to the current maximum , and instead recommend sending 2 < sup62</sup- 4 ( the theoretical maximum ) . Even if such a change makes this issue a design issue . Let me explain why . Quoting from , the status quo is : People might ( or would ) read that the second SHOULD is merely a recommendation , and consider that just sending GOAWAY with last Stream ID set to the current maximum is okay . The reality is that it is not . This is because there is no guarantee that the GOAWAY frame reaches the client before a MAXSTREAMS frame that the QUIC stack might generate reaches the client . Therefore , if the server is to send a GOAWAY frame with last Stream ID set to the current maximum , it MUST stop sending MAXSTREAMS that grant additional concurrency credit . However , as points out , such requirement is not necessary in terms of gracefully shutting down the connection . Just sending GOAWAY with last Stream ID set to 2 < sup62</sup-4 is sufficient . Considering that , I think just recommending 2 < sup62</sup-4 is the best way forward . 
 I agree with that . Stacks are n't obligated to offer any option for fine control over MAX_STREAMS , or any means of introspecting into the value . I would make another change though . As a suggestion , this text does n't need normative force . All assuming we go with the suggested outcome of . Adjust accordingly . 
 Thank you for the suggestions . I agree , I 've updated ( it 's based on master for the time being ) , I think it now aligns to what you have suggested . 
 The current spec only allows GOAWAY to be sent from the server to the client and contains only the last processed bidirectional stream ID . This makes sense for the vanilla HTTP use case , but may not play well with extensions . Unidirectional streams are a flexible extension point , and it may be useful for each endpoint to communicate to the peer the last processed unidirectional stream i d. An HTTP extension may also define a use for server initiated bidirectional streams , and may want the GOAWAY signal for these also . True if it 's an extension then the extension author can also extend GOAWAY to cover these cases or introduce another mechanism , but it would be a shame if many extensions had to cover the same ground . I suggest we allow GOAWAY to be sent by either endpoint , and that it should contain both the last processed peer initiated bidirectional and unidirectional stream . 
 I was compelled by  's discussion about this . It sounds like you are suggesting having two fields in the GOAWAY frame , one for each type . My thought was to mirror the way MAX_STREAMS works and have independent GOAWAY frames . 
 I think this argument makes sense , but this feels increasingly like a transport feature and not an HTTP feature . If you add a unidirectional limit , I 'd prefer a single frame , unless has a reason he thinks separate frames are likely to be useful in practice . 
 I do n't have a strong opinion here . For reference , the original issue about moving GOAWAY out of transport is For the separate frames topic : HTTP/3 currently lacks explanation about how GOAWAY works with MAXSTREAMS ( see ) . So my suggestion pre - empts that without much thought put into the final fix . Therefore it might be wrong . Some weak arguments : Before sending a GOAWAY , there is no explicit limit set by the server . The stream ID limit is implicit and real but more importantly , you do n't invoke the requirement . Imagination required on how we fix this language up for MAXSTREAMS . From  's problem statement description , I imagined GOAWAY to operate more like a drain state trigger . So having separate frames would allow the draining of unidirectional traffic and bidirectional traffic independently . E.g. a client declares " I 'm intending to leave soon , and I do n't want to accept new things from you ( pushes ) but I want the ability to create new requests , so please continue to give me bidi stream credits " . On a more practical level , a frame that includes both fields when only one type wants to be drained will likely end up with a set to max_int . So we 'd waste bytes to express " do n't do anything " . Modelling this by making fields optional adds complexity for little gain . Finally , we a separate GOAWAY for unidirectional streams opens the door for it to be an extension frame . However , I think this would be the wrong thing to do as it would make managing extensions very difficult . 
 The salient comment from for me is " I think that the GOAWAY frame needs to identify requests , not streams " Making GOAWAY bidirectional and cover unidirectional and bidirectional streams seems to run counter to that statement , which is why it was starting to feel more transport - y. But , I do n't feel that strongly about this , unless it becomes an implementation hassle of some sort . 
 I think the use case I 'm not sure is compelling is the one where we only want to drain one type of stream , but no the other . My model of GOAWAY is that it 's used for graceful shutdown , and I agree that could be useful on either side(moreso for non - HTTP applications , but maybe with WebTransport ? ) . I have a hard time thinking of an application where graceful shutdown requires continued creation of one of the stream types , but they may exist . 
 I think this is the pragmatic argument for making a single frame . You do n't want to make it easy for implementations to get into semi - draining states unintentionally . Sending GOAWAY with a limit of both forces that decision , which is good . 
 I had thought the H2 requirement was that after sending you will not accept or generate new streams , but I ca n't actually find that text in 7540 . If we 're concerned about being semi - draining , this seems like a restriction I 'd want to have as well . 
 I do n't think that we need to make special accommodations for possible future extensions , where the requirements for graceful shutdown are unpredictable . Strange . There 's an example in h3 . In order to answer a request , a server might create multiple push streams after the point that shutdown is initiated . The model for GOAWAY in h3 is based on the realization that the primary purpose of HTTP is to provide answers to requests . Stop the requests and you eventually run out of work . For the client , no signaling is required . For the server , it just has to have a way to block incoming requests . To  's point about identifying requests , I believe that it does ( if the text does n't support that , that 's just a bug ) . Extensions can change anything . But we ca n't really say what the graceful shutdown model would be without understanding the extension . Assuming that once shutdown is initiated there will no longer be any need for new streams is not safe . I can easily think of cases where new streams are needed to fulfill existing commitments . Any protocol that treats streams as messages with an 1 : N or N : M relationship between the message that initiates a transaction and the messages required to complete that transaction is open to this . Take a SQL or similar exchange where a transaction is opened , some queries and updates performed , and the transaction is committed or rolled back . A graceful shutdown might trigger rollback or it needs to allow for existing transactions to complete . If you want to allow transactions to complete , then you might have multiple streams created after the shutdown order is issued . And the SQL case is still simple , because it is still fundamentally transactional . If the protocol is truly bidirectional , with either peer initiating activity that might take time , then you need a more sophisticated shutdown process . The quanta used to measure what is accepted or rejected during shutdown might not be a discrete linear sequence as it is for simple transactional protocols ; it could be multi - dimensional . Indeed , the reason for this issue is the possibility that h3 with extensions could end up being multi - dimensional . The stuff people are doing with bidirectional transport use could end up like that , especially where it is intended to be multiplexed with h3 . Expecting things to line up around streams is probably reasonable , but when streams are used for multiple purposes , things get messy . You need to be identifying the unit . We get to use streams for GOAWAY because client - initiated bidirectional streams are exclusively used for requests , but we use stream identifiers only as means of identifying requests there ( again , if the text implies otherwise , we need to fix that ) . So my view is that GOAWAY is good enough for shutdown of requests . But that is all we can realistically provide for at this layer . If an extension needs to be shutdown gracefully , then the extension that adds that thing will need to provide signaling in support of that shutdown . Practically , that means multiple frames involved in shutdown , but that 's not terrible , just wait for all shutdown - y things to complete shutdown before tearing down the connection . 
 I think I 'm fine with GOAWAY as is , but PUSH is never a required feature , it 's a server - side optimization / pessimization . 
 This was n't making a value - judgment of server push , just a note that there are cases that do n't fit the model proposed . 
 To clarify , I was trying to note push is optional , and not required . In practice , I do n't think PUSH would work in this case , at least in browsers . If the client receives a GOAWAY , then I would n't expect any new requests to go to that connection , including those which may be matched with results from the push cache . 
 That 's true , but URLs may have already been promised ( not yet pushed ) and there may already be requests waiting to rendezvous with the pushed stream .  ? 
 That 's also a detail of one particular push implementation , not an inherent way that push works . I think the  implementation in WinInet would still work , because the push cache is at the level of a request group rather than an individual connection . ( Somewhat moot for deployment use , but existence proof that there 's more than one possible implementation of that . ) 
 I currently see 4 options : 1 ) Do nothing and assume there are some implementation specific edge cases that are going to go fairly sideways , but they 're unlikely to cause user visible issues . 2 ) Move GOAWAY to transport and have it include uni and bidi . 3 ) Add a  push i d to the existing GOAWAY 4 ) Add a new frame for push . I 'm ok with 1 and 2 , and would be hesitant to pursue 3 or 4 . 
 I prefer option 1 . I do nt see what 3 provides . I think we could achieve the same by adding text that says something like " the server commits to resolving all existing promises sent on streams up to and including the stream ID indicated in GOAWAY . Pushes may be cancelled or reset as normal " . My 2p . GOAWAY is starting to sound like more of a STOP_CREATING ( you have credit but it 's a waste to use it in the current state ) and PROCESSED ( endpoint processed all entities up to ID , it is safe to retry higher IDs on a different connection ) . 
 besides the theoretical interest of how GOAWAY works with extensions , do you have any HTTP/3 extension in mind where the current GOAWAY breaks badly ? And if so , would it be feasible to add another  frame for that use case ? ie : Can we just not fix this , or make some editorial tweaks ? 
 The extension we are developing allows complete bidirectionality to HTTP , so a server can initiate a request / response to the client . The H2 mapping of this extension uses a client - sent GOAWAY to clue the server in to stop doing this . I do n't know that missing this will break - badly ; it probably depends on what application developers do with the bidirectionality . It 's asymmetric with H2 , seemingly because we think we got it wrong in H2 and are trying to correct it ? I 'm trying to say there is some value in keeping it symmetric . I think Lucas correctly identified the semantics of what GOAWAY is - STOP_CREATING and PROCESSED . As mentioned in the original issue , anyone writing an extension can also extend the GOAWAY frame under that extension that does what I proposed , so doing nothing is of course viable . 
 Discussed in London ; we should mimic whatever H2 does , and there 's some uncertainty in the room about what a client - sent GOAWAY is intended to mean . H2 GOAWAY says : So HTTP/2 does define it in terms of streams , and a server upon receipt of a GOAWAY frame MUST NOT open more streams , which would include push . The other side probably ca n't police you , however , because they ca n't reliably know that the opening of the stream was n't already in flight ; they 'll just ignore it . 
 It was mentioned in Montreal that the HTTP WG was asked about this . Was the response reflected back in this ticket ? apologies , this one completely popped off my stack 
 To summarize the discussion on the HTTP list : H2 GOAWAY is symmetric A GOAWAY sent by the client will prevent any pushes higher than the last - stream - id in the GOAWAY  feels like this behavior is wrong , and it should n't be carried over into H3 . Do we need to build consensus from the HTTP working group that it is OK to deviate from H2 semantics in H3 , like we are now planning to do for priorities ? 
 While this is true , we have - as a working group - previously discussed the principles underlying this and agreed that the unit we should care about is the request . However , I agree that this is something we should discuss at the HTTP working group . Where we can each put on a different set of hats . 
 What 's ill defined is whether the pushes that come on a request are part of the request or not . I think a reasonable argument can be made for either interpretation . 
 A different use case came up : Consider streaming a ( potentially infinite ) live video as a sequence of pushes . How does a client signal its intent to close this connection , and stop the server from pushing more video segments ? The client can send a STOPSENDING frame on the request stream which is receiving the PUSHPROMISEs , but this may result in less than graceful termination of that stream . 
 In this case what do you advertise  as ? By limiting the value and not incrementing it , you can cause the server to be unable to drive the connection , and allow the client to hit its idle timeout . 
 Yeah , limiting credit via  is one way , but I still prefer the explicit signal from GOAWAY - it 's like immediately zeroing out the credit . 
 Agree . This is like writing a cheque but asking the other side not to cash it ( out of band ) to avoid it bouncing and causing pain all round . 
 Even with a client sent GOAWAY , you 'd receive a few more pushes within the next RTT . If you managed MAXPUSHID like flow control and only gave out enough extra for the time window you wanted to shut down within(ie : 1 - 2RTTs ) , I believe this achieves the desired behavior ? If that time window is < 1RTT , then your only real option is CONNECTION_CLOSE ? 
 I think it 's more about challenging the assumption that stopping sending requests ( or push credits ) is the same as explicitly signaling your intent to close the connection . If the endpoint knows it will shutdown , it signals the peer , and the peer can take actions in response to ensure the close is graceful . 
 Can you clarify what your current proposal is ? Is it to move GOAWAY to transport or keep it in H3 and make it bidi ? 
 Discussed in Cupertino : Clients can send GOAWAY . Add transition considerations to talk about relaying GOAWAY from an H2 to H3 connection / vice versa . We would like the client - sent GOAWAY to carry a Push ID . There is still disagreement over what the precise semantics of that are . to write a PR to provoke argument . 
 The semantics of an identifier in the server - to - client GOAWAY are twofold . The identifier clearly identifies requests that were not " processed " , which allows the client to retry those requests . The identifier also identifies which of those requests can be cleaned up expeditiously . My view is that the former is significantly more important . Enabling clean retry is one of the best features of h2 . For pushes , the need to signal whether the data was " processed " is moot , because only safe requests can be pushed . So most of this comes down to what optimizations are enabled by the explicit  ID . In h2 , requests are automatically " cancelled " , though the bits are still retransmitted by TCP if the connection is kept alive . A client is n't required to reset or finalize any associated streams if the requests were not complete , but the transport will automatically repair lost segments . In h3 , the same applies , though there is an optimization that might be enabled . The transport layer can be told not to retransmit data for " cancelled " streams if packets are lost . This does n't require explicit RESETSTREAM or STOPSENDING frames , reprioritization might be enough . Depending on the transport implementations , endpoints might need to use RESET_STREAM to ensure that transport stacks are aware of the need to suppress retransmissions . From that perspective , an explicit  ID would enable new capabilities in terms of suppression of unnecessary retransmission . For example , say that there is an open request that is receiving associated pushes for data that arrives on a fixed cadence . Say that a client wants to move to a different connection ( because it was told with    , for instance ) . The client might initiate a request starting at a particular time on a new connection . When the client cancels this connection , there might be a number of pushes in flight . If the client can precisely identify the push that immediately precedes the request it initiates on the new connection , the server can identify which of these pushes need to be fully delivered , and which can be abandoned . However , this optimization really only works if the client can make this identification precisely . If there are multiple requests in flight on the connection , the client might not be able to identify or predict the Push ID that will be used for the next push in the sequence . The server might avoid this by providing promises well ahead ( 1RTT ) of the actual pushes so that the client does n't need to guess , but that might not be possible in the general case . This also requires that  IDs are used strictly sequentially with respect to the global clock . This does n't guarantee clean separation even if  IDs monotonically increase for each resource . For instance , if two resources were providing the same sort of pushes , response 0 might promise  ID 10 for time=44 , but response 4 might promise  ID 9 that corresponds to time=45 . That makes it difficult for a client to make a clean cut with a single value . This also does n't interact well with a model where the answering of a request depends on receiving a set of pushes . If you have a resource that produces a continuous set of pushes on the same connection as a resource that ( ideally ) produces a fixed number of pushes ( see also Prefer - Push ) , then the cut for the continuous resource might be clean , but it might split the pushes for the resource with a fixed set of associated pushes . Of course , all of these arguments could easily be countered by saying that this is just an optimization , but given that it 's an optimization we do n't have for h2 ( because TCP ) , I think that I 'd prefer not to provide the capability . Finer - grained signals might be valuable : such as the idea that individual requests might have separate budgets for push that can be progressively expanded by clients as they are ready for more . That seems like something worth considering for future versions of this protocol . 
 makes a subtle but major change to the semantics , and I think we need to carefully consider whether that 's something we want . We were conflating these two models during interim discussion , and I do n't think we 're clear on our direction yet . Instead of " Clients MUST NOT send new requests on the connection after receiving GOAWAY " , we now have " Endpoints MUST NOT initiate new requests or pushes on the connection with an identifier greater than or equal to the smallest identifier received in a GOAWAY frame . " In other words , GOAWAY ( ) has changed from meaning " I 'll service your in - flight requests , but do n't make any new ones " to a no - op , since the client could n't have initiated such a request anyway . I understand that this might be a desirable pattern in the server - to - client direction , where certain use patterns consider the set of pushes part of the fulfillment of the client 's request , and the client actively wants the server to continue initiating pushes until the request is complete . This does n't seem a wise semantic to bring to the client - to - server direction . In HTTP/2 , the recipient of the GOAWAY was prohibited from initiating any more activity ( requests or pushes ) regardless of the value in the frame . My first preference is to preserve that , and actually have the same semantics as HTTP/2 . 
 I agree with that 's a useful semantic we should preserve in HTTP/3 . 
 I think  articulated a point I was trying to make on Slack but in a much better way . +1 . 
 Ah , I was trying to get the behavior was after for pushes ( eg : let the server keep pushing if it wants to ) , and did n't intend to allow the client to send more requests after receiving a GOAWAY -- that does n't work . But it sounds like we 'd prefer to keep the push behavior symmetric with h2 ( no more pushes after GOAWAY receipt ) than introduce a new push semantic where the client can allow pushes to continue even after signaling its intent to close . This is more along the lines that was advocating for - where the intent to close and how pushes are wound down are completely decoupled frames . The discussion on slack I thought was different - it was about what the sender of a GOAWAY should do with new incoming streams . I intended the PR to reflect that the sender of a GOAWAY should continue allowing requests or pushes with ID 's smaller than the sent GOAWAY value . Do we agree this is the right behavior ? 
 The sender of GOAWAY needs to continue accepting incoming streams up to the indicated ID , yes . If we decide the other semantic is useful , it 's easy enough to define another frame ( SOFTGOAWAY , INCONCLUSION , etc . ) in - spec or as an extension that simply hints to the other side that they should start cleaning up , but does n't fully prohibit new streams . 
 It sounds like LAST_ORDERS would be the classic optional - to - understand extension -- " I 'd like you to wrap up gracefully now , so it does n't hurt when I forcibly close in a few seconds . " Can we agree on ( and update the PR to ) keeping H2 semantics of " no new requests / pushes " after receipt of GOAWAY in either direction , and leave that for another day ? I 've created for this direction . 
 A few editorial suggestions , but I can live with this . ( I still think that signaling the push ID is n't entirely necessary , but I can see from this text how it might be used . And I recognize that avoid asymmetry makes the marginal value of including the push ID easier to accept.)This seems fine , though I 'm curious what the intent is if a GOAWAY is sent with the incorrect stream type ?
Paragraph (version A):
Multiplexing of requests is performed using the QUIC stream
abstraction, described in Section 2 of QUIC-TRANSPORT.  Each request
and response consumes a single QUIC stream.  Streams are independent
of each other, so one stream that is blocked or suffers packet loss
does not prevent progress on other streams.
Paragraph (version A):
The smallest unit of communication on a stream in HTTP/3,
consisting of a header and a variable-length sequence of octets
structured according to the frame type.  Protocol elements called
"frames" exist in both this document and QUIC-TRANSPORT.  Where
frames from QUIC-TRANSPORT are referenced, the frame name will be
prefaced with "QUIC."  For example, "QUIC CONNECTION_CLOSE
frames."  References without this preface refer to frames defined
in frames.
Paragraph (version A):
the message header (see RFC7230, Section 3.2), sent as a single
HEADERS frame (see frame-headers),
Paragraph (version A):
A server MAY send one or more PUSH_PROMISE frames (see frame-push-
promise) before, after, or interleaved with the frames of a response
message.  These PUSH_PROMISE frames are not part of the response; see
server-push for more details.
Paragraph (version B):
A server MAY send one or more PUSH_PROMISE (see frame-push-promise)
or DUPLICATE_PUSH (see frame-duplicate-push) frames before, after, or
interleaved with the frames of a response message.  These
PUSH_PROMISE and DUPLICATE_PUSH frames are not part of the response;
see server-push for more details.
Paragraph (version A):
A response MAY consist of multiple messages when and only when one or
more informational responses (1xx; see RFC7231, Section 6.2) precede
a final response to the same request.  Non-final responses do not
contain a payload body or trailers.
Paragraph (version B):
If an endpoint receives an invalid sequence of frames on either a
request or a push stream, it MUST respond with a connection error of
type H3_FRAME_UNEXPECTED (errors).  In particular, a DATA frame
before any HEADERS frame, or a HEADERS or DATA frame after the
trailing HEADERS frame is considered invalid.
Paragraph (version A):
When a stream is closed, this indicates the end of an HTTP message.
Because some messages are large or unbounded, endpoints SHOULD begin
processing partial HTTP messages once enough of the message has been
received to make progress.  If a client stream terminates without
enough of the HTTP message to provide a complete response, the server
SHOULD abort its response with the error code
HTTP_REQUEST_INCOMPLETE.
Paragraph (version A):
A server can send a complete response prior to the client sending an
entire request if the response does not depend on any portion of the
request that has not been sent and received.  When this is true, a
server MAY abort reading the request stream with error code
HTTP_EARLY_RESPONSE, send a complete response, and cleanly close the
sending part of the stream.  Clients MUST NOT discard complete
responses as a result of having their request terminated abruptly,
though clients can always discard responses at their discretion for
other reasons.
Paragraph (version B):
A server can send a complete response prior to the client sending an
entire request if the response does not depend on any portion of the
request that has not been sent and received.  When the server does
not need to receive the remainder of the request, it MAY abort
reading the request stream, send a complete response, and cleanly
close the sending part of the stream.  The error code H3_NO_ERROR
SHOULD be used when requesting that the client stop sending on the
request stream.  Clients MUST NOT discard complete responses as a
result of having their request terminated abruptly, though clients
can always discard responses at their discretion for other reasons.
If the server sends a partial or complete response but does not abort
reading, clients SHOULD continue sending the body of the request and
close the stream normally.
Paragraph (version B):
To allow for better compression efficiency, the cookie header field
RFC6265 MAY be split into separate header fields, each with one or
more cookie-pairs, before compression.  If a decompressed header list
contains multiple cookie header fields, these MUST be concatenated
before being passed into a non-HTTP/2, non-HTTP/3 context, as
described in Section 8.1.2.5 of HTTP2.
Paragraph (version A):
Clients can cancel requests by resetting and aborting the request
stream with an error code of HTTP_REQUEST_CANCELLED (http-error-
codes).  When the client aborts reading a response, it indicates that
this response is no longer of interest.  Implementations SHOULD
cancel requests by abruptly terminating any directions of a stream
that are still open.
Paragraph (version A):
When a client resets a request with the error code
HTTP_REQUEST_CANCELLED, a server MAY abruptly terminate the response
using the error code HTTP_REQUEST_REJECTED if no processing was
performed.  Clients MUST NOT use the HTTP_REQUEST_REJECTED error
code, except when a server has requested closure of the request
stream with this error code.
Paragraph (version A):
The pseudo-method CONNECT (RFC7231, Section 4.3.6) is primarily used
with HTTP proxies to establish a TLS session with an origin server
for the purposes of interacting with "https" resources.  In HTTP/1.x,
CONNECT is used to convert an entire HTTP connection into a tunnel to
a remote host.  In HTTP/2, the CONNECT method is used to establish a
tunnel over a single HTTP/2 stream to a remote host for similar
purposes.
Paragraph (version A):
A proxy that supports CONNECT establishes a TCP connection (RFC0793)
to the server identified in the ":authority" pseudo-header field.
Once this connection is successfully established, the proxy sends a
HEADERS frame containing a 2xx series status code to the client, as
defined in RFC7231, Section 4.3.6.
Paragraph (version B):
The pseudo-method CONNECT (Section 4.3.6 of RFC7231) is primarily
used with HTTP proxies to establish a TLS session with an origin
server for the purposes of interacting with "https" resources.  In
HTTP/1.x, CONNECT is used to convert an entire HTTP connection into a
tunnel to a remote host.  In HTTP/2, the CONNECT method is used to
establish a tunnel over a single HTTP/2 stream to a remote host for
similar purposes.
Paragraph (version B):
A CONNECT request in HTTP/3 functions in the same manner as in
HTTP/2.  The request MUST be formatted as described in Section 8.3 of
HTTP2.  A CONNECT request that does not conform to these restrictions
is malformed (see malformed).  The request stream MUST NOT be closed
at the end of the request.
Paragraph (version A):
A TCP connection error is signaled by abruptly terminating the
stream.  A proxy treats any error in the TCP connection, which
includes receiving a TCP segment with the RST bit set, as a stream
error of type HTTP_CONNECT_ERROR (http-error-codes).
Correspondingly, if a proxy detects an error with the stream or the
QUIC connection, it MUST close the TCP connection.  If the underlying
TCP implementation permits it, the proxy SHOULD send a TCP segment
with the RST bit set.
Paragraph (version A):
The header of the request message is carried by a PUSH_PROMISE frame
(see frame-push-promise) on the request stream which generated the
push.  This allows the server push to be associated with a client
request.  Promised requests MUST conform to the requirements in
Section 8.2 of HTTP2.
Paragraph (version A):
The same server push can be associated with additional client
requests using a DUPLICATE_PUSH frame (see frame-duplicate-push).
Paragraph (version B):
The header of the request message is carried by a PUSH_PROMISE frame
(see frame-push-promise) on the request stream which generated the
push.  Promised requests MUST conform to the requirements in
Section 8.2 of HTTP2.
Paragraph (version B):
Each pushed response is associated with one or more client requests.
The push is associated with the request stream on which the
PUSH_PROMISE frame was received.  The same server push can be
associated with additional client requests using a DUPLICATE_PUSH
frame (see frame-duplicate-push).  These associations do not affect
the operation of the protocol, but MAY be used by user agents when
deciding how to use pushed resources.
Paragraph (version A):
If a promised server push is not needed by the client, the client
SHOULD send a CANCEL_PUSH frame.  If the push stream is already open
or opens after sending the CANCEL_PUSH frame, the client can abort
reading the stream with an error code of HTTP_REQUEST_CANCELLED.
This asks the server not to transfer additional data and indicates
that it will be discarded upon receipt.
Paragraph (version A):
Even when a connection is not idle, either endpoint can decide to
stop using the connection and let the connection close gracefully.
Since clients drive request generation, clients perform a connection
shutdown by not sending additional requests on the connection;
responses and pushed responses associated to previous requests will
continue to completion.  Servers perform the same function by
communicating with clients.
Paragraph (version A):
Servers initiate the shutdown of a connection by sending a GOAWAY
frame (frame-goaway).  The GOAWAY frame indicates that client-
initiated requests on lower stream IDs were or might be processed in
this connection, while requests on the indicated stream ID and
greater were rejected.  This enables client and server to agree on
which requests were accepted prior to the connection shutdown.  This
identifier MAY be zero if no requests were processed.  Servers SHOULD
NOT permit additional QUIC streams after sending a GOAWAY frame.
Paragraph (version A):
Clients MUST NOT send new requests on the connection after receiving
GOAWAY; a new connection MAY be established to send additional
requests.
Paragraph (version A):
Some requests might already be in transit.  If the client has already
sent requests on streams with a Stream ID greater than or equal to
that indicated in the GOAWAY frame, those requests will not be
processed and MAY be retried by the client on a different connection.
The client MAY cancel these requests.  It is RECOMMENDED that the
server explicitly reject such requests (see request-cancellation) in
order to clean up transport state for the affected streams.
Paragraph (version A):
Requests on Stream IDs less than the Stream ID in the GOAWAY frame
might have been processed; their status cannot be known until a
response is received, the stream is reset individually, or the
connection terminates.  Servers MAY reject individual requests on
streams below the indicated ID if these requests were not processed.
Paragraph (version B):
The information in the GOAWAY frame enables a client and server to
agree on which requests or pushes were accepted prior to the
connection shutdown.  Upon sending a GOAWAY frame, the endpoint
SHOULD explicitly cancel (see request-cancellation and frame-cancel-
push) any requests or pushes that have identifiers greater than or
equal to that indicated, in order to clean up transport state for the
affected streams.  The endpoint SHOULD continue to do so as more
requests or pushes arrive.
Paragraph (version B):
Endpoints MUST NOT initiate new requests or promise new pushes on the
connection after receipt of a GOAWAY frame from the peer.  Clients
MAY establish a new connection to send additional requests.
Paragraph (version B):
Upon receipt of a GOAWAY frame, if the client has already sent
requests with a Stream ID greater than or equal to the identifier
received in a GOAWAY frame, those requests will not be processed.
Clients can safely retry unprocessed requests on a different
connection.
Paragraph (version B):
Servers MAY reject individual requests on streams below the
indicated ID if these requests were not processed.
Paragraph (version B):
If a server receives a GOAWAY frame after having promised pushes
with a Push ID greater than or equal to the identifier received in
a GOAWAY frame, those pushes will not be accepted.
Paragraph (version A):
A client that is unable to retry requests loses all requests that are
in flight when the server closes the connection.  A server MAY send
multiple GOAWAY frames indicating different stream IDs, but MUST NOT
increase the value they send in the last Stream ID, since clients
might already have retried unprocessed requests on another
connection.  A server that is attempting to gracefully shut down a
connection SHOULD send an initial GOAWAY frame with the last Stream
ID set to the maximum value allowed by QUIC's MAX_STREAMS and SHOULD
NOT increase the MAX_STREAMS limit thereafter.  This signals to the
client that a shutdown is imminent and that initiating further
requests is prohibited.  After allowing time for any in-flight
requests (at least one round-trip time), the server MAY send another
GOAWAY frame with an updated last Stream ID.  This ensures that a
connection can be cleanly shut down without losing requests.
Paragraph (version A):
Once all accepted requests have been processed, the server can permit
the connection to become idle, or MAY initiate an immediate closure
of the connection.  An endpoint that completes a graceful shutdown
SHOULD use the HTTP_NO_ERROR code when closing the connection.
Paragraph (version B):
A client that is unable to retry requests loses all requests that are
in flight when the server closes the connection.  An endpoint MAY
send multiple GOAWAY frames indicating different identifiers, but
MUST NOT increase the identifier value they send, since clients might
already have retried unprocessed requests on another connection.
Paragraph (version B):
An endpoint that is attempting to gracefully shut down a connection
can send a GOAWAY frame with a value set to the maximum possible
value (2^62-4 for servers, 2^62-1 for clients).  This ensures that
the peer stops creating new requests or pushes.  After allowing time
for any in-flight requests or pushes to arrive, the endpoint can send
another GOAWAY frame indicating which requests or pushes it might
accept before the end of the connection.  This ensures that a
connection can be cleanly shut down without losing requests.
Paragraph (version B):
Even when a GOAWAY indicates that a given request or push will not be
processed or accepted upon receipt, the underlying transport
resources still exist.  The endpoint that initiated these requests
can cancel them to clean up transport state.
Paragraph (version B):
Once all accepted requests and pushes have been processed, the
endpoint can permit the connection to become idle, or MAY initiate an
immediate closure of the connection.  An endpoint that completes a
graceful shutdown SHOULD use the HTTP_NO_ERROR code when closing the
connection.
Paragraph (version A):
Before closing the connection, a GOAWAY MAY be sent to allow the
client to retry some requests.  Including the GOAWAY frame in the
same packet as the QUIC CONNECTION_CLOSE frame improves the chances
of the frame being received by clients.
Paragraph (version B):
Before closing the connection, a GOAWAY frame MAY be sent to allow
the client to retry some requests.  Including the GOAWAY frame in the
same packet as the QUIC CONNECTION_CLOSE frame improves the chances
of the frame being received by clients.
Paragraph (version A):
All client-initiated bidirectional streams are used for HTTP requests
and responses.  A bidirectional stream ensures that the response can
be readily correlated with the request.  This means that the client's
first request occurs on QUIC stream 0, with subsequent requests on
stream 4, 8, and so on.  In order to permit these streams to open, an
HTTP/3 server SHOULD configure non-zero minimum values for the number
of permitted streams and the initial stream flow control window.  It
is RECOMMENDED that at least 100 requests be permitted at a time, so
as to not unnecessarily limit parallelism.
Paragraph (version B):
All client-initiated bidirectional streams are used for HTTP requests
and responses.  A bidirectional stream ensures that the response can
be readily correlated with the request.  This means that the client's
first request occurs on QUIC stream 0, with subsequent requests on
stream 4, 8, and so on.  In order to permit these streams to open, an
HTTP/3 server SHOULD configure non-zero minimum values for the number
of permitted streams and the initial stream flow control window.  So
as to not unnecessarily limit parallelism, at least 100 requests
SHOULD be permitted at a time.
Paragraph (version A):
If the stream header indicates a stream type which is not supported
by the recipient, the remainder of the stream cannot be consumed as
the semantics are unknown.  Recipients of unknown stream types MAY
abort reading of the stream with an error code of
HTTP_STREAM_CREATION_ERROR, but MUST NOT consider such streams to be
a connection error of any kind.
Paragraph (version A):
Each frame's payload MUST contain exactly the fields identified in
its description.  A frame payload that contains additional bytes
after the identified fields or a frame payload that terminates before
the end of the identified fields MUST be treated as a connection
error of type HTTP_FRAME_ERROR.
Paragraph (version A):
When a stream terminates cleanly, if the last frame on the stream was
truncated, this MUST be treated as a connection error (errors) of
type HTTP_FRAME_ERROR.  Streams which terminate abruptly may be reset
at any point in a frame.
Paragraph (version B):
If the client receives a CANCEL_PUSH frame, that frame might identify
a Push ID that has not yet been mentioned by a PUSH_PROMISE frame due
to reordering.  If a server receives a CANCEL_PUSH frame for a Push
ID that has not yet been mentioned by a PUSH_PROMISE frame, this MUST
be treated as a connection error of type H3_ID_ERROR.
Paragraph (version A):
A server MAY accept 0-RTT and subsequently provide different settings
in its SETTINGS frame.  If 0-RTT data is accepted by the server, its
SETTINGS frame MUST NOT reduce any limits or alter any values that
might be violated by the client with its 0-RTT data.  The server MUST
include all settings which differ from their default values.  If a
server accepts 0-RTT, but then sends a SETTINGS frame which reduces a
setting the client understands or omits a value that was previously
specified to have a non-default value, this MUST be treated as a
connection error of type HTTP_SETTINGS_ERROR.
Paragraph (version B):
A server MUST NOT use a Push ID that is larger than the client has
provided in a MAX_PUSH_ID frame (frame-max-push-id).  A client MUST
treat receipt of a PUSH_PROMISE frame that contains a larger Push ID
than the client has advertised as a connection error of H3_ID_ERROR.
Paragraph (version B):
A server MUST NOT use the same Push ID in multiple PUSH_PROMISE
frames.  A client MUST treat receipt of a Push ID which has already
been promised as a connection error of type H3_ID_ERROR.
Paragraph (version A):
The GOAWAY frame (type=0x7) is used to initiate graceful shutdown of
a connection by a server.  GOAWAY allows a server to stop accepting
new requests while still finishing processing of previously received
requests.  This enables administrative actions, like server
maintenance.  GOAWAY by itself does not close a connection.
Paragraph (version A):
The GOAWAY frame is always sent on the control stream.  It carries a
QUIC Stream ID for a client-initiated bidirectional stream encoded as
a variable-length integer.  A client MUST treat receipt of a GOAWAY
frame containing a Stream ID of any other type as a connection error
of type HTTP_ID_ERROR.
Paragraph (version B):
The GOAWAY frame (type=0x7) is used to initiate graceful shutdown of
a connection by either endpoint.  GOAWAY allows an endpoint to stop
accepting new requests or pushes while still finishing processing of
previously received requests and pushes.  This enables administrative
actions, like server maintenance.  GOAWAY by itself does not close a
connection.
Paragraph (version B):
The GOAWAY frame is always sent on the control stream.  In the server
to client direction, it carries a QUIC Stream ID for a client-
initiated bidirectional stream encoded as a variable-length integer.
A client MUST treat receipt of a GOAWAY frame containing a Stream ID
of any other type as a connection error of type H3_ID_ERROR.
Paragraph (version B):
In the client to server direction, the GOAWAY frame carries a Push ID
encoded as a variable-length integer.
Paragraph (version B):
The DUPLICATE_PUSH frame is always sent on a request stream.  Receipt
of a DUPLICATE_PUSH frame on any other stream MUST be treated as a
connection error of type H3_FRAME_UNEXPECTED.
Paragraph (version B):
A client MUST NOT send a DUPLICATE_PUSH frame.  A server MUST treat
the receipt of a DUPLICATE_PUSH frame as a connection error of type
H3_FRAME_UNEXPECTED.
Paragraph (version B):
The DUPLICATE_PUSH frame carries a single variable-length integer
that identifies the Push ID of a resource that the server has
previously promised (see frame-push-promise), though that promise
might not be received before this frame.  A server MUST NOT use a
Push ID that is larger than the client has provided in a MAX_PUSH_ID
frame (frame-max-push-id).  A client MUST treat receipt of a
DUPLICATE_PUSH that contains a larger Push ID than the client has
advertised as a connection error of type H3_ID_ERROR.
Paragraph (version A):
QUIC allows the application to abruptly terminate (reset) individual
streams or the entire connection when an error is encountered.  These
are referred to as "stream errors" or "connection errors" and are
described in more detail in QUIC-TRANSPORT.  An endpoint MAY choose
to treat a stream error as a connection error.
Paragraph (version A):
The remainder of the client's request is not needed to produce a
response.  For use in STOP_SENDING only.
Paragraph (version A):
Extensions that could change the semantics of existing protocol
components MUST be negotiated before being used.  For example, an
extension that changes the layout of the HEADERS frame cannot be used
until the peer has given a positive signal that this is acceptable.
In this case, it could also be necessary to coordinate when the
revised layout comes into effect.
Paragraph (version A):
A reference to a specification that includes a description of the
frame layout and its semantics, including any parts of the frame
that are conditionally present.
Paragraph (version A):
This document establishes a registry for HTTP/3 settings.  The
"HTTP/3 Settings" registry governs a 62-bit space.  This space is
split into three spaces that are governed by different policies.
Values between "0x00" and "0x3f" (in hexadecimal) are assigned via
the Standards Action or IESG Review policies RFC8126.  Values from
"0x40" to "0x3fff" operate on the Specification Required policy
RFC8126.  All other values are assigned to Private Use RFC8126.  The
designated experts are the same as those for the "HTTP/2 Settings"
registry defined in HTTP2.
Paragraph (version B):
Specifications of frame types MUST include a description of the frame
layout and its semantics, including any parts of the frame that are
conditionally present.
Paragraph (version B):
The entries in iana-frame-table are registered by this document.
Paragraph (version A):
An optional reference to a specification that describes the use of
the setting.
Paragraph (version A):
This document establishes a registry for HTTP/3 error codes.  The
"HTTP/3 Error Code" registry manages a 62-bit space.  The "HTTP/3
Error Code" registry operates under the "Expert Review" policy
RFC8126.
Paragraph (version A):
The 62-bit error code value.
Paragraph (version A):
A brief description of the error code semantics, longer if no
detailed specification is provided.
Paragraph (version A):
An optional reference for a specification that defines the error
code.
Paragraph (version A):
A reference to a specification that includes a description of the
stream type, including the layout semantics of its payload.
Paragraph (version B):
The entries in iana-setting-table are registered by this document.