HTTP Functions
Microvisor Public Beta
Microvisor is in a pre-release phase and the information contained in this document is subject to change. Some features referenced below may not be fully available until Microvisor’s General Availability (GA) release.
Microvisor system calls currently include the following functions to manage HTTP communications over the Internet.
The HTTP functions for managing requests and the responses they generate operate through Microvisor network channels. To learn how to establish network connections, and open channels through them, please see Microvisor network functions.
Return values and errors
All of the functions described below return a 32-bit integer that is one of the values from the standard Microvisor enumeration MvStatus
. All possible error values for a given system call are provided with each function’s description.
Success is always signaled by a return value of zero (MV_STATUS_OKAY
).
mvSendHttpRequest()
Issue an HTTP request via a channel
Declaration
extern enum MvStatus mvSendHttpRequest(MvChannelHandle handle,
const struct MvHttpRequest *request);
Parameters
Parameter | Description |
---|---|
handle |
The handle of the channel that will issue the request. This must be a channel of type MV_CHANNELTYPE_HTTP |
request |
A pointer to non-secure memory in which network configuration data is stored by the application |
Possible errors
Error Value | Description |
---|---|
MV_STATUS_PARAMETERFAULT |
request does not reference memory accessible to the application |
MV_STATUS_LATEFAULT |
One or more of the pointers within request — see below — are illegal |
MV_STATUS_INVALIDHANDLE |
handle does not reference a valid channel of type MV_CHANNELTYPE_HTTP |
MV_STATUS_INVALIDBUFFERSIZE |
The request structure will not fit in the channel’s send buffer |
MV_STATUS_TOOMANYELEMENTS |
Too many headers (i.e., more than 32) are attached to request |
MV_STATUS_CHANNELCLOSED |
The specified channel has already been closed |
MV_STATUS_REQUESTALREADYSENT |
The request has already been sent, either successfully or not |
Notifications
This call, if successful, may subsequently yield any of the following notifications.
Notification Event Type | Description |
---|---|
MV_EVENTTYPE_CHANNELDATAREADABLE |
Issued to the host channel’s notification center when data has been received through the channel. Call mvReadHttpResponseData() to the ultimate outcome of the request |
Description
The application makes use of channels of type MV_CHANNELTYPE_HTTP
to issue HTTP requests to remote servers. The channel must be open for the request to be issued and of the correct type.
For each channel, only one request can be issued. If Microvisor returns MV_STATUS_PARAMETERFAULT
, MV_STATUS_INVALIDHANDLE
, MV_STATUS_INVALIDBUFFERSIZE
or MV_STATUS_CHANNELCLOSED
, then the request will not have been issued, and you can reconfigure the request and try again. Any other value indicates that the request has been sent, and any attempt to issue it again, or to use the channel for a fresh request, will result in MV_STATUS_REQUESTALREADYSENT
being returned. Instead, send any subsequent HTTP request through a new channel. You can re-use the channel definition structure and buffers if you wish. Be sure to close the channel used for a given HTTP request once you have received the response or a failure notification.
The type of HTTP request is specified as the scheme prefix of the target URL. Only HTTPS — i.e., https://
— is supported. If your URL is prefixed http://
, or some other scheme, the request will be rejected: the device will receive an MvHttpResponseData
record with its result
field equal to MV_HTTPRESULT_UNSUPPORTED_URI_SCHEME
. Please see mvReadHttpResponseData()
for details of the MvHttpResponseData
structure.
The call’s request
parameter takes a pointer to a MvHttpRequest
structure:
struct MvHttpRequest {
struct MvSizedString method;
struct MvSizedString url;
uint32_t num_headers;
const struct MvHttpHeader *headers;
struct MvSizedString body;
uint32_t timeout_ms;
};
This structure’s properties are:
method
— A data structure comprising the request HTTP method, i.e.,GET
,HEAD
,POST
,PUT
,DELETE
,PATCH
orOPTIONS
, as bytes and the number of bytes.url
— A data structure comprising the target URL as bytes and the number of bytes. Onlyhttps://
is supported as a prefix.num_headers
— The number of headers included in theheaders
array.headers
— A pointer to an array of one or moreMvHttpHeader
structures.body
— A data structure comprising the request body content as bytes and the number of bytes. Include an empty string if there is no body content.timeout_ms
— The request timeout in milliseconds. Microvisor supports timeouts from 5000ms to 10000ms.
Headers
Each entry in the headers
array, if any, is a pointer to an MvHttpHeader
structure:
struct MvHttpHeader {
const uint8_t *data;
uint32_t length;
};
This structure’s properties are:
data
— A pointer to the header content. Do not terminate the header with<CR><LF>
.length
— The number of bytes indata
.
Microvisor automatically adds a Host:
header for you. It also inserts a Content-Length:
header based on the size of any data you include. Again, you do not need to add this yourself, and if you do include one, it will be overwritten by Microvisor.
The maximum number of headers you may attach is 32. An MV_STATUS_TOOMANYELEMENTS
is issued for higher values.
Example
This snippet from our sample HTTP code shows how we use mvSendHttpRequest()
to issue an HTTP request via the Twilio cloud. The calls takes an MvHttpRequest
struct which defines the request. The function server_log()
is not included here, but can be viewed in the sample HTTP code.
// Set up the request
unit32_t item_number = 1;
const char verb[] = "GET";
const char body[] = "";
char uri[46] = "";
sprintf(uri, "https://jsonplaceholder.typicode.com/todos/%u", item_number);
struct MvHttpHeader hdrs[] = {};
struct MvHttpRequest request_config = {
.method = {
.data = (uint8_t *)verb,
.length = strlen(verb)
},
.url = {
.data = (uint8_t *)uri,
.length = strlen(uri)
},
.num_headers = 0,
.headers = hdrs,
.body = {
.data = (uint8_t *)body,
.length = strlen(body)
},
.timeout_ms = 10000
};
// Issue the request -- and check its status
enum MvStatus status = mvSendHttpRequest(http_handles.channel, &request_config);
if (status == MV_STATUS_OKAY) {
server_log("Request sent to Twilio");
return true;
}
mvReadHttpResponseData()
Read the status of an HTTP response
Declaration
extern enum MvStatus mvReadHttpResponseData(MvChannelHandle handle,
struct MvHttpResponseData *response_data);
Parameters
Parameter | Description |
---|---|
handle |
The handle of the channel that passed the source request. This must be a channel of type MV_CHANNELTYPE_HTTP |
response_data |
A pointer to non-secure memory to which an MvHttpResponseData structure will be written by Microvisor |
Possible errors
Error Value | Description |
---|---|
MV_STATUS_PARAMETERFAULT |
response_data does not reference memory accessible to the application |
MV_STATUS_INVALIDHANDLE |
handle does not reference a valid channel of type MV_CHANNELTYPE_HTTP |
MV_STATUS_RESPONSENOTPRESENT |
No HTTP response is present |
MV_STATUS_CHANNELCLOSED |
The specified channel has already been closed |
Description
Your application should call mvReadHttpResponseData()
when the HTTP channel receives a notification of type MV_EVENTTYPE_CHANNELDATAREADABLE
. Microvisor will write an MvHttpResponseData
record which your code can then parse:
struct MvHttpResponseData {
enum MvHttpResult result;
uint32_t status_code;
uint32_t num_headers;
uint32_t body_length;
};
This structure’s properties are:
result
— A value indicating the outcome of the request operation.status_code
— The standard HTTP status code returned.num_headers
— The number of headers in the response.body_length
— The length of the response body in bytes.
The value written to the record’s result
field will be one of the following:
Constant | Code Value | Description |
---|---|---|
MV_HTTPRESULT_OK |
0 | The HTTP request succeeded — but check the status code |
MV_HTTPRESULT_UNSUPPORTEDURISCHEME |
1 | An unsupported URI scheme, e.g., http:// , was used in the request |
MV_HTTPRESULT_UNSUPPORTEDMETHOD |
2 | An unsupported HTTP method was used in the request |
MV_HTTPRESULT_INVALIDHEADERS |
3 | Invalid headers were provided in the request |
MV_HTTPRESULT_INVALIDTIMEOUT |
4 | An invalid timeout was specified in the request (it should be in the range 5000-10000) |
MV_HTTPRESULT_REQUESTFAILED |
5 | The HTTP request failed |
MV_HTTPRESULT_RESPONSETOOLARGE |
6 | The HTTP response returned by the server (headers plus body) didn’t fit into the HTTP channel’s receive buffer |
Example
This snippet from our sample HTTP code shows how we use mvReadHttpResponseData()
to access the response to a previously issued HTTP request. The functions server_log()
and server_error()
are not included here, but can be viewed in the sample HTTP code.
static struct MvHttpResponseData resp_data;
enum MvStatus status = mvReadHttpResponseData(http_handles.channel, &resp_data);
if (status == MV_STATUS_OKAY) {
// Check we successfully issued the request (`result` is OK) and
// the request was successful (status code 200)
if (resp_data.result == MV_HTTPRESULT_OK) {
if (resp_data.status_code == 200) {
server_log("HTTP response header count: %lu", resp_data.num_headers);
server_log("HTTP response body length: %lu", resp_data.body_length);
} else {
server_error("HTTP status code: %lu", resp_data.status_code);
}
} else {
server_error("Request failed. Status: %i", resp_data.result);;
}
} else {
server_error("Response data read failed. Status: %i", status);
}
mvReadHttpResponseHeader()
Read header data from an HTTP response
Declaration
extern enum MvStatus mvReadHttpResponseHeader(MvChannelHandle handle,
uint32_t header_index,
uint8_t *buffer,
uint32_t buffer_size);
Parameters
Parameter | Description |
---|---|
handle |
The handle of the channel that passed the source request. This must be a channel of type MV_CHANNELTYPE_HTTP |
header_index |
The index of the header you require |
buffer |
A pointer to non-secure memory into which the header will be written by Microvisor |
buffer_size |
The size of the buffer in bytes |
Possible errors
Error Value | Description |
---|---|
MV_STATUS_PARAMETERFAULT |
buffer does not reference memory accessible to the application |
MV_STATUS_INVALIDHANDLE |
handle does not reference a valid channel of type MV_CHANNELTYPE_HTTP |
MV_STATUS_HEADERINDEXINVALID |
The specified header index is greater the number of headers in the response - 1 |
MV_STATUS_RESPONSENOTPRESENT |
No HTTP response is present |
MV_STATUS_CHANNELCLOSED |
The specified channel has already been closed |
Description
Your call to mvReadHttpResponseData()
will indicate the number of headers, if any, included in the response. To read one of these headers, call this function and pass in a header_index
value indicating the desired header’s position in the sequence of headers. Microvisor will write the header into the buffer you specify in the call.
Example
The following function demonstrates how you can use mvReadHttpResponseHeader()
to extract one or more headers from the response to a previously issued HTTP request and log them. The functions server_log()
and server_error()
are not included here, but can be viewed in our sample HTTP code.
/**
* @brief Output all received headers.
*
* @param n: The number of headers to list.
*/
void output_headers(uint32_t n) {
if (n > 0) {
uint8_t buffer[2048];
for (uint32_t i = 0 ; i < n ; ++i) {
memset((void *)buffer, 0x00, 256);
enum MvStatus status = mvReadHttpResponseHeader(http_handles.channel, i, buffer, 2048);
if (status == MV_STATUS_OKAY) {
server_log("%lu. %s", i + 1, buffer);
} else {
server_error("Could not read header %lu", i + 1);
}
}
}
}
mvReadHttpResponseBody()
Read body data from an HTTP response
Declaration
extern enum MvStatus mvReadHttpResponseBody(MvChannelHandle handle,
uint32_t offset,
uint8_t *buffer,
uint32_t buffer_size);
Parameters
Parameter | Description |
---|---|
handle |
The handle of the channel that passed the source request. This must be a channel of type MV_CHANNELTYPE_HTTP |
offset |
The byte offset from the start of the body to read from |
buffer |
A pointer to non-secure memory into which the body data will be written by Microvisor |
buffer_size |
The size of the buffer in bytes |
Possible Errors
Error Value | Description |
---|---|
MV_STATUS_PARAMETERFAULT |
buffer does not reference memory accessible to the application |
MV_STATUS_INVALIDHANDLE |
handle does not reference a valid channel of type MV_CHANNELTYPE_HTTP |
MV_STATUS_OFFSETINVALID |
The value of offset exceeds the size of the returned body |
MV_STATUS_RESPONSENOTPRESENT |
No HTTP response is present |
MV_STATUS_CHANNELCLOSED |
The specified channel has already been closed |
Description
Your call to mvReadHttpResponseData()
will indicate the length of the response’s body, if any. To read all or part of the body data, call this function.
To read just a portion of the body, set a non-zero value of offset
as the start byte and/or specify a buffer size below that of the response body’s length. Microvisor will read from the response body from the byte at offset
up to the end of the target buffer.
Example
This snippet from our sample HTTP code shows how we use mvReadHttpResponseBody()
to access the body data within the response to a previously issued HTTP request. See the mvReadHttpResponseData()
example for the code that wraps this stanza. The functions server_log()
and server_error()
are not included here, but can be viewed in the sample HTTP code.
// Set up a buffer that we'll get Microvisor to write
// the response body into
uint8_t buffer[resp_data.body_length + 1];
memset((void *)buffer, 0x00, resp_data.body_length + 1);
status = mvReadHttpResponseBody(http_handles.channel, 0, buffer, resp_data.body_length);
if (status == MV_STATUS_OKAY) {
// Retrieved the body data successfully so log it
server_log("Message JSON:\n%s", buffer);
} else {
server_error("HTTP response body read status %i", status);
}
Need some help?
We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.