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 * @since 2.1 20 * @version 0.2.0 21 * @ingroup networking 22 * @{ 23 */ 24 25 #include <zephyr/kernel.h> 26 #include <zephyr/net/net_ip.h> 27 #include <zephyr/net/http/parser.h> 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 /** @cond INTERNAL_HIDDEN */ 34 35 #if !defined(HTTP_CRLF) 36 #define HTTP_CRLF "\r\n" 37 #endif 38 39 #if !defined(HTTP_STATUS_STR_SIZE) 40 #define HTTP_STATUS_STR_SIZE 32 41 #endif 42 43 /** @endcond */ 44 45 /** Is there more data to come */ 46 enum http_final_call { 47 HTTP_DATA_MORE = 0, /**< More data will come */ 48 HTTP_DATA_FINAL = 1, /**< End of data */ 49 }; 50 51 struct http_request; 52 struct http_response; 53 54 /** 55 * @typedef http_payload_cb_t 56 * @brief Callback used when data needs to be sent to the server. 57 * 58 * @param sock Socket id of the connection 59 * @param req HTTP request information 60 * @param user_data User specified data specified in http_client_req() 61 * 62 * @return >=0 amount of data sent, in this case http_client_req() should 63 * continue sending data, 64 * <0 if http_client_req() should return the error code to the 65 * caller. 66 */ 67 typedef int (*http_payload_cb_t)(int sock, 68 struct http_request *req, 69 void *user_data); 70 71 /** 72 * @typedef http_header_cb_t 73 * @brief Callback can be used if application wants to construct additional 74 * HTTP headers when the HTTP request is sent. Usage of this is optional. 75 * 76 * @param sock Socket id of the connection 77 * @param req HTTP request information 78 * @param user_data User specified data specified in http_client_req() 79 * 80 * @return >=0 amount of data sent, in this case http_client_req() should 81 * continue sending data, 82 * <0 if http_client_req() should return the error code to the 83 * caller. 84 */ 85 typedef int (*http_header_cb_t)(int sock, 86 struct http_request *req, 87 void *user_data); 88 89 /** 90 * @typedef http_response_cb_t 91 * @brief Callback used when data is received from the server. 92 * 93 * @param rsp HTTP response information 94 * @param final_data Does this data buffer contain all the data or 95 * is there still more data to come. 96 * @param user_data User specified data specified in http_client_req() 97 * 98 * @return 0 if http_client_req() should proceed with the download, 99 * <0 if http_client_req() should abort the download. 100 */ 101 typedef int (*http_response_cb_t)(struct http_response *rsp, 102 enum http_final_call final_data, 103 void *user_data); 104 105 /** 106 * HTTP response from the server. 107 */ 108 struct http_response { 109 /** HTTP parser settings for the application usage */ 110 const struct http_parser_settings *http_cb; 111 112 /** User provided HTTP response callback which is 113 * called when a response is received to a sent HTTP 114 * request. 115 */ 116 http_response_cb_t cb; 117 118 /** 119 * recv_buffer that contains header + body 120 * _______________________________________ 121 * 122 * |←-------- body_frag_len ---------→| 123 * |←--------------------- data len --------------------→| 124 * --------------------------------------------------------------- 125 * ..header | header | body | body.. 126 * --------------------------------------------------------------- 127 * ↑ ↑ 128 * recv_buf body_frag_start 129 * 130 * 131 * recv_buffer that contains body only 132 * ___________________________________ 133 * 134 * |←------------------ body_frag_len ------------------→| 135 * |←--------------------- data len --------------------→| 136 * --------------------------------------------------------------- 137 * ..header/body | body | body.. 138 * --------------------------------------------------------------- 139 * ↑ 140 * recv_buf 141 * body_frag_start 142 * 143 * body_frag_start >= recv_buf 144 * body_frag_len = data_len - (body_frag_start - recv_buf) 145 */ 146 /** Start address of the body fragment contained in the recv_buf */ 147 uint8_t *body_frag_start; 148 149 /** Length of the body fragment contained in the recv_buf */ 150 size_t body_frag_len; 151 152 /** Where the response is stored, this is to be 153 * provided by the user. 154 */ 155 uint8_t *recv_buf; 156 157 /** Response buffer maximum length */ 158 size_t recv_buf_len; 159 160 /** Length of the data in the result buf. If the value 161 * is larger than recv_buf_len, then it means that 162 * the data is truncated and could not be fully copied 163 * into recv_buf. This can only happen if the user 164 * did not set the response callback. If the callback 165 * is set, then the HTTP client API will call response 166 * callback many times so that all the data is 167 * delivered to the user. Will be zero in the event of 168 * a null response. 169 */ 170 size_t data_len; 171 172 /** HTTP Content-Length field value. Will be set to zero 173 * in the event of a null response. 174 */ 175 size_t content_length; 176 177 /** Amount of data given to the response callback so far, including the 178 * current data given to the callback. This should be equal to the 179 * content_length field once the entire body has been received. Will be 180 * zero if a null response is given. 181 */ 182 size_t processed; 183 184 /** See https://tools.ietf.org/html/rfc7230#section-3.1.2 for more information. 185 * The status-code element is a 3-digit integer code 186 * 187 * The reason-phrase element exists for the sole 188 * purpose of providing a textual description 189 * associated with the numeric status code. A client 190 * SHOULD ignore the reason-phrase content. 191 * 192 * Will be blank if a null HTTP response is given. 193 */ 194 char http_status[HTTP_STATUS_STR_SIZE]; 195 196 /** Numeric HTTP status code which corresponds to the 197 * textual description. Set to zero if null response is 198 * given. Otherwise, will be a 3-digit integer code if 199 * valid HTTP response is given. 200 */ 201 uint16_t http_status_code; 202 203 /** 204 * HTTP Content-Range response field value. Consist of range_start, 205 * range_end and total_size. Total is set to 0 if not supplied. 206 */ 207 struct http_content_range content_range; 208 209 uint8_t cl_present : 1; /**< Is Content-Length field present */ 210 uint8_t body_found : 1; /**< Is message body found */ 211 uint8_t message_complete : 1; /**< Is HTTP message parsing complete */ 212 uint8_t cr_present : 1; /**< Is Content-Range field present */ 213 }; 214 215 /** HTTP client internal data that the application should not touch 216 */ 217 struct http_client_internal_data { 218 /** HTTP parser context */ 219 struct http_parser parser; 220 221 /** HTTP parser settings */ 222 struct http_parser_settings parser_settings; 223 224 /** HTTP response specific data (filled by http_client_req() when 225 * data is received) 226 */ 227 struct http_response response; 228 229 /** User data */ 230 void *user_data; 231 232 /** HTTP socket */ 233 int sock; 234 }; 235 236 /** 237 * HTTP client request. This contains all the data that is needed when doing 238 * a HTTP request. 239 */ 240 struct http_request { 241 /** HTTP client request internal data */ 242 struct http_client_internal_data internal; 243 244 /* User should fill in following parameters */ 245 246 /** The HTTP method: GET, HEAD, OPTIONS, POST, ... */ 247 enum http_method method; 248 249 /** User supplied callback function to call when response is 250 * received. 251 */ 252 http_response_cb_t response; 253 254 /** User supplied list of HTTP callback functions if the 255 * calling application wants to know the parsing status or the HTTP 256 * fields. This is optional and normally not needed. 257 */ 258 const struct http_parser_settings *http_cb; 259 260 /** User supplied buffer where received data is stored */ 261 uint8_t *recv_buf; 262 263 /** Length of the user supplied receive buffer */ 264 size_t recv_buf_len; 265 266 /** Length of the unprocessed data left inside the user supplied receive 267 * buffer. In typical HTTP processing this should be 0, however in case 268 * of switching protocols, there may be some data left belonging to the 269 * new protocol. 270 */ 271 size_t data_len; 272 273 /** The URL for this request, for example: /index.html */ 274 const char *url; 275 276 /** The HTTP protocol, for example "HTTP/1.1" */ 277 const char *protocol; 278 279 /** The HTTP header fields (application specific) 280 * The Content-Type may be specified here or in the next field. 281 * Depending on your application, the Content-Type may vary, however 282 * some header fields may remain constant through the application's 283 * life cycle. This is a NULL terminated list of header fields. 284 */ 285 const char * const *header_fields; 286 287 /** The value of the Content-Type header field, may be NULL */ 288 const char *content_type_value; 289 290 /** Hostname to be used in the request */ 291 const char *host; 292 293 /** Port number to be used in the request */ 294 const char *port; 295 296 /** User supplied callback function to call when payload 297 * needs to be sent. This can be NULL in which case the payload field 298 * in http_request is used. The idea of this payload callback is to 299 * allow user to send more data that is practical to store in allocated 300 * memory. 301 */ 302 http_payload_cb_t payload_cb; 303 304 /** Payload, may be NULL */ 305 const char *payload; 306 307 /** Payload length is used to calculate Content-Length. Set to 0 308 * for chunked transfers. 309 */ 310 size_t payload_len; 311 312 /** User supplied callback function to call when optional headers need 313 * to be sent. This can be NULL, in which case the optional_headers 314 * field in http_request is used. The idea of this optional_headers 315 * callback is to allow user to send more HTTP header data that is 316 * practical to store in allocated memory. 317 */ 318 http_header_cb_t optional_headers_cb; 319 320 /** A NULL terminated list of any optional headers that 321 * should be added to the HTTP request. May be NULL. 322 * If the optional_headers_cb is specified, then this field is ignored. 323 * Note that there are two similar fields that contain headers, 324 * the header_fields above and this optional_headers. This is done 325 * like this to support Websocket use case where Websocket will use 326 * header_fields variable and any optional application specific 327 * headers will be placed into this field. 328 */ 329 const char **optional_headers; 330 }; 331 332 /** 333 * @brief Do a HTTP request. The callback is called when data is received 334 * from the HTTP server. The caller must have created a connection to the 335 * server before calling this function so connect() call must have be done 336 * successfully for the socket. 337 * 338 * @param sock Socket id of the connection. 339 * @param req HTTP request information 340 * @param timeout Max timeout to wait for the data. The timeout value cannot be 341 * 0 as there would be no time to receive the data. 342 * The timeout value is in milliseconds. 343 * @param user_data User specified data that is passed to the callback. 344 * 345 * @return <0 if error, >=0 amount of data sent to the server 346 */ 347 int http_client_req(int sock, struct http_request *req, 348 int32_t timeout, void *user_data); 349 350 #ifdef __cplusplus 351 } 352 #endif 353 354 /** 355 * @} 356 */ 357 358 #endif /* ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ */ 359