1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * lws-minimal-http-server-custom-headers 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Written in 2010-2019 by Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * This file is made available under the Creative Commons CC0 1.0 7d4afb5ceSopenharmony_ci * Universal Public Domain Dedication. 8d4afb5ceSopenharmony_ci * 9d4afb5ceSopenharmony_ci * This demonstrates a minimal http server that can produce dynamic http 10d4afb5ceSopenharmony_ci * content as well as static content. 11d4afb5ceSopenharmony_ci * 12d4afb5ceSopenharmony_ci * To keep it simple, it serves the static stuff from the subdirectory 13d4afb5ceSopenharmony_ci * "./mount-origin" of the directory it was started in. 14d4afb5ceSopenharmony_ci * 15d4afb5ceSopenharmony_ci * You can change that by changing mount.origin below. 16d4afb5ceSopenharmony_ci */ 17d4afb5ceSopenharmony_ci 18d4afb5ceSopenharmony_ci#include <libwebsockets.h> 19d4afb5ceSopenharmony_ci#include <string.h> 20d4afb5ceSopenharmony_ci#include <signal.h> 21d4afb5ceSopenharmony_ci#include <time.h> 22d4afb5ceSopenharmony_ci 23d4afb5ceSopenharmony_cistatic int interrupted; 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_cistruct pss { 26d4afb5ceSopenharmony_ci char result[128 + LWS_PRE]; 27d4afb5ceSopenharmony_ci int len; 28d4afb5ceSopenharmony_ci}; 29d4afb5ceSopenharmony_ci 30d4afb5ceSopenharmony_ci/* 31d4afb5ceSopenharmony_ci * This just lets us override LWS_CALLBACK_HTTP handling before passing it 32d4afb5ceSopenharmony_ci * and everything else to the default handler. 33d4afb5ceSopenharmony_ci */ 34d4afb5ceSopenharmony_ci 35d4afb5ceSopenharmony_cistatic int 36d4afb5ceSopenharmony_cicallback_http(struct lws *wsi, enum lws_callback_reasons reason, 37d4afb5ceSopenharmony_ci void *user, void *in, size_t len) 38d4afb5ceSopenharmony_ci{ 39d4afb5ceSopenharmony_ci uint8_t buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *p = start, 40d4afb5ceSopenharmony_ci *end = &buf[sizeof(buf) - 1]; 41d4afb5ceSopenharmony_ci struct pss *pss = (struct pss *)user; 42d4afb5ceSopenharmony_ci char value[32], *pr = &pss->result[LWS_PRE]; 43d4afb5ceSopenharmony_ci size_t e = sizeof(pss->result) - LWS_PRE; 44d4afb5ceSopenharmony_ci int n; 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_ci switch (reason) { 47d4afb5ceSopenharmony_ci case LWS_CALLBACK_HTTP: 48d4afb5ceSopenharmony_ci /* 49d4afb5ceSopenharmony_ci * LWS doesn't have the "DNT" header built-in. But we can 50d4afb5ceSopenharmony_ci * query it using the "custom" versions of the header apis. 51d4afb5ceSopenharmony_ci * 52d4afb5ceSopenharmony_ci * You can set your modern browser to issue DNT, look in the 53d4afb5ceSopenharmony_ci * privacy settings of your browser. 54d4afb5ceSopenharmony_ci */ 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci pss->len = 0; 57d4afb5ceSopenharmony_ci n = lws_hdr_custom_length(wsi, "dnt:", 4); 58d4afb5ceSopenharmony_ci if (n < 0) 59d4afb5ceSopenharmony_ci pss->len = lws_snprintf(pr, e, 60d4afb5ceSopenharmony_ci "%s: DNT header not found\n", __func__); 61d4afb5ceSopenharmony_ci else { 62d4afb5ceSopenharmony_ci 63d4afb5ceSopenharmony_ci pss->len = lws_snprintf(pr, e, 64d4afb5ceSopenharmony_ci "%s: DNT length %d<br>", __func__, n); 65d4afb5ceSopenharmony_ci n = lws_hdr_custom_copy(wsi, value, sizeof(value), "dnt:", 4); 66d4afb5ceSopenharmony_ci if (n < 0) 67d4afb5ceSopenharmony_ci pss->len += lws_snprintf(pr + pss->len, e - (unsigned int)pss->len, 68d4afb5ceSopenharmony_ci "%s: unable to get DNT value\n", __func__); 69d4afb5ceSopenharmony_ci else 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci pss->len += lws_snprintf(pr + pss->len , e - (unsigned int)pss->len, 72d4afb5ceSopenharmony_ci "%s: DNT value '%s'\n", __func__, value); 73d4afb5ceSopenharmony_ci } 74d4afb5ceSopenharmony_ci 75d4afb5ceSopenharmony_ci lwsl_user("%s\n", pr); 76d4afb5ceSopenharmony_ci 77d4afb5ceSopenharmony_ci if (lws_add_http_common_headers(wsi, HTTP_STATUS_OK, 78d4afb5ceSopenharmony_ci "text/html", (lws_filepos_t)pss->len, &p, end)) 79d4afb5ceSopenharmony_ci return 1; 80d4afb5ceSopenharmony_ci 81d4afb5ceSopenharmony_ci if (lws_finalize_write_http_header(wsi, start, &p, end)) 82d4afb5ceSopenharmony_ci return 1; 83d4afb5ceSopenharmony_ci 84d4afb5ceSopenharmony_ci 85d4afb5ceSopenharmony_ci /* write the body separately */ 86d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 87d4afb5ceSopenharmony_ci return 0; 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci case LWS_CALLBACK_HTTP_WRITEABLE: 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci strcpy((char *)start, "hello"); 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci if (lws_write(wsi, (uint8_t *)pr, (unsigned int)pss->len, LWS_WRITE_HTTP_FINAL) != pss->len) 94d4afb5ceSopenharmony_ci return 1; 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci if (lws_http_transaction_completed(wsi)) 97d4afb5ceSopenharmony_ci return -1; 98d4afb5ceSopenharmony_ci return 0; 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci default: 101d4afb5ceSopenharmony_ci break; 102d4afb5ceSopenharmony_ci } 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci return lws_callback_http_dummy(wsi, reason, user, in, len); 105d4afb5ceSopenharmony_ci} 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_cistatic struct lws_protocols protocols[] = { 108d4afb5ceSopenharmony_ci { "http", callback_http, sizeof(struct pss), 0, 0, NULL, 0 }, 109d4afb5ceSopenharmony_ci LWS_PROTOCOL_LIST_TERM 110d4afb5ceSopenharmony_ci}; 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_cistatic const struct lws_http_mount mount_dyn = { 113d4afb5ceSopenharmony_ci /* .mount_next */ NULL, /* linked-list "next" */ 114d4afb5ceSopenharmony_ci /* .mountpoint */ "/dyn", /* mountpoint URL */ 115d4afb5ceSopenharmony_ci /* .origin */ NULL, /* protocol */ 116d4afb5ceSopenharmony_ci /* .def */ NULL, 117d4afb5ceSopenharmony_ci /* .protocol */ "http", 118d4afb5ceSopenharmony_ci /* .cgienv */ NULL, 119d4afb5ceSopenharmony_ci /* .extra_mimetypes */ NULL, 120d4afb5ceSopenharmony_ci /* .interpret */ NULL, 121d4afb5ceSopenharmony_ci /* .cgi_timeout */ 0, 122d4afb5ceSopenharmony_ci /* .cache_max_age */ 0, 123d4afb5ceSopenharmony_ci /* .auth_mask */ 0, 124d4afb5ceSopenharmony_ci /* .cache_reusable */ 0, 125d4afb5ceSopenharmony_ci /* .cache_revalidate */ 0, 126d4afb5ceSopenharmony_ci /* .cache_intermediaries */ 0, 127d4afb5ceSopenharmony_ci /* .origin_protocol */ LWSMPRO_CALLBACK, /* dynamic */ 128d4afb5ceSopenharmony_ci /* .mountpoint_len */ 4, /* char count */ 129d4afb5ceSopenharmony_ci /* .basic_auth_login_file */ NULL, 130d4afb5ceSopenharmony_ci}; 131d4afb5ceSopenharmony_ci 132d4afb5ceSopenharmony_ci/* default mount serves the URL space from ./mount-origin */ 133d4afb5ceSopenharmony_ci 134d4afb5ceSopenharmony_cistatic const struct lws_http_mount mount = { 135d4afb5ceSopenharmony_ci /* .mount_next */ &mount_dyn, /* linked-list "next" */ 136d4afb5ceSopenharmony_ci /* .mountpoint */ "/", /* mountpoint URL */ 137d4afb5ceSopenharmony_ci /* .origin */ "./mount-origin", /* serve from dir */ 138d4afb5ceSopenharmony_ci /* .def */ "index.html", /* default filename */ 139d4afb5ceSopenharmony_ci /* .protocol */ NULL, 140d4afb5ceSopenharmony_ci /* .cgienv */ NULL, 141d4afb5ceSopenharmony_ci /* .extra_mimetypes */ NULL, 142d4afb5ceSopenharmony_ci /* .interpret */ NULL, 143d4afb5ceSopenharmony_ci /* .cgi_timeout */ 0, 144d4afb5ceSopenharmony_ci /* .cache_max_age */ 0, 145d4afb5ceSopenharmony_ci /* .auth_mask */ 0, 146d4afb5ceSopenharmony_ci /* .cache_reusable */ 0, 147d4afb5ceSopenharmony_ci /* .cache_revalidate */ 0, 148d4afb5ceSopenharmony_ci /* .cache_intermediaries */ 0, 149d4afb5ceSopenharmony_ci /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ 150d4afb5ceSopenharmony_ci /* .mountpoint_len */ 1, /* char count */ 151d4afb5ceSopenharmony_ci /* .basic_auth_login_file */ NULL, 152d4afb5ceSopenharmony_ci}; 153d4afb5ceSopenharmony_ci 154d4afb5ceSopenharmony_civoid sigint_handler(int sig) 155d4afb5ceSopenharmony_ci{ 156d4afb5ceSopenharmony_ci interrupted = 1; 157d4afb5ceSopenharmony_ci} 158d4afb5ceSopenharmony_ci 159d4afb5ceSopenharmony_ciint main(int argc, const char **argv) 160d4afb5ceSopenharmony_ci{ 161d4afb5ceSopenharmony_ci struct lws_context_creation_info info; 162d4afb5ceSopenharmony_ci struct lws_context *context; 163d4afb5ceSopenharmony_ci const char *p; 164d4afb5ceSopenharmony_ci int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; 165d4afb5ceSopenharmony_ci 166d4afb5ceSopenharmony_ci signal(SIGINT, sigint_handler); 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci if ((p = lws_cmdline_option(argc, argv, "-d"))) 169d4afb5ceSopenharmony_ci logs = atoi(p); 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci lws_set_log_level(logs, NULL); 172d4afb5ceSopenharmony_ci lwsl_user("LWS minimal http server custom headers | visit http://localhost:7681\n"); 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ci memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 175d4afb5ceSopenharmony_ci info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | 176d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_EXPLICIT_VHOSTS | 177d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci /* for testing ah queue, not useful in real world */ 180d4afb5ceSopenharmony_ci if (lws_cmdline_option(argc, argv, "--ah1")) 181d4afb5ceSopenharmony_ci info.max_http_header_pool = 1; 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci context = lws_create_context(&info); 184d4afb5ceSopenharmony_ci if (!context) { 185d4afb5ceSopenharmony_ci lwsl_err("lws init failed\n"); 186d4afb5ceSopenharmony_ci return 1; 187d4afb5ceSopenharmony_ci } 188d4afb5ceSopenharmony_ci 189d4afb5ceSopenharmony_ci /* http on 7681 */ 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ci info.port = 7681; 192d4afb5ceSopenharmony_ci info.protocols = protocols; 193d4afb5ceSopenharmony_ci info.mounts = &mount; 194d4afb5ceSopenharmony_ci info.vhost_name = "http"; 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_ci if (!lws_create_vhost(context, &info)) { 197d4afb5ceSopenharmony_ci lwsl_err("Failed to create tls vhost\n"); 198d4afb5ceSopenharmony_ci goto bail; 199d4afb5ceSopenharmony_ci } 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci /* https on 7682 */ 202d4afb5ceSopenharmony_ci 203d4afb5ceSopenharmony_ci info.port = 7682; 204d4afb5ceSopenharmony_ci info.error_document_404 = "/404.html"; 205d4afb5ceSopenharmony_ci#if defined(LWS_WITH_TLS) 206d4afb5ceSopenharmony_ci info.ssl_cert_filepath = "localhost-100y.cert"; 207d4afb5ceSopenharmony_ci info.ssl_private_key_filepath = "localhost-100y.key"; 208d4afb5ceSopenharmony_ci#endif 209d4afb5ceSopenharmony_ci info.vhost_name = "https"; 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_ci if (!lws_create_vhost(context, &info)) { 212d4afb5ceSopenharmony_ci lwsl_err("Failed to create tls vhost\n"); 213d4afb5ceSopenharmony_ci goto bail; 214d4afb5ceSopenharmony_ci } 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci while (n >= 0 && !interrupted) 217d4afb5ceSopenharmony_ci n = lws_service(context, 0); 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_cibail: 220d4afb5ceSopenharmony_ci lws_context_destroy(context); 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_ci return 0; 223d4afb5ceSopenharmony_ci} 224