<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.6.26 (Ruby 2.6.4) -->
<?rfc-ext html-pretty-print="prettyprint https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"?>
<rfc xmlns:x="http://purl.org/net/xml2rfc/ext"
      category="std"
      consensus="true"
      docName="draft-ietf-httpbis-resumable-upload-01"
      ipr="trust200902"
      sortRefs="true"
      symRefs="true"
      tocInclude="true">
   <x:feedback template="mailto:ietf-http-wg@w3.org?subject={docname},%20%22{section}%22\&amp;amp;body=%3c{ref}%3e:"/>
   <front>
      <title abbrev="Resumable Uploads">Resumable Uploads for HTTP</title>
      <author fullname="Marius Kleidl"
               initials="M."
               role="editor"
               surname="Kleidl">
         <organization>Transloadit Ltd</organization>
         <address>
            <email>marius@transloadit.com</email>
         </address>
      </author>
      <author fullname="Guoye Zhang"
               initials="G."
               role="editor"
               surname="Zhang">
         <organization>Apple Inc.</organization>
         <address>
            <email>guoye_zhang@apple.com</email>
         </address>
      </author>
      <author fullname="Lucas Pardue"
               initials="L."
               role="editor"
               surname="Pardue">
         <organization>Cloudflare</organization>
         <address>
            <email>lucaspardue.24.7@gmail.com</email>
         </address>
      </author>
      <date day="02" month="March" year="2023"/>
      <area>ART</area>
      <workgroup>HTTP</workgroup>
      <keyword>Internet-Draft</keyword>
      <abstract>
         <t>HTTP clients often encounter interrupted data transfers as a result of canceled requests or dropped connections. Prior to interruption, part of a representation may have been exchanged. To complete the data transfer of the entire representation, it is often desirable to issue subsequent requests that transfer only the remainder of the representation. HTTP range requests support this concept of resumable downloads from server to client. This document describes a mechanism that supports resumable uploads from client to server using HTTP.</t>
      </abstract>
      <note removeInRFC="true" title="About This Document">
         <t>Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ietf-httpbis-resumable-upload/"/>.</t>
         <t>Discussion of this document takes place on the HTTP Working Group mailing list (<eref target="mailto:ietf-http-wg@w3.org"/>), which is archived at <eref target="https://lists.w3.org/Archives/Public/ietf-http-wg/"/>. Working Group information can be found at <eref target="https://httpwg.org/"/>.</t>
         <t>Source for this draft and an issue tracker can be found at <eref target="https://github.com/httpwg/http-extensions/labels/resumable-upload"/>.</t>
      </note>
   </front>
   <middle>
      <section anchor="introduction">
         <name>Introduction</name>
         <t>HTTP clients often encounter interrupted data transfers as a result of canceled requests or dropped connections. Prior to interruption, part of a representation (see <xref section="3.2" sectionFormat="of" target="HTTP"/>) might have been exchanged. To complete the data transfer of the entire representation, it is often desirable to issue subsequent requests that transfer only the remainder of the representation. HTTP range requests (see <xref section="14" sectionFormat="of" target="HTTP"/>) support this concept of resumable downloads from server to client.</t>
         <t>HTTP methods such as POST or PUT can be used by clients to request processing of representation data enclosed in the request message. The transfer of representation data from client to server is often referred to as an upload. Uploads are just as likely as downloads to suffer from the effects of data transfer interruption. Humans can play a role in upload interruptions through manual actions such as pausing an upload. Regardless of the cause of an interruption, servers may have received part of the representation before its occurrence and it is desirable if clients can complete the data transfer by sending only the remainder of the representation. The process of sending additional parts of a representation using subsequent HTTP requests from client to server is herein referred to as a resumable upload.</t>
         <t>Connection interruptions are common and the absence of a standard mechanism for resumable uploads has lead to a proliferation of custom solutions. Some of those use HTTP, while others rely on other transfer mechanisms entirely. An HTTP-based standard solution is desirable for such a common class of problem.</t>
         <t>This document defines the Resumable Uploads Protocol, an optional mechanism for resumable uploads using HTTP that is backwards-compatible with conventional HTTP uploads. When an upload is interrupted, clients can send subsequent requests to query the server state and use this information to the send remaining data. Alternatively, they can cancel the upload entirely. Different from ranged downloads, this protocol does not support transferring different parts of the same representation in parallel.</t>
      </section>
      <section anchor="conventions-and-definitions">
         <name>Conventions and Definitions</name>
         <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/>
            <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
         <t>The terms byte sequence, Item, string, sf-binary, sf-boolean, sf-integer, sf-string, and sf-token are imported from <xref target="STRUCTURED-FIELDS"/>.</t>
         <t>The terms client and server are imported from <xref target="HTTP"/>.</t>
         <t>Upload: A sequence of one or more procedures, uniquely identified by an upload URL chosen by a server.</t>
         <t>Procedure: An HTTP message exchange for that can be used for resumable uploads.</t>
      </section>
      <section anchor="uploading-overview">
         <name>Uploading Overview</name>
         <t>The Resumable Uploads Protocol consists of several procedures that rely on HTTP message exchanges. The following procedures are defined:</t>
         <t>
            <list style="symbols">
               <t>Upload Creation Procedure (<xref target="upload-creation"/>)</t>
               <t>Offset Retrieving Procedure (<xref target="offset-retrieving"/>)</t>
               <t>Upload Appending Procedure (<xref target="upload-appending"/>)</t>
               <t>Upload Cancellation Procedure (<xref target="upload-cancellation"/>)</t>
            </list>
         </t>
         <t>A single upload is a sequence of one or more procedures. Each upload is uniquely identified by an upload URL chosen by a server.</t>
         <t>The remainder of this section uses examples of a file upload to illustrate permutations of procedure sequence. Note, however, that HTTP message exchanges use representation data (see <xref section="8.1" sectionFormat="of" target="HTTP"/>), which means that procedures can apply to many forms of content.</t>
         <section anchor="example-1-complete-upload-of-file-with-known-size">
            <name>Example 1: Complete upload of file with known size</name>
            <t>In this example, the client first attempts to upload a file with a known size in a single HTTP request. An interruption occurs and the client then attempts to resume the upload using subsequent HTTP requests.</t>
            <t>1) The Upload Creation Procedure (<xref target="upload-creation"/>) can be used to notify the server that the client wants to begin an upload. The server should then reserve the required resources to accept the upload from the client. The client also begins transferring the entire file in the request body. An informational response can be sent to the client to signal the support of resumable upload on the server and transmit the upload URL in the Location header, which is used for identifying future requests related to this upload.</t>
            <figure anchor="fig-upload-creation-procedure"
                     title="Upload Creation Procedure">
               <artwork>
