Skip to content

Commit ef9d61d

Browse files
committed
net: http: client: Initial version
Simple HTTP client API. Signed-off-by: Jukka Rissanen <[email protected]>
1 parent 110332c commit ef9d61d

File tree

5 files changed

+883
-2
lines changed

5 files changed

+883
-2
lines changed

include/net/http_client.h

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
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 <kernel.h>
24+
25+
#include <net/net_ip.h>
26+
#include <net/http_parser.h>
27+
28+
#ifdef __cplusplus
29+
extern "C" {
30+
#endif
31+
32+
#if !defined(HTTP_CRLF)
33+
#define HTTP_CRLF "\r\n"
34+
#endif
35+
36+
#if !defined(HTTP_STATUS_STR_SIZE)
37+
#define HTTP_STATUS_STR_SIZE 32
38+
#endif
39+
40+
/* Is there more data to come */
41+
enum http_final_call {
42+
HTTP_DATA_MORE = 0,
43+
HTTP_DATA_FINAL = 1,
44+
};
45+
46+
struct http_request;
47+
struct http_response;
48+
49+
/**
50+
* @typedef http_payload_cb_t
51+
* @brief Callback used when data needs to be sent to the server.
52+
*
53+
* @param sock Socket id of the connection
54+
* @param req HTTP request information
55+
* @param user_data User specified data specified in http_client_req()
56+
*
57+
* @return >=0 amount of data sent, in this case http_client_req() should
58+
* continue sending data,
59+
* <0 if http_client_req() should return the error code to the
60+
* caller.
61+
*/
62+
typedef int (*http_payload_cb_t)(int sock,
63+
struct http_request *req,
64+
void *user_data);
65+
66+
/**
67+
* @typedef http_response_cb_t
68+
* @brief Callback used when data is received from the server.
69+
*
70+
* @param sock Socket id of the connection
71+
* @param req HTTP request information
72+
* @param recv_buf User supplied buffer where received data is stored
73+
* @param recv_buf_len Length of the user supplied receive buffer
74+
* @param data_len Received data len, if this is larger than recv_buf_len,
75+
* then some data was skipped.
76+
* @param final_data Does this data buffer contain all the data or
77+
* is there still more data to come.
78+
* @param user_data User specified data specified in http_client_req()
79+
*
80+
* @return 0 if http_client_req() should continue processing data (if not
81+
* all data is received), <0 if http_client_req() should return
82+
* the error code to the caller. If all data has been received,
83+
* then http_client_req() will return to the caller.
84+
*/
85+
typedef int (*http_response_cb_t)(struct http_response *rsp,
86+
enum http_final_call final_data,
87+
void *user_data);
88+
89+
/**
90+
* HTTP response from the server.
91+
*/
92+
struct http_response {
93+
/** HTTP parser settings for the application usage */
94+
const struct http_parser_settings *http_cb;
95+
96+
/** User provided HTTP response callback which is
97+
* called when a response is received to a sent HTTP
98+
* request.
99+
*/
100+
http_response_cb_t cb;
101+
102+
/** Where the body starts */
103+
u8_t *body_start;
104+
105+
/** Where the response is stored, this is to be
106+
* provided by the user.
107+
*/
108+
u8_t *recv_buf;
109+
110+
/** Response buffer maximum length */
111+
size_t recv_buf_len;
112+
113+
/** Length of the data in the result buf. If the value
114+
* is larger than response_buf_len, then it means that
115+
* the data is truncated and could not be fully copied
116+
* into response_buf. This can only happen if the user
117+
* did not set the response callback. If the callback
118+
* is set, then the HTTP client API will call response
119+
* callback many times so that all the data is
120+
* delivered to the user.
121+
*/
122+
size_t data_len;
123+
124+
/** HTTP Content-Length field value */
125+
size_t content_length;
126+
127+
/** Content length parsed. This should be the same as
128+
* the content_length field if parsing was ok.
129+
*/
130+
size_t processed;
131+
132+
/* https://tools.ietf.org/html/rfc7230#section-3.1.2
133+
* The status-code element is a 3-digit integer code
134+
*
135+
* The reason-phrase element exists for the sole
136+
* purpose of providing a textual description
137+
* associated with the numeric status code. A client
138+
* SHOULD ignore the reason-phrase content.
139+
*/
140+
char http_status[HTTP_STATUS_STR_SIZE];
141+
142+
u8_t cl_present:1;
143+
u8_t body_found:1;
144+
u8_t message_complete:1;
145+
};
146+
147+
/**
148+
* HTTP client request. This contains all the data that is needed when doing
149+
* a HTTP request.
150+
*/
151+
struct http_request {
152+
/** HTTP parser context */
153+
struct http_parser parser;
154+
155+
/** HTTP parser settings */
156+
struct http_parser_settings parser_settings;
157+
158+
/** HTTP response specific data (filled by http_client_req() when
159+
* data is received)
160+
*/
161+
struct http_response response;
162+
163+
/** User data */
164+
void *user_data;
165+
166+
/** HTTP socket */
167+
int sock;
168+
169+
/** Request timeout */
170+
s32_t timeout;
171+
172+
/* User should fill in following parameters */
173+
174+
/** The HTTP method: GET, HEAD, OPTIONS, POST, ... */
175+
enum http_method method;
176+
177+
/** The URL for this request, for example: /index.html */
178+
const char *url;
179+
180+
/** The HTTP protocol, for example "HTTP/1.1" */
181+
const char *protocol;
182+
183+
/** The HTTP header fields (application specific)
184+
* The Content-Type may be specified here or in the next field.
185+
* Depending on your application, the Content-Type may vary, however
186+
* some header fields may remain constant through the application's
187+
* life cycle. This is a NULL terminated list of header fields.
188+
*/
189+
char **header_fields;
190+
191+
/** The value of the Content-Type header field, may be NULL */
192+
const char *content_type_value;
193+
194+
/** Hostname to be used in the request */
195+
const char *host;
196+
197+
/** User supplied callback function to call when payload
198+
* needs to be sent. This can be NULL in which case the payload field
199+
* in http_request is used. The idea of this payload callback is to
200+
* allow user to send more data that is practical to store in allocated
201+
* memory.
202+
*/
203+
http_payload_cb_t payload_cb;
204+
205+
/** Payload, may be NULL */
206+
const char *payload;
207+
208+
/** Payload length, may be 0. Only used if payload field is not NULL */
209+
size_t payload_len;
210+
};
211+
212+
/**
213+
* @brief Do a HTTP request. The callback is called when data is received
214+
* from the HTTP server. The caller must have created a connection to the
215+
* server before calling this function so connect() call must have be done
216+
* successfully for the socket.
217+
*
218+
* @param sock Socket id of the connection.
219+
* @param req HTTP request information
220+
* @param optional_headers A NULL terminated list of any optional headers that
221+
* should be added to the HTTP request.
222+
* @param response User supplied callback function to call when response is
223+
* received
224+
* @param http_cb User supplied list of callback functions if the
225+
* calling application wants to know the parsing status or the HTTP
226+
* fields. This is optional parameter and normally not needed.
227+
* @param recv_buf User supplied buffer where received data is stored
228+
* @param recv_buf_len Length of the user supplied receive buffer
229+
* @param timeout Max timeout to wait for the data. The timeout value cannot be
230+
* 0 as there would be no time to receive the data.
231+
* @param user_data User specified data that is passed to the callback.
232+
*
233+
* @return <0 if error, >=0 amount of data sent to the server
234+
*/
235+
int http_client_req(int sock, struct http_request *req,
236+
const char **optional_headers,
237+
http_response_cb_t response,
238+
const struct http_parser_settings *http_cb,
239+
u8_t *recv_buf, size_t recv_buf_len,
240+
s32_t timeout, void *user_data);
241+
242+
#ifdef __cplusplus
243+
}
244+
#endif
245+
246+
/**
247+
* @}
248+
*/
249+
250+
#endif /* ZEPHYR_INCLUDE_NET_HTTP_CLIENT_H_ */

