Async API (Async HTTP)

Summary

In Event-driven architectures or architectures with long-running queries, a common architecture design pattern is to use Asynchronous API also known as Async HTTP.

Note that the implementation of Async API requires a backend server to proxy Header responses. You cannot access Header properties like the location property in SPA or browser applications due to the CORS restriction.

Async API Design Patterns

Design Pattern #1 Async API for SPA

SPAs cannot receive Header information such as the Location header sent during an HTTP 202 Accepted Response due to the CORS restriction. For this reason, in order for the SPA to continuously poll the Resource Endpoint, the Resource Location needs to be sent with the Response as a 200 response.

The Architecture is as follows:

The Frontend makes an API request to the Backend. The Backend relays the Request to the API Endpoint. The Endpoint responds to the Backend Request by supplying a resource URL. The Backend, responds to the Frontend with the Resource URI. The Frontend polls the Resource URI continuously until the status is complete, and the Response is delivered to the Frontend.

Design Pattern #2 Async API for non-SPA

The Architecture for the non-SPA is very similar to the SPA design, the only difference is that the Frontend & Backend are a single platform. The Backend does not need to relay the Response as a 200.

Async API Response from API Server

An example Response from the API Server might be as follows:

{
    "properties": {
        "waitEndTime": "2022-11-02T18:27:49.2954455Z",
        "startTime": "2022-11-02T18:27:49.2954455Z",
        "status": "Running",
        "correlation": {
            "clientTrackingId": "08585341932161829552230682483CU16"
        },
        "workflow": {
            "id": "/workflows/fbd94c22f397423abd2561ebcfbf6061/versions/08585341933469140203",
            "name": "08585341933469140203",
            "type": "Microsoft.Logic/workflows/versions"
        },
        "trigger": {
            "name": "manual",
            "inputsLink": {
                "uri": "https://prod-15.uksouth.logic.azure.com:443/workflows/fbd94c22f397423abd2561ebcfbf6061/runs/08585341932161829552230682483CU16/contents/TriggerInputs?api-version=2016-10-01&se=2022-11-02T22%3A00%3A00.0000000Z&sp=%2Fruns%2F08585341932161829552230682483CU16%2Fcontents%2FTriggerInputs%2Fread&sv=1.0&sig=V0Ntzo5nOgUH0Ow-O0zE8Dc34F77sk1l1hQcDzQaRmw",
                "contentVersion": "orFp4bBboCU+WMK0G2xF4g==",
                "contentSize": 214,
                "contentHash": {
                    "algorithm": "md5",
                    "value": "orFp4bBboCU+WMK0G2xF4g=="
                }
            },
            "outputsLink": {
                "uri": "https://prod-15.uksouth.logic.azure.com:443/workflows/fbd94c22f397423abd2561ebcfbf6061/runs/08585341932161829552230682483CU16/contents/TriggerOutputs?api-version=2016-10-01&se=2022-11-02T22%3A00%3A00.0000000Z&sp=%2Fruns%2F08585341932161829552230682483CU16%2Fcontents%2FTriggerOutputs%2Fread&sv=1.0&sig=tXxzKcTGXzhDq6mRBhSnxuTbsrsGFIBVTR6JZBDs5ag",
                "contentVersion": "jwSvza50VPDMox0raaISMA==",
                "contentSize": 244,
                "contentHash": {
                    "algorithm": "md5",
                    "value": "jwSvza50VPDMox0raaISMA=="
                }
            },
            "startTime": "2022-11-02T18:27:49.287966Z",
            "endTime": "2022-11-02T18:27:49.287966Z",
            "originHistoryName": "08585341932161829552230682483CU16",
            "correlation": {
                "clientTrackingId": "08585341932161829552230682483CU16"
            },
            "status": "Succeeded"
        },
        "outputs": {},
        "response": {
            "startTime": "2022-11-02T18:27:49.287966Z",
            "correlation": {},
            "status": "Waiting"
        }
    },
    "id": "/workflows/fbd94c22f397423abd2561ebcfbf6061/runs/08585341932161829552230682483CU16",
    "name": "08585341932161829552230682483CU16",
    "type": "Microsoft.Logic/workflows/runs"
}

The Response Header contains a Location property that points to the Resource URI.

This Location Header can be polled repeatedly for an output.

Leave a comment