Client                                  Server
|                                            |
| POST                                       |
|-------------------------------------------&gt;|
|                                            |
|                                            | Reserve resources
|                                            | for upload
|                                            |------------------
|                                            |                 |
|                                            |&lt;-----------------
|                                            |
|            104 Upload Resumption Supported |
|            with upload URL                 |
|&lt;-------------------------------------------|
|                                            |
| Flow Interrupted                           |
|-------------------------------------------&gt;|
|                                            |
</artwork>
            </figure>
            <t>2) If the connection to the server gets interrupted during the Upload Creation Procedure, the client may want to resume the upload. Before this is possible, the client must know the amount of data that the server was able to receive before the connection got interrupted. To achieve this, the client uses the Offset Retrieving Procedure (<xref target="offset-retrieving"/>) to obtain the upload's offset using the upload URL.</t>
            <figure anchor="fig-offset-retrieving-procedure"
                     title="Offset Retrieving Procedure">
               <artwork>
Client                                      Server
|                                                |
| HEAD to upload URL                             |
|-----------------------------------------------&gt;|
|                                                |
|              204 No Content with Upload-Offset |
|&lt;-----------------------------------------------|
|                                                |
</artwork>
            </figure>
            <t>3) After the Offset Retrieving Procedure (<xref target="offset-retrieving"/>) completes, the client can resume the upload by sending the remaining file content to the server using the Upload Appending Procedure (<xref target="upload-appending"/>), appending to the already stored data in the upload. The <spanx style="verb">Upload-Offset</spanx> value is included to ensure that the client and server agree on the offset that the upload resumes from.</t>
            <figure anchor="fig-upload-appending-procedure"
                     title="Upload Appending Procedure">
               <artwork>
Client                                      Server
|                                                |
| PATCH to upload URL with Upload-Offset         |
|-----------------------------------------------&gt;|
|                                                |
|                      201 Created on completion |
|&lt;-----------------------------------------------|
|                                                |
</artwork>
            </figure>
            <t>4) If the client is not interested in completing the upload anymore, it can instruct the server to delete the upload and free all related resources using the Upload Cancellation Procedure (<xref target="upload-cancellation"/>).</t>
            <figure anchor="fig-upload-cancellation-procedure"
                     title="Upload Cancellation Procedure">
               <artwork>
Client                                      Server
|                                                |
| DELETE to upload URL                           |
|-----------------------------------------------&gt;|
|                                                |
|                   204 No Content on completion |
|&lt;-----------------------------------------------|
|                                                |
</artwork>
            </figure>
         </section>
         <section anchor="example-2-upload-as-a-series-of-parts">
            <name>Example 2: Upload as a series of parts</name>
            <t>In some cases clients might prefer to upload a file as a series of parts sent across multiple HTTP messages. One use case is to overcome server limits on HTTP message content size. Another use case is where the client does not know the final size, such as when file data originates from a streaming source.</t>
            <t>This example shows how the client, with prior knowledge about the server's resumable upload support, can upload parts of a file over a sequence of procedures.</t>
            <t>1) If the client is aware that the server supports resumable upload, it can use the Upload Creation Procedure with the <spanx style="verb">Upload-Incomplete</spanx> header to start an upload. The client can include the first part of the file in the Upload Creation Procedure.</t>
            <figure anchor="fig-upload-creation-procedure-incomplete"
                     title="Upload Creation Procedure Incomplete">
               <artwork>
Client                                      Server
|                                                |
| POST with Upload-Incomplete                    |
|-----------------------------------------------&gt;|
|                                                |
|             201 Created with Upload-Incomplete |
|              and Location on completion        |
|&lt;-----------------------------------------------|
|                                                |
</artwork>
            </figure>
            <t>2) After creation, the following parts are sent using the Upload Appending Procedure (<xref target="upload-appending"/>), and the last part of the upload does not have the <spanx style="verb">Upload-Incomplete</spanx> header.</t>
            <figure anchor="fig-upload-appending-procedure-last-chunk"
                     title="Upload Appending Procedure Last Chunk">
               <artwork>
