1. HTTP (Hypertext Transfer Protocol)

  1. Asynchronous Operations in HTTP
    1. Mechanisms for returning an Asynchronous Response
    2. Glossary
    3. Mechanisms for real-time notifications
      1. Status Codes
    4. Suggested Asynchronous Workflow
      1. Synchronous return
      2. Wait
      3. Accepted into background
      4. Information request
      5. Canceling & modifying the operation
      6. Operation complete
    5. Examples/Implementations

Asynchronous Operations in HTTP

An asynchronous operation in HTTP is a request that the server will continue processing after the request returns, and can change the state of the server over time as the operation is being processed. This is in contrast to the typical "synchronous" request whose effects, if any, do not occur after the response.

Asynchronous operations are useful for any sort of operation that runs a very long time (which is anything than a few seconds for many applications), or when recovering from a network failure is important.

Suppose a person owns a newfangled electric tea kettle running an HTTP server; how can other devices use this to listen for when the kettle is finished boiling water? We don't know quite when the task will complete; but we want to receive a message when the operation completes. This is called an asynchronous operation in HTTP.

Mechanisms for returning an Asynchronous Response

Glossary

Event
A change in the state of the service, that a user may wish to know about as soon as possible.
Service
The party that is typically the server; but may use a client when delivering a notification to a user of the service.
User
The party that is typically the client; but may also run a server in order to receive notifications from the service.
Request
A standard HTTP request that synchronously returns a response; the request may kick off new operations and subscriptions that run after the request has returned.
Operation
A request by a user for the service to perform a task; that may generate events until the operation completes.
Notification
A message that a service wants to deliver to a user, conveying newly available information.
Subscription
A request by a user to receive notifications from a service, until the user decides to stop listening.

Mechanisms for real-time notifications

In order to make the results of an operation available, the user must have some way of receiving the results outside the context of the response. This is called a transactional notification, and may be implemented in a variety of ways.

The simplest mechanism is to make the results of the operation available from a resource that the user must poll: re-request until the resource says the operation is complete.

The other way to receive a notification from the service. The user must either connect to a service where they may receive an message in real time (realtime request), or run a server listening for a message (realtime push).

For on-demand and realtime requests, the server simply needs to wait for the client to connect, nothing special needs to be configured.

If the client intends to listen for a realtime push, it must register the notification settings with the service:

Callback (webhook)
A field in the request body may specify an address to make POST requests to. The service may wish to test this endpoint with a GET request before returning.
Email
A field in the request body may specify an address to deliver emails to. The From header may also contain an email address, but do not send transactional notifications to this address unless specified by the user; it is typically understood to be a human's mailbox.
Web Push
The service has to receive the push service address, somehow.
Chat service
A chat protocol such as XMPP, IRC, or a proprietary Web-based service is designed for delivering notifications. Users have to specify various connection details and delivery targets, depending on the protocol and service used.

Status Codes

A resource that supports asynchronous operations may return different responses, depending on how the operation is being handled:

Status CodeCompleteSuccessful
200 OKYes✅Yes✅
201 CreatedYes✅Yes✅
202 AcceptedNo⏰Indeterminate
303 See OtherIndeterminateUnknown

Suggested Asynchronous Workflow

An asynchronous workflow begins when a client makes an unsafe request (typically POST, but potentially any unsafe method). Handling begins by collecting data necessary to begin the operation. Typically, the user should provide all the information necessary for the service to run the entire operation.

The information collected should include the client's preferences for reading the result. Many of these preferences are provided in a Prefer request header. Other preferences are service-specific, and should be accepted in the request body. If the client wishes to receive push notifications, it should be specified at this time.

Once the service has received data from the user's client, the operation may be split up into multiple phases:

Synchronous return

The synchronous return phase is the phase the short period of time (preferably less than one second) where the service behaves like a synchronous request. This includes reading the upload (if any), parsing it, checking for obvious errors, and responding to errors that prevent a background operation from being kicked off.

Wait

