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 typedef void (*http_response_cb_t)(struct http_response *rsp, 99 enum http_final_call final_data, 100 void *user_data); 101 102 /** 103 * HTTP response from the server. 104 */ 105 struct http_response { 106 /** HTTP parser settings for the application usage */ 107 const struct http_parser_settings *http_cb; 108 109 /** User provided HTTP response callback which is 110 * called when a response is received to a sent HTTP 111 * request. 112 */ 113 http_response_cb_t cb; 114 115 /** 116 * recv_buffer that contains header + body 117 * _______________________________________ 118 * 119 * |←-------- body_frag_len ---------→| 120 * |←--------------------- data len --------------------→| 121 * --------------------------------------------------------------- 122 * ..header | header | body | body.. 123 * --------------------------------------------------------------- 124 * ↑ ↑ 125 * recv_buf body_frag_start 126 * 127 * 128 * recv_buffer that contains body only 129 * ___________________________________ 130 * 131 * |←------------------ body_frag_len ------------------→| 132 * |←--------------------- data len --------------------→| 133 * --------------------------------------------------------------- 134 * ..header/body | body | body.. 135 * --------------------------------------------------------------- 136 * ↑ 137 * recv_buf 138 * body_frag_start 139 * 140 * body_frag_start >= recv_buf 141 * body_frag_len = data_len - (body_frag_start - recv_buf) 142 */ 143 /** Start address of the body fragment contained in the recv_buf */ 144 uint8_t *body_frag_start; 145 146 /** Length of the body fragment contained in the recv_buf */ 147 size_t body_frag_len; 148 149 /** Where the response is stored, this is to be 150 * provided by the user. 151 */ 152 uint8_t *recv_buf; 153 154 /** Response buffer maximum length */ 155 size_t recv_buf_len; 156 157 /** Length of the data in the result buf. If the value 158 * is larger than recv_buf_len, then it means that 159 * the data is truncated and could not be fully copied 160 * into recv_buf. This can only happen if the user 161 * did not set the response callback. If the callback 162 * is set, then the HTTP client API will call response 163 * callback many times so that all the data is 164 * delivered to the user. Will be zero in the event of 165 * a null response. 166 */ 167 size_t data_len; 168 169 /** HTTP Content-Length field value. Will be set to zero 170 * in the event of a null response. 171 */ 172 size_t content_length; 173 174 /** Amount of data given to the response callback so far, including the 175 * current data given to the callback. This should be equal to the 176 * content_length field once the entire body has been received. Will be 177 * zero if a null response is given. 178 */ 179 size_t processed; 180 181 /** See https://tools.ietf.org/html/rfc7230#section-3.1.2 for more information. 182 * The status-code element is a 3-digit integer code 183 * 184 * The reason-phrase element exists for the sole 185 * purpose of providing a textual description 186 * associated with the numeric status code. A client 187 * SHOULD ignore the reason-phrase content. 188 * 189 * Will be blank if a null HTTP response is given. 190 */ 191 char http_status[HTTP_STATUS_STR_SIZE]; 192 193 /** Numeric HTTP status code which corresponds to the 194 * textual description. Set to zero if null response is 195 * given. Otherwise, will be a 3-digit integer code if 196 * valid HTTP response is given. 197 */ 198 uint16_t http_status_code; 199 200 uint8_t cl_present : 1; /**< Is Content-Length field present */ 201 uint8_t body_found : 1; /**< Is message body found */ 202 uint8_t message_complete : 1; /**< Is HTTP message parsing complete */ 203 }; 204 205 /** HTTP client internal data that the application should not touch 206 */ 207 struct http_client_internal_data { 208 /** HTTP parser context */ 209 struct http_parser parser; 210 211 /** HTTP parser settings */ 212 struct http_parser_settings parser_settings; 213 214 /** HTTP response specific data (filled by http_client_req() when 215 * data is received) 216 */ 217 struct http_response response; 218 219 /** User data */ 220 void *user_data; 221 222 /** HTTP socket */ 223 int sock; 224 }; 225 226 /** 227 * HTTP client request. This contains all the data that is needed when doing 228 * a HTTP request. 229 */ 230 struct http_request { 231 /** HTTP client request internal data */ 232 struct http_client_internal_data internal; 233 234 /* User should fill in following parameters */ 235 236 /** The HTTP method: GET, HEAD, OPTIONS, POST, ... */ 237 enum http_method method; 238 239 /** User supplied callback function to call when response is 240 * received. 241 */ 242 http_response_cb_t response; 243 244 /** User supplied list of HTTP callback functions if the 245 * calling application wants to know the parsing status or the HTTP 246 * fields. This is optional and normally not needed. 247 */ 248 const struct http_parser_settings *http_cb; 249 250 /** User supplied buffer where received data is stored */ 251 uint8_t *recv_buf; 252 253 /** Length of the user supplied receive buffer */ 254 size_t recv_buf_len; 255 256 /** The URL for this request, for example: /index.html */ 257 const char *url; 258 259 /** The HTTP protocol, for example "HTTP/1.1" */ 260 const char *protocol; 261 262 /** The HTTP header fields (application specific) 263 * The Content-Type may be specified here or in the next field. 264 * Depending on your application, the Content-Type may vary, however 265 * some header fields may remain constant through the application's 266 * life cycle. This is a NULL terminated list of header fields. 267 */ 268 const char **header_fields; 269 270 /** The value of the Content-Type header field, may be NULL */ 271 const char *content_type_value; 272 273 /** Hostname to be used in the request */ 274 const char *host; 275 276 /** Port number to be used in the request */ 277 const char *port; 278 279 /** User supplied callback function to call when payload 280 * needs to be sent. This can be NULL in which case the payload field 281 * in http_request is used. The idea of this payload callback is to 282 * allow user to send more data that is practical to store in allocated 283 * memory. 284 */ 285 http_payload_cb_t payload_cb; 286 287 /** Payload, may be NULL */ 288 const char *payload; 289 290 /** Payload length is used to calculate Content-Length. Set to 0 291 * for chunked transfers. 292 */ 293 size_t payload_len; 294 295 /** User supplied callback function to call when optional headers need 296 * to be sent. This can be NULL, in which case the optional_headers 297 * field in http_request is used. The idea of this optional_headers 298 * callback is to allow user to send more HTTP header data that is 299 * practical to store in allocated memory. 300 */ 301 http_header_cb_t optional_headers_cb; 302 303 /** A NULL terminated list of any optional headers that 304 * should be added to the HTTP request. May be NULL. 305 * If the optional_headers_cb is specified, then this field is ignored. 306 * Note that there are two similar fields that contain headers, 307 * the header_fields above and this optional_headers. This is done 308 * like this to support Websocket use case where Websocket will use 309 * header_fields variable and any optional application specific 310 * headers will be placed into this field. 311 */ 312 const char **optional_headers; 313 }; 314 315 /** 316 * @brief Do a HTTP request. The callback is called when data is received 317 * from the HTTP server. The caller must have created a connection to the 318 * server before calling this function so connect() call must have be done 319 * successfully for the socket. 320 * 321 * @param sock Socket id of the connection. 322 * @param req HTTP request information 323 * @param timeout Max timeout to wait for the data. The timeout value cannot be 324 * 0 as there would be no time to receive the data. 325 * The timeout value is in milliseconds. 326 * @param user_data User specified data that is passed to the callback. 327 * 328 * @return <0 if error, >=0 amount of data sent to the server 329 */ 330 int http_client_req(int sock, struct http_request *req, 331 int32_t timeout, void *user_data); 332 333 #ifdef __cplusplus 334 } 335 #endif 336 337 /** 338 * @} 339 */ 340 341 #endif /* ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ */ 342