Client                                      Server
|                                                |
| PATCH to upload URL and Upload-Offset          |
|-----------------------------------------------&gt;|
|                                                |
|                      201 Created on completion |
|&lt;-----------------------------------------------|
|                                                |
</artwork>
            </figure>
         </section>
      </section>
      <section anchor="upload-creation">
         <name>Upload Creation Procedure</name>
         <t>The Upload Creation Procedure is intended for starting a new upload. A limited form of this procedure <bcp14>MAY</bcp14> be used by the client without the knowledge of server support of the Resumable Uploads Protocol.</t>
         <t>This procedure is designed to be compatible with a regular upload. Therefore all methods are allowed with the exception of <spanx style="verb">GET</spanx>, <spanx style="verb">HEAD</spanx>, <spanx style="verb">DELETE</spanx>, and <spanx style="verb">OPTIONS</spanx>. All response status codes are allowed. The client is <bcp14>RECOMMENDED</bcp14> to use the <spanx style="verb">POST</spanx> method if not otherwise intended. The server <bcp14>MAY</bcp14> only support a limited number of methods.</t>
         <t>The request <bcp14>MUST</bcp14> include the <spanx style="verb">Upload-Incomplete</spanx> header field (<xref target="upload-incomplete"/>). It <bcp14>MUST</bcp14> be set to true if the end of the request body is not the end of the upload. Otherwise, it <bcp14>MUST</bcp14> be set to false. This header field can be used for request identification by a server. The request <bcp14>MUST NOT</bcp14> include the <spanx style="verb">Upload-Offset</spanx> header.</t>
         <t>If the request is valid, the server <bcp14>SHOULD</bcp14> create an upload resource. If so, the server <bcp14>MUST</bcp14> include the <spanx style="verb">Location</spanx> header in the response and set to the upload URL, which points to the created upload resource. The client <bcp14>MAY</bcp14> use this upload URL to execute the Offset Retrieving Procedure (<xref target="offset-retrieving"/>), Upload Appending Procedure (<xref target="upload-appending"/>), or Upload Cancellation Procedure (<xref target="upload-cancellation"/>).</t>
         <t>As soon as the upload resource is available, the server <bcp14>MAY</bcp14> send an informational response with <spanx style="verb">104 (Upload Resumption Supported)</spanx> status to the client while the request body is being uploaded. In this informational response, the <spanx style="verb">Location</spanx> header field <bcp14>MUST</bcp14> be set to the upload URL.</t>
         <t>The server <bcp14>MUST</bcp14> send the <spanx style="verb">Upload-Offset</spanx> header in the response if it considers the upload active, either when the response is a success (e.g. <spanx style="verb">201 (Created)</spanx>), or when the response is a failure (e.g. <spanx style="verb">409 (Conflict)</spanx>). The value <bcp14>MUST</bcp14> be equal to the end offset of the entire upload, or the begin offset of the next chunk if the upload is still incomplete. The client <bcp14>SHOULD</bcp14> consider the upload failed if the response status code indicates a success but the offset in the <spanx style="verb">Upload-Offset</spanx> header field in the response does not equal to the begin offset plus the number of bytes uploaded in the request.</t>
         <t>If the request completes successfully and the entire upload is complete, the server <bcp14>MUST</bcp14> acknowledge it by responding with a successful status code between 200 and 299 (inclusive). Server is <bcp14>RECOMMENDED</bcp14> to use <spanx style="verb">201 (Created)</spanx> response if not otherwise specified. The response <bcp14>MUST NOT</bcp14> include the <spanx style="verb">Upload-Incomplete</spanx> header with the value of true.</t>
         <t>If the request completes successfully but the entire upload is not yet complete indicated by the <spanx style="verb">Upload-Incomplete</spanx> header, the server <bcp14>MUST</bcp14> acknowledge it by responding with the <spanx style="verb">201 (Created)</spanx> status code, the <spanx style="verb">Upload-Incomplete</spanx> header set to true.</t>
         <figure>
            <sourcecode type="example">
:method: POST
:scheme: https
:authority: example.com
:path: /upload
upload-draft-interop-version: 3
upload-incomplete: ?0
content-length: 100
[content (100 bytes)]

:status: 104
upload-draft-interop-version: 3
location: https://example.com/upload/b530ce8ff

:status: 201
location: https://example.com/upload/b530ce8ff
upload-offset: 100
</sourcecode>
         </figure>
         <figure>
            <sourcecode type="example">
:method: POST
:scheme: https
:authority: example.com
:path: /upload
upload-draft-interop-version: 3
upload-incomplete: ?1
content-length: 25
[partial content (25 bytes)]

:status: 201
location: https://example.com/upload/b530ce8ff
upload-incomplete: ?1
upload-offset: 25
</sourcecode>
         </figure>
         <t>If the client received an informational repsonse with the upload URL, it <bcp14>MAY</bcp14> automatically attempt upload resumption when the connection is terminated unexpectedly, or if a server error status code between 500 and 599 (inclusive) is received. The client <bcp14>SHOULD NOT</bcp14> automatically retry if a client error status code between 400 and 499 (inclusive) is received.</t>
         <t>File metadata can affect how servers might act on the uploaded file. Clients can send Representation Metadata (see <xref section="8.3" sectionFormat="of" target="HTTP"/>) in the Upload Creation Procedure request that starts an upload. Servers <bcp14>MAY</bcp14> interpret this metadata or <bcp14>MAY</bcp14> ignore it. The <spanx style="verb">Content-Type</spanx> header can be used to indicate the MIME type of the file. The <spanx style="verb">Content-Disposition</spanx> header can be used to transmit a filename. If included, the parameters <bcp14>SHOULD</bcp14> be either <spanx style="verb">filename</spanx>, <spanx style="verb">filename*</spanx> or <spanx style="verb">boundary</spanx>.</t>
         <section anchor="feature-detection">
            <name>Feature Detection</name>
            <t>If the client has no knowledge of whether the resource supports resumable uploads, the Upload Creation Procedure <bcp14>MAY</bcp14> be used with some additional constraints. In particular, the <spanx style="verb">Upload-Incomplete</spanx> header field (<xref target="upload-incomplete"/>) <bcp14>MUST NOT</bcp14> be set to true if the server support is unclear. This allows the upload to function as if it is a regular upload.</t>
            <t>The server <bcp14>SHOULD</bcp14> send the <spanx style="verb">104 (Upload Resumption Supported)</spanx> informational response to the client, to indicate its support for a resumable upload.</t>
            <t>The client <bcp14>MUST NOT</bcp14> attempt to resume an upload if it did not receive the <spanx style="verb">104 (Upload Resumption Supported)</spanx> informational response, and it does not have other signals of whether the server supporting resumable upload.</t>
         </section>
         <section anchor="draft-version-identification">
            <name>Draft Version Identification</name>
            <ul empty="true">
               <li>
                  <t>
                     <strong>RFC Editor's Note:</strong> Please remove this section and <spanx style="verb">Upload-Draft-Interop-Version</spanx> from all examples prior to publication of a final version of this document.</t>
               </li>
            </ul>
            <t>The current interop version is 3.</t>
            <t>Client implementations of draft versions of the protocol <bcp14>MUST</bcp14> send a header field <spanx style="verb">Upload-Draft-Interop-Version</spanx> with the interop version as its value to its requests. Its ABNF is</t>
            <figure>
               <sourcecode type="abnf">