The wait phase occurs after the client has determined it may begin working on the operation, but does not know how long the operation will take to complete. At this point, the server should send a 102 (Processing) intermediate response to let the client know that processing has begun. The server may send a 102 (Processing) every few seconds to keep the client informed that the operation is still processing.

The client may specify a maximum duration for this phase with the wait HTTP preference. The server may also enforce its own maximum wait time, typically to conserve server resources and mitigate risk of network failures. If the operation completes within this time, the service may generate a synchronous response.

If the operation exceeds the "wait" duration, or it becomes clear the operation will take longer than this, the service may immediately move to the next phase, to background the operation.

In many applications, the operation will always be longer than the duration the server is prepared to wait, in which case this phase will always be very short.

If the request does not contain a Prefer header, then choose values sensible for a Web browser. Most people are not willing to wait more than a few seconds before becoming impatient, so two seconds is suggested.

Clients that do not support notifications and asynchronous responses (e.g. robots or simple scripts) may send Prefer: wait=3600 or some similar large value. Requests that end up taking longer than the specified time may be considered an error.

Accepted into background

The accepted into background phase occurs once the service knows that the operation cannot complete within the wait phase; and so wishes to direct the user to a resource that will be updated as the operation progresses. This tells the client that the operation is still being processed, and it will need to make additional requests or listen for notifications in order to know when the operation finishes.

If the initial request contains a respond-async preference, then return 202 (Accepted) response, and relevant information:

Content-Location header
Specifies where the representation of this response may be re-requested from. It may change over time as the operation progresses, but cannot be content-type negotiated.
Location header
Presumably, this points to a resource about the operation in progress, i.e. the status document. However, the semantics of Location are undefined for a 202 response.
Link header
The Link header may specify additional resources and their relationship to the current request.

With this information, the client may retrieve the status of the request.

The client may also receive notifications from the service when the status of the operation changes in a significant way, for example, it has completed, failed, or requires additional information. Depending on the notification method, the client registers contact information with the service during the initial request.

If the initial request lacks a Prefer header, then treat the request as if it's from a Web browser, and return a 303 (See Other) response. The redirect target should be able to show the current status in HTML (or other formats, if Content-Type negotiated); and may include a script that subscribes to updates (for example, over WebSockets).

Information request

An information request occurs when the service requires additional information in order to continue processing. Typically, the initial request should provide all the information necessary to complete the request, so this usually indicates that human intervention is necessary.

If this occurs during the synchronous or wait phases, this immediately accepts the operation into the background, since this pauses operation indefinitely. The client at this point will read the response, and determine how to respond to it.

Canceling & modifying the operation

The user may wish to modify the operation while it is in progress, such as canceling further work on the operation, or changing how the user receives notifications. This may be done with standard hypermedia features, such as a POST target. This information should be available inside the status document, or in a Link response header with a rel describing the action, for example:

HTTP/1.1 200 OK
Link: <http://example.com/op/42.cancel>;rel="http://example.com/ns/cancel"

In this example, the client sees a link with the rel http://example.com/ns/cancel which it understands as pointing to a resource that will cancel the operation via a POST request.

If the status page is represented in HTML, it may contain forms for each of the permitted state changes.

Operation complete

If the user registered a notification method, emit a notification that the operation has finished, along with results, or a way to retrieve the results.

The status document should include an HTTP-equivalent status code, the status code that would have been returned if the operation completed synchronously (within the wait phase). The best way to do this may be with a message/http document, that the user may parse the same way as an HTTP response. That is, to present an HTTP response within an HTTP response:

HTTP/1.1 200 OK
Content-Type: message/http

HTTP/1.1 507 Insufficient Storage
Content-Type: application/problem+json
Content-Language: en

{
	"status": 507,
	"type": "https://example.com/error/507",
	"title": "Out of disk space.",
	"detail": "The server does not have enough disk space to complete the operation, 5.3TB additional space is required.",
	"instance": "/event/1010F54D-7B25-4DD9-A606-EF592F855DB9"
}

Examples/Implementations