subsys/net/lib/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ if (CONFIG_DNS_RESOLVER
1717
add_subdirectory(dns)
1818
endif()
1919

20-
if(CONFIG_HTTP_PARSER_URL
21-
OR CONFIG_HTTP_PARSER)
20+
if(CONFIG_HTTP_PARSER_URL OR CONFIG_HTTP_PARSER OR CONFIG_HTTP_CLIENT)
2221
add_subdirectory(http)
2322
endif()
2423

subsys/net/lib/http/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@ if(CONFIG_HTTP_PARSER_STRICT)
66
zephyr_library_compile_definitions(HTTP_PARSER_STRICT)
77
endif()
88

9+
zephyr_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
10+
911
zephyr_library_sources_if_kconfig(http_parser.c)
1012
zephyr_library_sources_if_kconfig(http_parser_url.c)
13+
zephyr_library_sources_if_kconfig(http_client.c)

subsys/net/lib/http/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,16 @@ config HTTP_PARSER_STRICT
2323
depends on (HTTP_PARSER || HTTP_PARSER_URL)
2424
help
2525
This option enables the strict parsing option
26+
27+
config HTTP_CLIENT
28+
bool "HTTP client API [EXPERIMENTAL]"
29+
select HTTP_PARSER
30+
select HTTP_PARSER_URL
31+
help
32+
HTTP client API
33+
34+
module = NET_HTTP
35+
module-dep = NET_LOG
36+
module-str = Log level for HTTP client library
37+
module-help = Enables HTTP client code to output debug messages.
38+
source "subsys/net/Kconfig.template.log_config.net"

0 commit comments

Comments
 (0)