Upload-Draft-Interop-Version = sf-integer
</sourcecode>
            </figure>
            <t>Server implementations of draft versions of the protocol <bcp14>MUST NOT</bcp14> send a <spanx style="verb">104 (Upload Resumption Supported)</spanx> informational response when the interop version indicated by the <spanx style="verb">Upload-Draft-Interop-Version</spanx> header field in the request is missing or mismatching.</t>
            <t>Server implementations of draft versions of the protocol <bcp14>MUST</bcp14> also send a header field <spanx style="verb">Upload-Draft-Interop-Version</spanx> with the interop version as its value to the <spanx style="verb">104 (Upload Resumption Supported)</spanx> informational response.</t>
            <t>Client implementations of draft versions of the protocol <bcp14>MUST</bcp14> ignore a <spanx style="verb">104 (Upload Resumption Supported)</spanx> informational response with missing or mismatching interop version indicated by the <spanx style="verb">Upload-Draft-Interop-Version</spanx> header field.</t>
            <t>The reason both the client and the server are sending and checking the draft version is to ensure that implementations of the final RFC will not accidentally interop with draft implementations, as they will not check the existence of the <spanx style="verb">Upload-Draft-Interop-Version</spanx> header field.</t>
         </section>
      </section>
      <section anchor="offset-retrieving">
         <name>Offset Retrieving Procedure</name>
         <t>If an upload is interrupted, the client <bcp14>MAY</bcp14> attempt to fetch the offset of the incomplete upload by sending a <spanx style="verb">HEAD</spanx> request to the upload URL, as obtained from the Upload Creation Procedure (<xref target="upload-creation"/>). The client <bcp14>MUST NOT</bcp14> initiate this procedure without the knowledge of server support.</t>
         <t>The request <bcp14>MUST NOT</bcp14> include the <spanx style="verb">Upload-Offset</spanx> header or the <spanx style="verb">Upload-Incomplete</spanx> header. The server <bcp14>MUST</bcp14> reject the request with the <spanx style="verb">Upload-Offset</spanx> header or the <spanx style="verb">Upload-Incomplete</spanx> header by sending a <spanx style="verb">400 (Bad Request)</spanx> response.</t>
         <t>If the server considers the upload associated with this upload URL active, it <bcp14>MUST</bcp14> send back a <spanx style="verb">204 (No Content)</spanx> response. The response <bcp14>MUST</bcp14> include the <spanx style="verb">Upload-Offset</spanx> header set to the current resumption offset for the client. The response <bcp14>MUST</bcp14> include the <spanx style="verb">Upload-Incomplete</spanx> header which is set to true if and only if the upload is incomplete. An upload is considered complete if and only if the server completely and successfully received a corresponding Upload Creation Procedure (<xref target="upload-creation"/>) or Upload Appending Procedure (<xref target="upload-appending"/>) request with the <spanx style="verb">Upload-Incomplete</spanx> header being omitted or set to false.</t>
         <t>The client <bcp14>MUST NOT</bcp14> perform the Offset Retrieving Procedure (<xref target="offset-retrieving"/>) while the Upload Creation Procedure (<xref target="upload-creation"/>) or the Upload Appending Procedure (<xref target="upload-appending"/>) is in progress.</t>
         <t>The offset <bcp14>MUST</bcp14> be accepted by a subsequent Upload Appending Procedure (<xref target="upload-appending"/>). Due to network delay and reordering, the server might still be receiving data from an ongoing transfer for the same upload URL, which in the client perspective has failed. The server <bcp14>MAY</bcp14> terminate any transfers for the same upload URL before sending the response by abruptly terminating the HTTP connection or stream. Alternatively, the server <bcp14>MAY</bcp14> keep the ongoing transfer alive but ignore further bytes received past the offset.</t>
         <t>The client <bcp14>MUST NOT</bcp14> start more than one Upload Appending Procedures (<xref target="upload-appending"/>) based on the resumption offset from a single Offset Retrieving Procedure (<xref target="offset-retrieving"/>).</t>
         <t>The response <bcp14>SHOULD</bcp14> include <spanx style="verb">Cache-Control: no-store</spanx> header to prevent HTTP caching.</t>
         <t>If the server does not consider the upload associated with this upload URL active, it <bcp14>MUST</bcp14> respond with <spanx style="verb">404 (Not Found)</spanx> status code.</t>
         <t>The resumption offset can be less than or equal to the number of bytes the client has already sent. The client <bcp14>MAY</bcp14> reject an offset which is greater than the number of bytes it has already sent during this upload. The client is expected to handle backtracking of a reasonable length. If the offset is invalid for this upload, or if the client cannot backtrack to the offset and reproduce the same content it has already sent, the upload <bcp14>MUST</bcp14> be considered a failure. The client <bcp14>MAY</bcp14> use the Upload Cancellation Procedure (<xref target="upload-cancellation"/>) to cancel the upload after rejecting the offset.</t>
         <figure>
            <artwork>
:method: HEAD
:scheme: https
:authority: example.com
:path: /upload/b530ce8ff
upload-draft-interop-version: 3

