|
|
|
#include <stdio.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "httpd.h"
|
|
|
|
#include "httpd-utils.h"
|
|
|
|
#include "cgi-espfs.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) {
|
|
|
|
httpdPlatFree(conn->userData);
|
|
|
|
conn->userData = NULL;
|
|
|
|
}
|
|
|
|
return HTTPD_CGI_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!conn->userData) {
|
|
|
|
rd = httpdPlatMalloc(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, "<a href=\"foo\">foo</a>");
|
|
|
|
}
|
|
|
|
else if (streq(token, "html2")) {
|
|
|
|
tplSend(conn, "<a href=\"bar\">bar</a>");
|
|
|
|
}
|
|
|
|
else if (streq(token, "json1")) {
|
|
|
|
tplSend(conn, "\"hello\":\"foo<angle>'' 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;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
//int httpdGetCookie(HttpdConnData *conn, const char *name, char *buff, size_t buffLen)
|
|
|
|
//{
|
|
|
|
// httpdGetHeader(conn, "Cookie", )
|
|
|
|
//}
|
|
|
|
|
|
|
|
httpd_cgi_state cgiStartSession(HttpdConnData *conn)
|
|
|
|
{
|
|
|
|
httpdQueueHeader(conn, "X-Foo", "FOO");
|
|
|
|
httpdQueueHeader(conn, "X-Bar", "Bar");
|
|
|
|
|
|
|
|
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_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;
|
|
|
|
}
|