2 * lws-minimal-http-client
4 * Written in 2010-2019 by Andy Green <andy@warmcat.com>
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
9 * This demonstrates the a minimal http client using lws.
11 * It visits https://warmcat.com/ and receives the html page there. You
12 * can dump the page data by changing the #if 0 below.
15 #include <libwebsockets.h>
19 static int interrupted, bad = 1, status;
20 static struct lws *client_wsi;
23 callback_http(struct lws *wsi, enum lws_callback_reasons reason,
24 void *user, void *in, size_t len)
31 /* because we are protocols[0] ... */
32 case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
33 lwsl_err("CLIENT_CONNECTION_ERROR: %s\n",
34 in ? (char *)in : "(null)");
38 case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
40 unsigned char **p = (unsigned char **)in, *end = (*p) + len;
43 * How to send a custom header in the request to the server
46 if (lws_add_http_header_by_name(wsi,
47 (const unsigned char *)"dnt",
48 (const unsigned char *)"1", 1, p, end))
53 case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
54 status = lws_http_client_http_response(wsi);
55 lwsl_user("Connected with server response: %d\n", status);
58 * How to query custom headers (http 1.x only at the momemnt)
60 * warmcat.com sends a custom header "test-custom-header" for
61 * testing, it has the fixed value "hello".
64 n = lws_hdr_custom_length(wsi, "test-custom-header:", 19);
66 lwsl_notice("%s: Can't find test-custom-header\n",
69 if (lws_hdr_custom_copy(wsi, val, sizeof(val),
70 "test-custom-header:", 19) < 0)
71 lwsl_notice("%s: custom header too long\n",
74 lwsl_notice("%s: custom header: '%s'\n",
79 /* chunks of chunked content, with header removed */
80 case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
81 lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len);
82 #if 0 /* enable to dump the html */
93 return 0; /* don't passthru */
95 /* uninterpreted http content */
96 case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
98 char buffer[1024 + LWS_PRE];
99 char *px = buffer + LWS_PRE;
100 int lenx = sizeof(buffer) - LWS_PRE;
102 if (lws_http_client_read(wsi, &px, &lenx) < 0)
105 return 0; /* don't passthru */
107 case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
108 lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n");
111 lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
114 case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
117 lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
124 return lws_callback_http_dummy(wsi, reason, user, in, len);
127 static const struct lws_protocols protocols[] = {
138 sigint_handler(int sig)
143 int main(int argc, const char **argv)
145 struct lws_context_creation_info info;
146 struct lws_client_connect_info i;
147 struct lws_context *context;
149 int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
151 * For LLL_ verbosity above NOTICE to be built into lws,
152 * lws must have been configured and built with
153 * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE
155 * | LLL_INFO | LLL_PARSER | LLL_HEADER | LLL_EXT |
156 * LLL_CLIENT | LLL_LATENCY | LLL_DEBUG
159 signal(SIGINT, sigint_handler);
161 if ((p = lws_cmdline_option(argc, argv, "-d")))
164 lws_set_log_level(logs, NULL);
165 lwsl_user("LWS minimal http client Custom Headers [-d<verbosity>] [-l] [--h1]\n");
167 memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
168 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
169 info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
170 info.protocols = protocols;
172 * since we know this lws context is only ever going to be used with
173 * one client wsis / fds / sockets at a time, let lws know it doesn't
174 * have to use the default allocations for fd tables up to ulimit -n.
175 * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
178 info.fd_limit_per_thread = 1 + 1 + 1;
180 #if defined(LWS_WITH_MBEDTLS)
182 * OpenSSL uses the system trust store. mbedTLS has to be told which
183 * CA to trust explicitly.
185 info.client_ssl_ca_filepath = "./warmcat.com.cer";
188 context = lws_create_context(&info);
190 lwsl_err("lws init failed\n");
194 memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
197 if (!lws_cmdline_option(argc, argv, "-n"))
198 i.ssl_connection = LCCSCF_USE_SSL;
200 if (lws_cmdline_option(argc, argv, "-l")) {
202 i.address = "localhost";
203 i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED;
206 i.address = "warmcat.com";
209 /* currently custom headers receive only works with h1 */
214 i.origin = i.address;
217 i.protocol = protocols[0].name;
218 i.pwsi = &client_wsi;
219 lws_client_connect_via_info(&i);
221 while (n >= 0 && client_wsi && !interrupted)
222 n = lws_service(context, 0);
224 lws_context_destroy(context);
225 lwsl_user("Completed: %s\n", bad ? "failed" : "OK");