1 /** @file 2 * @brief HTTP client API 3 * 4 * An API for applications do HTTP requests 5 */ 6 7 /* 8 * Copyright (c) 2019 Intel Corporation 9 * 10 * SPDX-License-Identifier: Apache-2.0 11 */ 12 13 #ifndef ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ 14 #define ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ 15 16 /** 17 * @brief HTTP client API 18 * @defgroup http_client HTTP client API 19 * @ingroup networking 20 * @{ 21 */ 22 23 #include <kernel.h> 24 #include <net/net_ip.h> 25 #include <net/http_parser.h> 26 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 #if !defined(HTTP_CRLF) 32 #define HTTP_CRLF "\r\n" 33 #endif 34 35 #if !defined(HTTP_STATUS_STR_SIZE) 36 #define HTTP_STATUS_STR_SIZE 32 37 #endif 38 39 /* Is there more data to come */ 40 enum http_final_call { 41 HTTP_DATA_MORE = 0, 42 HTTP_DATA_FINAL = 1, 43 }; 44 45 struct http_request; 46 struct http_response; 47 48 /** 49 * @typedef http_payload_cb_t 50 * @brief Callback used when data needs to be sent to the server. 51 * 52 * @param sock Socket id of the connection 53 * @param req HTTP request information 54 * @param user_data User specified data specified in http_client_req() 55 * 56 * @return >=0 amount of data sent, in this case http_client_req() should 57 * continue sending data, 58 * <0 if http_client_req() should return the error code to the 59 * caller. 60 */ 61 typedef int (*http_payload_cb_t)(int sock, 62 struct http_request *req, 63 void *user_data); 64 65 /** 66 * @typedef http_header_cb_t 67 * @brief Callback can be used if application wants to construct additional 68 * HTTP headers when the HTTP request is sent. Usage of this is optional. 69 * 70 * @param sock Socket id of the connection 71 * @param req HTTP request information 72 * @param user_data User specified data specified in http_client_req() 73 * 74 * @return >=0 amount of data sent, in this case http_client_req() should 75 * continue sending data, 76 * <0 if http_client_req() should return the error code to the 77 * caller. 78 */ 79 typedef int (*http_header_cb_t)(int sock, 80 struct http_request *req, 81 void *user_data); 82 83 /** 84 * @typedef http_response_cb_t 85 * @brief Callback used when data is received from the server. 86 * 87 * @param rsp HTTP response information 88 * @param final_data Does this data buffer contain all the data or 89 * is there still more data to come. 90 * @param user_data User specified data specified in http_client_req() 91 */ 92 typedef void (*http_response_cb_t)(struct http_response *rsp, 93 enum http_final_call final_data, 94 void *user_data); 95 96 /** 97 * HTTP response from the server. 98 */ 99 struct http_response { 100 /** HTTP parser settings for the application usage */ 101 const struct http_parser_settings *http_cb; 102 103 /** User provided HTTP response callback which is 104 * called when a response is received to a sent HTTP 105 * request. 106 */ 107 http_response_cb_t cb; 108 109 /** Where the body starts */ 110 uint8_t *body_start; 111 112 /** Where the response is stored, this is to be 113 * provided by the user. 114 */ 115 uint8_t *recv_buf; 116 117 /** Response buffer maximum length */ 118 size_t recv_buf_len; 119 120 /** Length of the data in the result buf. If the value 121 * is larger than recv_buf_len, then it means that 122 * the data is truncated and could not be fully copied 123 * into recv_buf. This can only happen if the user 124 * did not set the response callback. If the callback 125 * is set, then the HTTP client API will call response 126 * callback many times so that all the data is 127 * delivered to the user. 128 */ 129 size_t data_len; 130 131 /** HTTP Content-Length field value */ 132 size_t content_length; 133 134 /** Content length parsed. This should be the same as 135 * the content_length field if parsing was ok. 136 */ 137 size_t processed; 138 139 /* https://tools.ietf.org/html/rfc7230#section-3.1.2 140 * The status-code element is a 3-digit integer code 141 * 142 * The reason-phrase element exists for the sole 143 * purpose of providing a textual description 144 * associated with the numeric status code. A client 145 * SHOULD ignore the reason-phrase content. 146 */ 147 char http_status[HTTP_STATUS_STR_SIZE]; 148 149 /** Numeric HTTP status code which corresponds to the 150 * textual description. 151 */ 152 uint16_t http_status_code; 153 154 uint8_t cl_present : 1; 155 uint8_t body_found : 1; 156 uint8_t message_complete : 1; 157 }; 158 159 /** HTTP client internal data that the application should not touch 160 */ 161 struct http_client_internal_data { 162 /** Work for handling timeout */ 163 struct k_work_delayable work; 164 165 /** HTTP parser context */ 166 struct http_parser parser; 167 168 /** HTTP parser settings */ 169 struct http_parser_settings parser_settings; 170 171 /** HTTP response specific data (filled by http_client_req() when 172 * data is received) 173 */ 174 struct http_response response; 175 176 /** User data */ 177 void *user_data; 178 179 /** HTTP socket */ 180 int sock; 181 182 /** Request timeout */ 183 k_timeout_t timeout; 184 }; 185 186 /** 187 * HTTP client request. This contains all the data that is needed when doing 188 * a HTTP request. 189 */ 190 struct http_request { 191 /** HTTP client request internal data */ 192 struct http_client_internal_data internal; 193 194 /* User should fill in following parameters */ 195 196 /** The HTTP method: GET, HEAD, OPTIONS, POST, ... */ 197 enum http_method method; 198 199 /** User supplied callback function to call when response is 200 * received. 201 */ 202 http_response_cb_t response; 203 204 /** User supplied list of HTTP callback functions if the 205 * calling application wants to know the parsing status or the HTTP 206 * fields. This is optional and normally not needed. 207 */ 208 const struct http_parser_settings *http_cb; 209 210 /** User supplied buffer where received data is stored */ 211 uint8_t *recv_buf; 212 213 /** Length of the user supplied receive buffer */ 214 size_t recv_buf_len; 215 216 /** The URL for this request, for example: /index.html */ 217 const char *url; 218 219 /** The HTTP protocol, for example "HTTP/1.1" */ 220 const char *protocol; 221 222 /** The HTTP header fields (application specific) 223 * The Content-Type may be specified here or in the next field. 224 * Depending on your application, the Content-Type may vary, however 225 * some header fields may remain constant through the application's 226 * life cycle. This is a NULL terminated list of header fields. 227 */ 228 const char **header_fields; 229 230 /** The value of the Content-Type header field, may be NULL */ 231 const char *content_type_value; 232 233 /** Hostname to be used in the request */ 234 const char *host; 235 236 /** Port number to be used in the request */ 237 const char *port; 238 239 /** User supplied callback function to call when payload 240 * needs to be sent. This can be NULL in which case the payload field 241 * in http_request is used. The idea of this payload callback is to 242 * allow user to send more data that is practical to store in allocated 243 * memory. 244 */ 245 http_payload_cb_t payload_cb; 246 247 /** Payload, may be NULL */ 248 const char *payload; 249 250 /** Payload length is used to calculate Content-Length. Set to 0 251 * for chunked transfers. 252 */ 253 size_t payload_len; 254 255 /** User supplied callback function to call when optional headers need 256 * to be sent. This can be NULL, in which case the optional_headers 257 * field in http_request is used. The idea of this optional_headers 258 * callback is to allow user to send more HTTP header data that is 259 * practical to store in allocated memory. 260 */ 261 http_header_cb_t optional_headers_cb; 262 263 /** A NULL terminated list of any optional headers that 264 * should be added to the HTTP request. May be NULL. 265 * If the optional_headers_cb is specified, then this field is ignored. 266 * Note that there are two similar fields that contain headers, 267 * the header_fields above and this optional_headers. This is done 268 * like this to support Websocket use case where Websocket will use 269 * header_fields variable and any optional application specific 270 * headers will be placed into this field. 271 */ 272 const char **optional_headers; 273 }; 274 275 /** 276 * @brief Do a HTTP request. The callback is called when data is received 277 * from the HTTP server. The caller must have created a connection to the 278 * server before calling this function so connect() call must have be done 279 * successfully for the socket. 280 * 281 * @param sock Socket id of the connection. 282 * @param req HTTP request information 283 * @param timeout Max timeout to wait for the data. The timeout value cannot be 284 * 0 as there would be no time to receive the data. 285 * The timeout value is in milliseconds. 286 * @param user_data User specified data that is passed to the callback. 287 * 288 * @return <0 if error, >=0 amount of data sent to the server 289 */ 290 int http_client_req(int sock, struct http_request *req, 291 int32_t timeout, void *user_data); 292 293 #ifdef __cplusplus 294 } 295 #endif 296 297 /** 298 * @} 299 */ 300 301 #endif /* ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ */ 302