| /** @file |
| * @brief HTTP client API |
| * |
| * An API for applications do HTTP requests |
| */ |
| |
| /* |
| * Copyright (c) 2019 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ |
| #define ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ |
| |
| /** |
| * @brief HTTP client API |
| * @defgroup http_client HTTP client API |
| * @ingroup networking |
| * @{ |
| */ |
| |
| #include <kernel.h> |
| #include <net/net_ip.h> |
| #include <net/http_parser.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #if !defined(HTTP_CRLF) |
| #define HTTP_CRLF "\r\n" |
| #endif |
| |
| #if !defined(HTTP_STATUS_STR_SIZE) |
| #define HTTP_STATUS_STR_SIZE 32 |
| #endif |
| |
| /* Is there more data to come */ |
| enum http_final_call { |
| HTTP_DATA_MORE = 0, |
| HTTP_DATA_FINAL = 1, |
| }; |
| |
| struct http_request; |
| struct http_response; |
| |
| /** |
| * @typedef http_payload_cb_t |
| * @brief Callback used when data needs to be sent to the server. |
| * |
| * @param sock Socket id of the connection |
| * @param req HTTP request information |
| * @param user_data User specified data specified in http_client_req() |
| * |
| * @return >=0 amount of data sent, in this case http_client_req() should |
| * continue sending data, |
| * <0 if http_client_req() should return the error code to the |
| * caller. |
| */ |
| typedef int (*http_payload_cb_t)(int sock, |
| struct http_request *req, |
| void *user_data); |
| |
| /** |
| * @typedef http_header_cb_t |
| * @brief Callback can be used if application wants to construct additional |
| * HTTP headers when the HTTP request is sent. Usage of this is optional. |
| * |
| * @param sock Socket id of the connection |
| * @param req HTTP request information |
| * @param user_data User specified data specified in http_client_req() |
| * |
| * @return >=0 amount of data sent, in this case http_client_req() should |
| * continue sending data, |
| * <0 if http_client_req() should return the error code to the |
| * caller. |
| */ |
| typedef int (*http_header_cb_t)(int sock, |
| struct http_request *req, |
| void *user_data); |
| |
| /** |
| * @typedef http_response_cb_t |
| * @brief Callback used when data is received from the server. |
| * |
| * @param rsp HTTP response information |
| * @param final_data Does this data buffer contain all the data or |
| * is there still more data to come. |
| * @param user_data User specified data specified in http_client_req() |
| */ |
| typedef void (*http_response_cb_t)(struct http_response *rsp, |
| enum http_final_call final_data, |
| void *user_data); |
| |
| /** |
| * HTTP response from the server. |
| */ |
| struct http_response { |
| /** HTTP parser settings for the application usage */ |
| const struct http_parser_settings *http_cb; |
| |
| /** User provided HTTP response callback which is |
| * called when a response is received to a sent HTTP |
| * request. |
| */ |
| http_response_cb_t cb; |
| |
| /** Where the body starts */ |
| uint8_t *body_start; |
| |
| /** Where the response is stored, this is to be |
| * provided by the user. |
| */ |
| uint8_t *recv_buf; |
| |
| /** Response buffer maximum length */ |
| size_t recv_buf_len; |
| |
| /** Length of the data in the result buf. If the value |
| * is larger than recv_buf_len, then it means that |
| * the data is truncated and could not be fully copied |
| * into recv_buf. This can only happen if the user |
| * did not set the response callback. If the callback |
| * is set, then the HTTP client API will call response |
| * callback many times so that all the data is |
| * delivered to the user. |
| */ |
| size_t data_len; |
| |
| /** HTTP Content-Length field value */ |
| size_t content_length; |
| |
| /** Content length parsed. This should be the same as |
| * the content_length field if parsing was ok. |
| */ |
| size_t processed; |
| |
| /* https://tools.ietf.org/html/rfc7230#section-3.1.2 |
| * The status-code element is a 3-digit integer code |
| * |
| * The reason-phrase element exists for the sole |
| * purpose of providing a textual description |
| * associated with the numeric status code. A client |
| * SHOULD ignore the reason-phrase content. |
| */ |
| char http_status[HTTP_STATUS_STR_SIZE]; |
| |
| /** Numeric HTTP status code which corresponds to the |
| * textual description. |
| */ |
| uint16_t http_status_code; |
| |
| uint8_t cl_present : 1; |
| uint8_t body_found : 1; |
| uint8_t message_complete : 1; |
| }; |
| |
| /** HTTP client internal data that the application should not touch |
| */ |
| struct http_client_internal_data { |
| /** Work for handling timeout */ |
| struct k_work_delayable work; |
| |
| /** HTTP parser context */ |
| struct http_parser parser; |
| |
| /** HTTP parser settings */ |
| struct http_parser_settings parser_settings; |
| |
| /** HTTP response specific data (filled by http_client_req() when |
| * data is received) |
| */ |
| struct http_response response; |
| |
| /** User data */ |
| void *user_data; |
| |
| /** HTTP socket */ |
| int sock; |
| |
| /** Request timeout */ |
| k_timeout_t timeout; |
| }; |
| |
| /** |
| * HTTP client request. This contains all the data that is needed when doing |
| * a HTTP request. |
| */ |
| struct http_request { |
| /** HTTP client request internal data */ |
| struct http_client_internal_data internal; |
| |
| /* User should fill in following parameters */ |
| |
| /** The HTTP method: GET, HEAD, OPTIONS, POST, ... */ |
| enum http_method method; |
| |
| /** User supplied callback function to call when response is |
| * received. |
| */ |
| http_response_cb_t response; |
| |
| /** User supplied list of HTTP callback functions if the |
| * calling application wants to know the parsing status or the HTTP |
| * fields. This is optional and normally not needed. |
| */ |
| const struct http_parser_settings *http_cb; |
| |
| /** User supplied buffer where received data is stored */ |
| uint8_t *recv_buf; |
| |
| /** Length of the user supplied receive buffer */ |
| size_t recv_buf_len; |
| |
| /** The URL for this request, for example: /index.html */ |
| const char *url; |
| |
| /** The HTTP protocol, for example "HTTP/1.1" */ |
| const char *protocol; |
| |
| /** The HTTP header fields (application specific) |
| * The Content-Type may be specified here or in the next field. |
| * Depending on your application, the Content-Type may vary, however |
| * some header fields may remain constant through the application's |
| * life cycle. This is a NULL terminated list of header fields. |
| */ |
| const char **header_fields; |
| |
| /** The value of the Content-Type header field, may be NULL */ |
| const char *content_type_value; |
| |
| /** Hostname to be used in the request */ |
| const char *host; |
| |
| /** Port number to be used in the request */ |
| const char *port; |
| |
| /** User supplied callback function to call when payload |
| * needs to be sent. This can be NULL in which case the payload field |
| * in http_request is used. The idea of this payload callback is to |
| * allow user to send more data that is practical to store in allocated |
| * memory. |
| */ |
| http_payload_cb_t payload_cb; |
| |
| /** Payload, may be NULL */ |
| const char *payload; |
| |
| /** Payload length is used to calculate Content-Length. Set to 0 |
| * for chunked transfers. |
| */ |
| size_t payload_len; |
| |
| /** User supplied callback function to call when optional headers need |
| * to be sent. This can be NULL, in which case the optional_headers |
| * field in http_request is used. The idea of this optional_headers |
| * callback is to allow user to send more HTTP header data that is |
| * practical to store in allocated memory. |
| */ |
| http_header_cb_t optional_headers_cb; |
| |
| /** A NULL terminated list of any optional headers that |
| * should be added to the HTTP request. May be NULL. |
| * If the optional_headers_cb is specified, then this field is ignored. |
| * Note that there are two similar fields that contain headers, |
| * the header_fields above and this optional_headers. This is done |
| * like this to support Websocket use case where Websocket will use |
| * header_fields variable and any optional application specific |
| * headers will be placed into this field. |
| */ |
| const char **optional_headers; |
| }; |
| |
| /** |
| * @brief Do a HTTP request. The callback is called when data is received |
| * from the HTTP server. The caller must have created a connection to the |
| * server before calling this function so connect() call must have be done |
| * successfully for the socket. |
| * |
| * @param sock Socket id of the connection. |
| * @param req HTTP request information |
| * @param timeout Max timeout to wait for the data. The timeout value cannot be |
| * 0 as there would be no time to receive the data. |
| * The timeout value is in milliseconds. |
| * @param user_data User specified data that is passed to the callback. |
| * |
| * @return <0 if error, >=0 amount of data sent to the server |
| */ |
| int http_client_req(int sock, struct http_request *req, |
| int32_t timeout, void *user_data); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| /** |
| * @} |
| */ |
| |
| #endif /* ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ */ |