Skip to content

Instantly share code, notes, and snippets.

@awwright
Last active July 22, 2024 13:53
Show Gist options
  • Save awwright/f9a1d2730ec01568342c53e5168a738e to your computer and use it in GitHub Desktop.
Save awwright/f9a1d2730ec01568342c53e5168a738e to your computer and use it in GitHub Desktop.
Reporting progress of a long-running operation in HTTP

Reporting progress of a long-running operation in HTTP

Author: Austin Wright

An HTTP intermediate status for communicating progress of long-running responses.

Use Cases

The 102 Processing workflow is intended to suit a broad range of applications, including:

  • Copying, patching, or deleting large sets of files
  • Waiting for an operation to be started at a specific time
  • Adding an operation to a queue
  • Working through a multi-step operation, e.g. provisioning a server
  • Receiving updates to a long running task, e.g. construction of a building
  • Reading a response interrupted by a reset connection

The HTTP intermediate progress flow

The interemdiate progress flow defines a status document that is related to a single request. This status document is expected to specify the status of the operation, until the operation completes, then it will finalize, specifying the results of the operation.

Initial nonsafe request

To begin, the client makes the initial, nonsafe request. For example, POST /resource.

  • If the request finishes quickly, the server can issue the non-1xx, non-202 response. If the server is responding with a document of the result of the operation, the server MAY respond with Content-Location indicating where this status can be re-downloaded.

  • If the client sent a Prefer: processing preference, the server MAY issue a 102 Processing intermediate response. If the client additionally sent a Prefer: progress preference, this 102 intermediate response SHOULD include a Progress: 0/n header, and the first of the 102 responses SHOULD include a Location: <?request=id> header. Respond normally with a 2xx (non-202) or 4xx status code when the operation finishes.

  • If the request includes Prefer: respond-async, wait=n, and has been running longer than the preferred wait time, then background the operation and emit 202 Accepted, with a Location: <?request=id> header. If the server emitted a 102 Processing intermediate response, this will be the same header as in that first response.

The URI of the status document is not constrained; this example just uses a query parameter for compactness.

If the client makes a request with a Prefer: return=minimal or Prefer: return=representation, the server can either ignore this preference, or not write out the status document if it normally would (only writing the Location header pointing to it).

Status document request

If the client received an operation status document from the initial nonsafe request, it may make a GET request to this document to re-download the result of the request.

The client may do this for any reason, including:

  • The operation resulted in a 202 Accepted response and the client wants to know if the operation finished
  • The user wants to review the outcome of the request after having discarded the initial 2xx (non-202) response
  • The connection was reset before the initial request could respond with a non-1xx status code

If the client makes this request with the Prefer: progress preference, the server SHOULD send 102 Processing headers until the operation completes, and the status document is finalized.

The server SHOULD include a Status-URI: code </resource> specifying the status code of the response to /resource.

Example

Clients may send all four preferences in a request:

POST http://example.com/resource HTTP/1.1
Prefer: processing, progress, respond-async, wait=20

To which the server might reply:

HTTP/1.1 102 Processing
Progress: 0/2 (Herding Cats)
Location: <?request=id>

HTTP/1.1 102 Processing 
Progress: 1/2 (Knitting Sweaters)

HTTP/1.1 202 OK
Content-Location: <?request=id>
Content-Type: application/json

{ status: "200 OK" }

If this same request took significantly longer (more than 20 seconds), the response might look like this:

HTTP/1.1 102 Processing
Progress: 0/2 (Herding Cats)
Location: </status>

HTTP/1.1 102 Processing
Progress: 1/2 (Knitting Sweaters)

HTTP/1.1 202 Accepted
Location: </status>
Content-Type: application/json

{ status: "102 Processing" }

The client can re-subscribe to updates by making a GET request to the status document:

GET http://example.com/resource?request=1 HTTP/1.1
Prefer: processing, progress, respond-async, wait=20

HTTP/1.1 102 Processing
Progress: 1/2 (Knitting Sweaters)

HTTP/1.1 202 Accepted
Location: </status>
Content-Type: application/json
Status-URI: 200 <http://example.com/resource>

{ status: "200 OK" }

Note how the request immediately responded with 102 for the current progress.

Document creation flow

If the operation creates a document (typically by POST or PUT), the server MAY return 201 Created, and a subsequent request to the created document, identified by the Location header, will return 102 Processing until the document contents are known.

Definitions

The "102 Processing" status code

The 102 (Processing) status code is an interim response used to inform the client that the server has accepted the request, but has not yet completed it.

The 102 Processing status was first described by WebDAV in RFC2518, but was not included in subsequent revisions of WebDAV for lack of implementations. This document updates the definition of the "102 Processing" status code first defined there.

Use of the "Location" header in 102 Processing

The meaning of a Location header is the same as in a 202 Accepted response: It identifies a document that will be updated with the progress, current status, and result of the operation.

A Location header SHOULD be sent in the first 102 Processing response, as well as any 202 Accepted response to the same request.

Use of Content-Location in 2xx (non-202) and 4xx

Operations that would return a status document SHOULD identify the URI of this status document in a Content-Location header.

The "Progress" header

Progress      = 1*DIGIT "/" 1*DIGIT [ WS comment / quoted-string / ext-value ]
comment       = <comment, see [RFC7230], Section 3.2.6>
quoted-string = <quoted-string, see [RFC7230], Section 3.2.6>
ext-value     = <ext-value, see [RFC8187]>

If the HTTP server supports localization, the server SHOULD negotiate a language using Accept-Language, if it exists in the request. The header field value should use the "ext-value" production and include the language tag of the negotiated language, which MAY be different than the Content-Language.

The "Status-URI" header

If an operation was performed on multiple resources, or the status code of an operation on the request URI becomes known, the Status-URI header can be used to show the result of the operation.

Status-URI = #(Status-Code Coded-URL)

The "processing" preference

When performing a nonsafe action, the server should emit intermediate 102 Processing responses until the action finishes.

In a GET or HEAD request to a status document, it means the client is only interested in the final results of the status document after the operation completes, and the server should send 102 Processing updates until then.

The "progress" preference

The "processing" HTTP preference indicates the client would like 102 Processing intermediate responses to be accompnied by a Progress header.

Security Conscerns

Status URIs

The fact that this operation produces a URI for each operation means that third parties can look at the requests being made by a user. Servers SHOULD ensure that only the user who made the request has access to the status document. Servers SHOULD generate URIs with sufficient entropy, although URIs supposed to be considered public knowledge (see HTTP).

References

  • RFC2518: HTTP Extensions for Distributed Authoring -- WEBDAV
  • RFC7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
  • RFC7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
  • RFC7240: Prefer Header for HTTP
  • RFC8187: Indicating Character Encoding and Language for HTTP Header Field Parameters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment