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