coreHTTP  v1.0.0
HTTP/1.1 Client Library
Design

HTTP Client Library Architecture and Design

This HTTP client library implements a subset of the HTTP/1.1 protocol. It is optimized for resource constrained devices and does not dynamically allocate any memory.

Transport Interface

For decoupling from the user platform, the HTTP client library uses a transport interface. The transport interface allows the HTTP client library to send and receive data over the user's transport layer. The user platform must implement a TransportInterface_t to use in HTTPClient_Send.

See also
The transport interface documentation for more information.

Building an HTTP Request

The HTTP client library provides the following API to serialize request headers.

An application is expected to create and populate an HTTPRequestInfo_t and set a buffer to use for the headers in HTTPRequestHeaders_t::pBuffer. The application may first call HTTPClient_InitializeRequestHeaders to populate the HTTPRequestHeaders_t with the method, the path, and the host. The HTTP request will be serialized to the following when HTTPRequestInfo_t.reqFlags is zero.

<METHOD> <PATH> HTTP/1.1\r\n
User-Agent: <MY-PLATFORM>\r\n
Host: <SERVER-URL>\r\n\r\n

When the HTTPRequestInfo_t::reqFlags has HTTP_REQUEST_KEEP_ALIVE_FLAG set, then the HTTP request will be serialized to the following:

<METHOD> <PATH> HTTP/1.1\r\n
User-Agent: <MY-PLATFORM>\r\n
Host: <SERVER-URL>\r\n
Connection: keep-alive\r\n\r\n

The user application may add more headers using HTTPClient_AddHeader or HTTPClient_AddRangeHeader. New headers will be appended to the end of the existing headers. Please see the following example:

<METHOD> <PATH> HTTP/1.1\r\n
User-Agent: <MY-PLATFORM>\r\n
Host: <SERVER-URL>\r\n
Connection: keep-alive\r\n
Another-Header1: another-value1\r\n
Another-Header2: another-value2\r\n
Another-Header3: another-value3\r\n\r\n

The user application may pass a request body into the HTTPClient_Send function when the request is ready to be sent.

HTTP Range Requests and Partial Content Responses

Range Requests are strongly encouraged for downloading a large file. Large is defined here to be a file whose total size cannot fit into the space currently available in RAM. By downloading a large file using range requests the user application can spend time processing that part of the file (for example writing to flash), then request the next part of the file. If the user application were to request the entire file at once and process it in sections from the network, the system is at a high risk for dropping packets. Dropped packets cause retransmissions in the system's transport layer. With many, there can be a negative impact on the overall system throughput, network bandwidth, and battery life of the device.

Range requests are supported using HTTPClient_AddRangeHeader. Please see the function documentation for more information.

Receiving and Parsing an HTTP Response

After the request headers are serialized, the user application must set a buffer to receive the HTTP response in HTTPResponse_t::pBuffer. HTTPClient_Send is then used to send the request and receive the response. If the request has a body it is passed as a parameter to HTTPClient_Send. As soon as the response is received from the network it is parsed. The final parsed response is represented by the HTTPResponse_t returned from HTTPClient_Send. Parsing the HTTP response is done using http-parser. http-parser invokes callbacks for each section in the HTTP response it finds. Using these callbacks the HTTP client library sets the members of HTTPResponse_t to return from HTTPClient_Send. The overall flow of HTTPClient_Send is shown in the activity diagram below:

Reading the HTTP Response Headers

Upon a successful return from HTTPClient_Send, the HTTP Response headers can be read from the headers found in HTTPResponse_t::pHeaders. The function HTTPClient_ReadHeader reads the headers from an HTTPResponse_t. HTTPClient_ReadHeader will re-parse the response in HTTPResponse_t::pBuffer, looking for the header field of interest. Re-parsing involves using http-parser to look at each character starting from the beginning of HTTPResponse_t::pBuffer until the header field of interest is found.

If the user application wants to avoid re-parsing HTTPResponse_t::pBuffer, then the user application may register a callback in HTTPResponse_t::pHeaderParsingCallback. When the HTTP response message is first received from the network, in HTTPClient_Send, http-parser is invoked to parse the response. This first parsing in HTTPClient_Send will invoke HTTPResponse_t::pHeaderParsingCallback for each header that is found in response. Please see the sequence diagram below for an illustration of when HTTPClient_ResponseHeaderParsingCallback_t::onHeaderCallback is invoked during the operation of HTTPClient_Send.