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