:status: 204
upload-offset: 100
upload-incomplete: ?1
cache-control: no-store
</artwork>
         </figure>
         <t>The client <bcp14>SHOULD NOT</bcp14> automatically retry if a client error status code between 400 and 499 (inclusive) is received.</t>
      </section>
      <section anchor="upload-appending">
         <name>Upload Appending Procedure</name>
         <t>The Upload Appending Procedure is used for resuming an existing upload.</t>
         <t>The request <bcp14>MUST</bcp14> use the <spanx style="verb">PATCH</spanx> method and be sent to the upload URL, as obtained from the Upload Creation Procedure (<xref target="upload-creation"/>). The <spanx style="verb">Upload-Offset</spanx> header field (<xref target="upload-offset"/>) <bcp14>MUST</bcp14> be set to the resumption offset.</t>
         <t>If the end of the request body is not the end of the upload, the <spanx style="verb">Upload-Incomplete</spanx> header field (<xref target="upload-incomplete"/>) <bcp14>MUST</bcp14> be set to true.</t>
         <t>The server <bcp14>SHOULD</bcp14> respect representation metadata received in the Upload Creation Procedure (<xref target="upload-creation"/>) and ignore any representation metadata received in the Upload Appending Procedure (<xref target="upload-appending"/>).</t>
         <t>If the server does not consider the upload associated with the upload URL active, it <bcp14>MUST</bcp14> respond with <spanx style="verb">404 (Not Found)</spanx> status code.</t>
         <t>The client <bcp14>MUST NOT</bcp14> perform multiple upload transfers for the same upload URL using Upload Creation Procedures (<xref target="upload-creation"/>) or Upload Appending Procedures (<xref target="upload-appending"/>) in parallel to avoid race conditions and data loss or corruption. The server is <bcp14>RECOMMENDED</bcp14> to take measures to avoid parallel upload transfers: The server <bcp14>MAY</bcp14> terminate any ongoing Upload Creation Procedure (<xref target="upload-creation"/>) or Upload Appending Procedure (<xref target="upload-appending"/>) for the same upload URL. Since the client is not allowed to perform multiple transfers in parallel, the server can assume that the previous attempt has already failed. Therefore, the server <bcp14>MAY</bcp14> abruptly terminate the previous HTTP connection or stream.</t>
         <t>If the offset in the <spanx style="verb">Upload-Offset</spanx> header field does not match the offset provided by the immediate previous Offset Retrieving Procedure (<xref target="offset-retrieving"/>), or the end offset of the immediate previous incomplete successful transfer, the server <bcp14>MUST</bcp14> respond with <spanx style="verb">409 (Conflict)</spanx> status code.</t>
         <t>The server <bcp14>MUST</bcp14> send the <spanx style="verb">Upload-Offset</spanx> header in the response if it considers the upload active, either when the response is a success (e.g. <spanx style="verb">201 (Created)</spanx>), or when the response is a failure (e.g. <spanx style="verb">409 (Conflict)</spanx>). The value <bcp14>MUST</bcp14> be equal to the end offset of the entire upload, or the begin offset of the next chunk if the upload is still incomplete. The client <bcp14>SHOULD</bcp14> consider the upload failed if the response status code indicates a success but the offset in the <spanx style="verb">Upload-Offset</spanx> header field in the response does not equal to the begin offset plus the number of bytes uploaded in the request.</t>
         <t>If the request completes successfully and the entire upload is complete, the server <bcp14>MUST</bcp14> acknowledge it by responding with a successful status code between 200 and 299 (inclusive). Server is <bcp14>RECOMMENDED</bcp14> to use <spanx style="verb">201 (Created)</spanx> response if not otherwise specified. The response <bcp14>MUST NOT</bcp14> include the <spanx style="verb">Upload-Incomplete</spanx> header with the value of true.</t>
         <t>If the request completes successfully but the entire upload is not yet complete indicated by the <spanx style="verb">Upload-Incomplete</spanx> header, the server <bcp14>MUST</bcp14> acknowledge it by responding with the <spanx style="verb">201 (Created)</spanx> status code, the <spanx style="verb">Upload-Incomplete</spanx> header set to true.</t>
         <figure>
            <sourcecode type="example">
:method: PATCH
:scheme: https
:authority: example.com
:path: /upload/b530ce8ff
upload-offset: 100
upload-draft-interop-version: 3
content-length: 100
[content (100 bytes)]

:status: 201
upload-offset: 200
</sourcecode>
         </figure>
         <t>The client <bcp14>MAY</bcp14> automatically attempt upload resumption when the connection is terminated unexpectedly, or if a server error status code between 500 and 599 (inclusive) is received. The client <bcp14>SHOULD NOT</bcp14> automatically retry if a client error status code between 400 and 499 (inclusive) is received.</t>
      </section>
      <section anchor="upload-cancellation">
         <name>Upload Cancellation Procedure</name>
         <t>If the client wants to terminate the transfer without the ability to resume, it <bcp14>MAY</bcp14> send a <spanx style="verb">DELETE</spanx> request to the upload URL, as obtained from the Upload Creation Procedure (<xref target="upload-creation"/>). It is an indication that the client is no longer interested in uploading this body and the server can release resources associated with this upload URL. The client <bcp14>MUST NOT</bcp14> initiate this procedure without the knowledge of server support.</t>
         <t>The request <bcp14>MUST</bcp14> use the <spanx style="verb">DELETE</spanx> method. The request <bcp14>MUST NOT</bcp14> include the <spanx style="verb">Upload-Offset</spanx> header or the <spanx style="verb">Upload-Incomplete</spanx> header. The server <bcp14>MUST</bcp14> reject the request with the <spanx style="verb">Upload-Offset</spanx> header or the <spanx style="verb">Upload-Incomplete</spanx> header by sending a <spanx style="verb">400 (Bad Request)</spanx> response.</t>
         <t>If the server has successfully deactivated this upload URL, it <bcp14>MUST</bcp14> send back a <spanx style="verb">204 (No Content)</spanx> response.</t>
         <t>The server <bcp14>MAY</bcp14> terminate any ongoing Upload Creation Procedure (<xref target="upload-creation"/>) or Upload Appending Procedure (<xref target="upload-appending"/>) for the same upload URL before sending the response by abruptly terminating the HTTP connection or stream.</t>
         <t>If the server does not consider the upload associated with this upload URL active, it <bcp14>MUST</bcp14> respond with <spanx style="verb">404 (Not Found)</spanx> status code.</t>
         <t>If the server does not support cancellation, it <bcp14>MUST</bcp14> respond with <spanx style="verb">405 (Method Not Allowed)</spanx> status code.</t>
         <figure>
            <sourcecode type="example">
