#include #include #include #include "httpd.h" #include "httpd-utils.h" #include "cgi-espfs.h" #include "httpd-heap.h" extern unsigned char espfs_image[]; extern unsigned int espfs_image_len; httpd_thread_handle_t *s_serverHandle = NULL; struct SharedData { int visits; }; static struct SharedData shared = {}; struct RequestData { int counter; }; /** "About" page */ httpd_cgi_state templateReplacer(HttpdConnData *conn, const char *token) { struct RequestData *rd; if (!token) { if (conn->userData) { httpdFree(conn->userData); conn->userData = NULL; } return HTTPD_CGI_DONE; } if (!conn->userData) { rd = httpdMalloc(sizeof(struct RequestData)); conn->userData = rd; rd->counter = 0; shared.visits++; } else { rd = conn->userData; } char buf[100]; if (streq(token, "visits")) { sprintf(buf, "%d", shared.visits); tplSend(conn, buf); } else if (streq(token, "html1")) { tplSend(conn, "foo"); } else if (streq(token, "html2")) { tplSend(conn, "bar"); } else if (streq(token, "json1")) { tplSend(conn, "\"hello\":\"foo'' and backslash\\ \" also crlf \r\n"); } else if (streq(token, "multipart")) { if (rd->counter < 100) { sprintf(buf, "HELLO %d, ", rd->counter); tplSend(conn, buf); rd->counter++; return HTTPD_CGI_MORE; } tplSend(conn, "and that's it."); } else { return HTTPD_CGI_NOTFOUND; } return HTTPD_CGI_DONE; } httpd_cgi_state cgiStartSession(HttpdConnData *conn) { httpdQueueHeader(conn, "X-Foo", "FOO"); httpdQueueHeader(conn, "X-Bar", "Bar"); char cbuf[100] = {}; httpdGetCookie(conn, "testCookie", cbuf, 100); printf("Cookie val = %s\n", cbuf); httpdSetCookie(conn, &(SetCookie) { .name = "testCookie", .value = "lala-lele", // .domain = "localhost", // .expires = "BABABABAx", // .httponly = true, .maxAge = 0, // .path = "foo/bar/baz", // .sameSite = COOKIE_SAMESITE_LAX, // .secure = true, }); return HTTPD_CGI_NOTFOUND; } /** * Application routes */ const HttpdBuiltInUrl routes[] = { // TODO password lock ... ROUTE_CGI("*", cgiStartSession), // --- Web pages --- // ROUTE_TPL_FILE("/", tplIndex, "/index.tpl"), ROUTE_FILE("/", "index.html"), ROUTE_TPL_FILE("/tpl", templateReplacer, "template.tpl.txt"), ROUTE_FILESYSTEM(), ROUTE_END(), }; void sigpipe_handler(int signum) { (void) signum; } void handle_sigint(int signum) { (void) signum; fprintf(stderr, " SIGINT detected, shutting down HTTPD\n"); httpdShutdown(s_serverHandle); } int main(void) { struct sigaction action; memset(&action, 0, sizeof(action)); action.sa_handler = handle_sigint; sigaction(SIGINT, &action, NULL); // prevent abort on sigpipe sigaction(SIGPIPE, &(struct sigaction) {{sigpipe_handler},.sa_mask={}}, NULL); struct httpd_init_options opts = { .port = 8080, }; s_serverHandle = httpdStart(routes, &opts); httpdSetName("SpriteHTTPD Server Demo"); httpdJoin(s_serverHandle); return 0; } int httpdPlatEspfsRead(void *dest, size_t offset, size_t len) { if (offset + len > espfs_image_len) { return -1; } memcpy(dest, &espfs_image[offset], len); return 0; }