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