:method: DELETE
:scheme: https
:authority: example.com
:path: /upload/b530ce8ff
upload-draft-interop-version: 3

:status: 204
</sourcecode>
         </figure>
      </section>
      <section anchor="request-identification">
         <name>Request Identification</name>
         <t>The Upload Creation Procedure (<xref target="upload-creation"/>) supports arbitrary methods including <spanx style="verb">PATCH</spanx>, therefore it is not possible to identify the procedure of a request purely by its method. The following algorithm is <bcp14>RECOMMENDED</bcp14> to identify the procedure from a request for a generic implementation:</t>
         <t>
            <list style="numbers">
               <t>The request URL is not an upload URL (i.e. does not point to an upload resource): Upload Creation Procedure (<xref target="upload-creation"/>)</t>
               <t>The request URL is an upload URL and the method is <spanx style="verb">HEAD</spanx>: Offset Retrieving Procedure (<xref target="offset-retrieving"/>).</t>
               <t>The request URL is an upload URL and the method is <spanx style="verb">DELETE</spanx>: Upload Cancellation Procedure (<xref target="upload-cancellation"/>).</t>
               <t>The request URL is an upload URL and the <spanx style="verb">Upload-Offset</spanx> header is present: Upload Appending Procedure (<xref target="upload-appending"/>).</t>
               <t>Otherwise: Not a resumable upload.</t>
            </list>
         </t>
      </section>
      <section anchor="header-fields">
         <name>Header Fields</name>
         <section anchor="upload-offset">
            <name>Upload-Offset</name>
            <t>The <spanx style="verb">Upload-Offset</spanx> request and response header field is an Item Structured Header indicating the resumption offset of corresponding upload, counted in bytes. Its value <bcp14>MUST</bcp14> be an integer. Its ABNF is</t>
            <figure>
               <sourcecode type="abnf">
Upload-Offset = sf-integer
</sourcecode>
            </figure>
         </section>
         <section anchor="upload-incomplete">
            <name>Upload-Incomplete</name>
            <t>The <spanx style="verb">Upload-Incomplete</spanx> request and response header field is an Item Structured Header indicating whether the corresponding upload is considered complete. Its value <bcp14>MUST</bcp14> be a boolean. Its ABNF is</t>
            <figure>
               <sourcecode type="abnf">
