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 : * @return 0 if http_client_req() should proceed with the download,
99 : * <0 if http_client_req() should abort the download.
100 : */
101 1 : 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 1 : struct http_response {
109 : /** HTTP parser settings for the application usage */
110 1 : 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 1 : 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 1 : uint8_t *body_frag_start;
148 :
149 : /** Length of the body fragment contained in the recv_buf */
150 1 : size_t body_frag_len;
151 :
152 : /** Where the response is stored, this is to be
153 : * provided by the user.
154 : */
155 1 : uint8_t *recv_buf;
156 :
157 : /** Response buffer maximum length */
158 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : struct http_content_range content_range;
208 :
209 1 : uint8_t cl_present : 1; /**< Is Content-Length field present */
210 1 : uint8_t body_found : 1; /**< Is message body found */
211 1 : uint8_t message_complete : 1; /**< Is HTTP message parsing complete */
212 1 : 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 1 : struct http_client_internal_data {
218 : /** HTTP parser context */
219 1 : struct http_parser parser;
220 :
221 : /** HTTP parser settings */
222 1 : struct http_parser_settings parser_settings;
223 :
224 : /** HTTP response specific data (filled by http_client_req() when
225 : * data is received)
226 : */
227 1 : struct http_response response;
228 :
229 : /** User data */
230 1 : void *user_data;
231 :
232 : /** HTTP socket */
233 1 : 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 1 : struct http_request {
241 : /** HTTP client request internal data */
242 1 : struct http_client_internal_data internal;
243 :
244 : /* User should fill in following parameters */
245 :
246 : /** The HTTP method: GET, HEAD, OPTIONS, POST, ... */
247 1 : enum http_method method;
248 :
249 : /** User supplied callback function to call when response is
250 : * received.
251 : */
252 1 : 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 1 : const struct http_parser_settings *http_cb;
259 :
260 : /** User supplied buffer where received data is stored */
261 1 : uint8_t *recv_buf;
262 :
263 : /** Length of the user supplied receive buffer */
264 1 : 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 1 : size_t data_len;
272 :
273 : /** The URL for this request, for example: /index.html */
274 1 : const char *url;
275 :
276 : /** The HTTP protocol, for example "HTTP/1.1" */
277 1 : 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 1 : const char * const *header_fields;
286 :
287 : /** The value of the Content-Type header field, may be NULL */
288 1 : const char *content_type_value;
289 :
290 : /** Hostname to be used in the request */
291 1 : const char *host;
292 :
293 : /** Port number to be used in the request */
294 1 : 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 1 : http_payload_cb_t payload_cb;
303 :
304 : /** Payload, may be NULL */
305 1 : const char *payload;
306 :
307 : /** Payload length is used to calculate Content-Length. Set to 0
308 : * for chunked transfers.
309 : */
310 1 : 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 1 : 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 1 : 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 1 : 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_ */
|