Line data Source code
1 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : struct http_response { 106 : /** HTTP parser settings for the application usage */ 107 1 : 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 1 : 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 1 : uint8_t *body_frag_start; 145 : 146 : /** Length of the body fragment contained in the recv_buf */ 147 1 : size_t body_frag_len; 148 : 149 : /** Where the response is stored, this is to be 150 : * provided by the user. 151 : */ 152 1 : uint8_t *recv_buf; 153 : 154 : /** Response buffer maximum length */ 155 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : uint16_t http_status_code; 199 : 200 1 : uint8_t cl_present : 1; /**< Is Content-Length field present */ 201 1 : uint8_t body_found : 1; /**< Is message body found */ 202 1 : 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 1 : struct http_client_internal_data { 208 : /** HTTP parser context */ 209 1 : struct http_parser parser; 210 : 211 : /** HTTP parser settings */ 212 1 : struct http_parser_settings parser_settings; 213 : 214 : /** HTTP response specific data (filled by http_client_req() when 215 : * data is received) 216 : */ 217 1 : struct http_response response; 218 : 219 : /** User data */ 220 1 : void *user_data; 221 : 222 : /** HTTP socket */ 223 1 : 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 1 : struct http_request { 231 : /** HTTP client request internal data */ 232 1 : struct http_client_internal_data internal; 233 : 234 : /* User should fill in following parameters */ 235 : 236 : /** The HTTP method: GET, HEAD, OPTIONS, POST, ... */ 237 1 : enum http_method method; 238 : 239 : /** User supplied callback function to call when response is 240 : * received. 241 : */ 242 1 : 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 1 : const struct http_parser_settings *http_cb; 249 : 250 : /** User supplied buffer where received data is stored */ 251 1 : uint8_t *recv_buf; 252 : 253 : /** Length of the user supplied receive buffer */ 254 1 : size_t recv_buf_len; 255 : 256 : /** The URL for this request, for example: /index.html */ 257 1 : const char *url; 258 : 259 : /** The HTTP protocol, for example "HTTP/1.1" */ 260 1 : 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 1 : const char **header_fields; 269 : 270 : /** The value of the Content-Type header field, may be NULL */ 271 1 : const char *content_type_value; 272 : 273 : /** Hostname to be used in the request */ 274 1 : const char *host; 275 : 276 : /** Port number to be used in the request */ 277 1 : 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 1 : http_payload_cb_t payload_cb; 286 : 287 : /** Payload, may be NULL */ 288 1 : const char *payload; 289 : 290 : /** Payload length is used to calculate Content-Length. Set to 0 291 : * for chunked transfers. 292 : */ 293 1 : 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 1 : 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 1 : 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 1 : 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_ */