Upload-Incomplete = sf-boolean
</sourcecode>
            </figure>
            <t>The <spanx style="verb">Upload-Incomplete</spanx> header field <bcp14>MUST</bcp14> only by used if support by the resource is known to the client (<xref target="feature-detection"/>).</t>
         </section>
      </section>
      <section anchor="redirection">
         <name>Redirection</name>
         <t>The <spanx style="verb">301 (Moved Permanently)</spanx> status code and the <spanx style="verb">302 (Found)</spanx> status code <bcp14>MUST NOT</bcp14> be used in Offset Retrieving Procedure (<xref target="offset-retrieving"/>) and Upload Cancellation Procedure (<xref target="upload-cancellation"/>) responses. A <spanx style="verb">308 (Permanent Redirect)</spanx> response <bcp14>MAY</bcp14> be persisted for all subsequent procedures. If client receives a <spanx style="verb">307 (Temporary Redirect)</spanx> response in the Offset Retrieving Procedure (<xref target="offset-retrieving"/>), it <bcp14>MAY</bcp14> apply the redirection directly in the immediate subsequent Upload Appending Procedure (<xref target="upload-appending"/>).</t>
      </section>
      <section anchor="security-considerations">
         <name>Security Considerations</name>
         <t>The upload URL obtained through the Upload Creation Procedure (<xref target="upload-creation"/>) is the identifier used for modifying the upload. Without further protection of this upload URL, an attacker may use the upload URL to obtain information about an upload, append data to it, or cancel it. To prevent this, the server <bcp14>SHOULD</bcp14> ensure that only authorized clients can perform the Offset Retrieving Procedure (<xref target="offset-retrieving"/>), Upload Appending Procedure (<xref target="upload-appending"/>), or Upload Cancellation Procedure (<xref target="upload-cancellation"/>) for a given upload URL and otherwise reject the procedure. In addition, the upload URL <bcp14>SHOULD</bcp14> be generated in such a way that makes it hard to be guessed by non-authorized clients.</t>
      </section>
      <section anchor="iana-considerations">
         <name>IANA Considerations</name>
         <t>This specification registers the following entry in the Permanent Message Header Field Names registry established by <xref target="RFC3864"/>:</t>
         <t>Header field name: Upload-Offset, Upload-Incomplete</t>
         <t>Applicable protocol: http</t>
         <t>Status: standard</t>
         <t>Author/change controller: IETF</t>
         <t>Specification: This document</t>
         <t>Related information: n/a</t>
         <t>This specification registers the following entry in the "HTTP Status Codes" registry:</t>
         <t>Code: 104 (suggested value)</t>
         <t>Description: Upload Resumption Supported</t>
         <t>Specification: This document</t>
      </section>
   </middle>
   <back>
      <references title="Normative References">
         <reference anchor="RFC2119">
            <front>
               <title>Key words for use in RFCs to Indicate Requirement Levels</title>
               <author fullname="S. Bradner" initials="S." surname="Bradner"/>
               <date month="March" year="1997"/>
            </front>
            <seriesInfo name="BCP" value="14"/>
            <seriesInfo name="RFC" value="2119"/>
            <seriesInfo name="DOI" value="10.17487/RFC2119"/>
         </reference>
         <reference anchor="HTTP">
            <front>
               <title>HTTP Semantics</title>
               <author fullname="Roy T. Fielding" initials="R. T." surname="Fielding">
                  <organization>Adobe</organization>
               </author>
               <author fullname="Mark Nottingham" initials="M." surname="Nottingham">
                  <organization>Fastly</organization>
               </author>
               <author fullname="Julian Reschke" initials="J." surname="Reschke">
                  <organization>greenbytes GmbH</organization>
               </author>
               <date day="12" month="September" year="2021"/>
            </front>
            <seriesInfo name="Internet-Draft" value="draft-ietf-httpbis-semantics-19"/>
         </reference>
         <reference anchor="RFC8174">
            <front>
               <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
               <author fullname="B. Leiba" initials="B." surname="Leiba"/>
               <date month="May" year="2017"/>
            </front>
            <seriesInfo name="BCP" value="14"/>
            <seriesInfo name="RFC" value="8174"/>
            <seriesInfo name="DOI" value="10.17487/RFC8174"/>
         </reference>
         <reference anchor="STRUCTURED-FIELDS">
            <front>
               <title>Structured Field Values for HTTP</title>
               <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
               <author fullname="P-H. Kamp" initials="P-H." surname="Kamp"/>
               <date month="February" year="2021"/>
            </front>
            <seriesInfo name="RFC" value="8941"/>
            <seriesInfo name="DOI" value="10.17487/RFC8941"/>
         </reference>
         <reference anchor="RFC3864">
            <front>
               <title>Registration Procedures for Message Header Fields</title>
               <author fullname="G. Klyne" initials="G." surname="Klyne"/>
               <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
               <author fullname="J. Mogul" initials="J." surname="Mogul"/>
               <date month="September" year="2004"/>
            </front>
            <seriesInfo name="BCP" value="90"/>
            <seriesInfo name="RFC" value="3864"/>
            <seriesInfo name="DOI" value="10.17487/RFC3864"/>
         </reference>
      </references>
      <section anchor="since-draft-ietf-httpbis-resumable-upload-00">
         <name>Since draft-ietf-httpbis-resumable-upload-00</name>
         <t>
            <list style="symbols">
               <t>Remove Upload-Token and instead use Server-generated upload URL for upload identification.</t>
               <t>Require the Upload-Incomplete header field in Upload Creation Procedure.</t>
               <t>Increase the draft interop version.</t>
            </list>
         </t>
         <section anchor="since-draft-tus-httpbis-resumable-uploads-protocol-02">
            <name>Since draft-tus-httpbis-resumable-uploads-protocol-02</name>
            <t>None</t>
         </section>
         <section anchor="since-draft-tus-httpbis-resumable-uploads-protocol-01">
            <name>Since draft-tus-httpbis-resumable-uploads-protocol-01</name>
            <t>
               <list style="symbols">
                  <t>Clarifying backtracking and preventing skipping ahead during the Offset Receiving Procedure.</t>
                  <t>Clients auto-retry 404 is no longer allowed.</t>
               </list>
            </t>
         </section>
         <section anchor="since-draft-tus-httpbis-resumable-uploads-protocol-00">
            <name>Since draft-tus-httpbis-resumable-uploads-protocol-00</name>
            <t>
               <list style="symbols">
                  <t>Split the Upload Transfer Procedure into the Upload Creation Procedure and the Upload Appending Procedure.</t>
               </list>
            </t>
         </section>
      </section>
      <section anchor="informational-response">
         <name>Informational Response</name>
         <t>The server is allowed to respond to Upload Creation Procedure (<xref target="upload-creation"/>) requests with a <spanx style="verb">104 (Upload Resumption Supported)</spanx> intermediate response as soon as the server has validated the request. This way, the client knows that the server supports resumable uploads before the complete response for the Upload Creation Procedure is received. The benefit is the clients can defer starting the actual data transfer until the server indicates full support of the incoming Upload Creation Procedure (i.e. resumable are supported, the provided upload URL is active etc).</t>
         <t>On the contrary, support for intermediate responses (the <spanx style="verb">1XX</spanx> range) in existing software is limited or not at all present. Such software includes proxies, firewalls, browsers, and HTTP libraries for clients and server. Therefore, the <spanx style="verb">104 (Upload Resumption Supported)</spanx> status code is optional and not mandatory for the successful completion of an upload. Otherwise, it might be impossible in some cases to implement resumable upload servers using existing software packages. Furthermore, as parts of the current internet infrastructure currently have limited support for intermediate responses, a successful delivery of a <spanx style="verb">104 (Upload Resumption Supported)</spanx> from the server to the client should be assumed.</t>
         <t>We hope that support for intermediate responses increases in the near future, to allow a wider usage of <spanx style="verb">104 (Upload Resumption Supported)</spanx>.</t>
      </section>
      <section anchor="changes-feature-detection">
         <name>Feature Detection</name>
         <t>This specification includes a section about feature detection (it was called service discovery in earlier discussions, but this name is probably ill-suited). The idea is to allow resumable uploads to be transparently implemented by HTTP clients. This means that application developers just keep using the same API of their HTTP library as they have done in the past with traditional, non-resumable uploads. Once the HTTP library gets updated (e.g. because mobile OS or browsers start implementing resumable uploads), the HTTP library can transparently decide to use resumable uploads without explicit configuration by the application developer. Of course, in order to use resumable uploads, the HTTP library needs to know whether the server supports resumable uploads. If no support is detected, the HTTP library should use the traditional, non-resumable upload technique. We call this process feature detection.</t>
         <t>Ideally, the technique used for feature detection meets following <strong>criteria</strong> (there might not be one approach which fits all requirements, so we have to prioritize them):</t>
         <t>
            <list style="numbers">
               <t>Avoid additional roundtrips by the client, if possible (i.e. an additional HTTP request by the client should be avoided).</t>
               <t>Be backwards compatible to HTTP/1.1 and existing network infrastructure: This means to avoid using new features in HTTP/2, or features which might require changes to existing network infrastructure (e.g. nginx or HTTP libraries)</t>
               <t>Conserve the user's privacy (i.e. the feature detection should not leak information to other third-parties about which URLs have been connected to)</t>
            </list>
         </t>
         <t>Following <strong>approaches</strong> have already been considered in the past. All except the last approaches have not been deemed acceptable and are therefore not included in the specification. This follow list is a reference for the advantages and disadvantages of some approaches:</t>
         <t>
            <strong>Include a support statement in the SETTINGS frame.</strong> The SETTINGS frame is a HTTP/2 feature and is sent by the server to the client to exchange information about the current connection. The idea was to include an additional statement in this frame, so the client can detect support for resumable uploads without an additional roundtrip. The problem is that this is not compatible with HTTP/1.1. Furthermore, the SETTINGS frame is intended for information about the current connection (not bound to a request/response) and might not be persisted when transmitted through a proxy.</t>
         <t>
            <strong>Include a support statement in the DNS record.</strong> The client can detect support when resolving a domain name. Of course, DNS is not semantically the correct layer. Also, DNS might not be involved if the record is cached or retrieved from a hosts files.</t>
         <t>
            <strong>Send a HTTP request to ask for support.</strong> This is the easiest approach where the client sends an OPTIONS request and uses the response to determine if the server indicates support for resumable uploads. An alternative is that the client sends the request to a well-known URL to obtain this response, e.g. <spanx style="verb">/.well-known/resumable-uploads</spanx>. Of course, while being fully backwards-compatible, it requires an additional roundtrip.</t>
         <t>
            <strong>Include a support statement in previous responses.</strong> In many cases, the file upload is not the first time that the client connects to the server. Often additional requests are sent beforehand for authentication, data retrieval etc. The responses for those requests can also include a header which indicates support for resumable uploads. There are two options: - Use the standardized <spanx style="verb">Alt-Svc</spanx> response header. However, it has been indicated to us that this header might be reworked in the future and could also be semantically different from our intended usage. - Use a new response header <spanx style="verb">Resumable-Uploads: https://example.org/files/*</spanx> to indicate under which endpoints support for resumable uploads is available.</t>
         <t>
            <strong>Send a 104 intermediate response to indicate support.</strong> The clients normally starts a traditional upload and includes a header indicate that it supports resumable uploads (e.g. <spanx style="verb">Upload-Offset: 0</spanx>). If the server also supports resumable uploads, it will immediately respond with a 104 intermediate response to indicate its support, before further processing the request. This way the client is informed during the upload whether it can resume from possible connection errors or not. While an additional roundtrip is avoided, the problem with that solution is that many HTTP server libraries do not support sending custom 1XX responses and that some proxies may not be able to handle new 1XX status codes correctly.</t>
         <t>
            <strong>Send a 103 Early Hint response to indicate support.</strong> This approach is the similar to the above one, with one exception: Instead of a new <spanx style="verb">104 (Upload Resumption Supported)</spanx> status code, the existing <spanx style="verb">103 (Early Hint)</spanx> status code is used in the intermediate response. The 103 code would then be accompanied by a header indicating support for resumable uploads (e.g. <spanx style="verb">Resumable-Uploads: 1</spanx>). It is unclear whether the Early Hints code is appropriate for that, as it is currently only used to indicate resources for prefetching them.</t>
      </section>
      <section anchor="upload-metadata">
         <name>Upload Metadata</name>
         <t>The Upload Creation Procedure (<xref target="upload-creation"/>) allows the <spanx style="verb">Content-Type</spanx> and <spanx style="verb">Content-Disposition</spanx> header to be included. They are intended to be a standardized way of communicating the file name and file type, if available. However, this is not without controversy. Some argue that since these headers are already defined in other specifications, it is not necessary to include them here again. Furthermore, the <spanx style="verb">Content-Disposition</spanx> header field's format is not clearly enough defined. For example, it is left open which disposition value should be used in the header. There needs to be more discussion whether this approach is suited or not.</t>
         <t>However, from experience with the tus project, users are often asking for a way to communicate the file name and file type. Therefore, we believe it is help to explicitly include an approach for doing so.</t>
      </section>
      <section anchor="faq">
         <name>FAQ</name>
         <t>
            <list style="symbols">
               <t>
                  <strong>Are multipart requests supported?</strong> Yes, requests whose body is encoded using the <spanx style="verb">multipart/form-data</spanx> are implicitly supported. The entire encoded body can be considered as a single file, which is then uploaded using the resumable protocol. The server, of course, must store the delimiter ("boundary") separating each part and must be able to parse the multipart format once the upload is completed.</t>
            </list>
         </t>
      </section>
      <section anchor="acknowledgments" numbered="false">
         <name>Acknowledgments</name>
         <t>This document is based on an Internet-Draft specification written by Jiten Mehta, Stefan Matsson, and the authors of this document.</t>
         <t>The <eref target="https://tus.io/">tus v1 protocol</eref> is a specification for a resumable file upload protocol over HTTP. It inspired the early design of this protocol. Members of the tus community helped significantly in the process of bringing this work to the IETF.</t>
         <t>TODO: more acknowledgements.</t>
      </section>
   </back>
</rfc>
