2022-03-15 21:43:53 -04:00
|
|
|
/* Feel free to use this example code in any way
|
|
|
|
you see fit (Public Domain) */
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
//#ifndef _WIN32
|
|
|
|
#include <sys/select.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
//#else
|
|
|
|
//#include <winsock2.h>
|
|
|
|
//#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include <microhttpd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "web.h"
|
2022-03-19 22:25:20 -04:00
|
|
|
#include "tokens.h"
|
2022-03-15 21:43:53 -04:00
|
|
|
|
2022-03-18 11:23:19 -04:00
|
|
|
#ifdef _MHD_FLAGS_ENUM
|
|
|
|
typedef enum MHD_Result HttpResult;
|
|
|
|
#else
|
|
|
|
typedef int HttpResult;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int requestDefinition = -1;
|
|
|
|
|
2022-03-15 21:43:53 -04:00
|
|
|
int routeCount = 0;
|
|
|
|
struct Route routes[10];
|
|
|
|
|
2022-03-19 21:28:17 -04:00
|
|
|
int addRoute(struct Route route)
|
|
|
|
{
|
|
|
|
routes[routeCount] = route;
|
|
|
|
routeCount += 1;
|
|
|
|
return 0;
|
2022-03-15 21:43:53 -04:00
|
|
|
}
|
|
|
|
|
2022-03-15 23:22:28 -04:00
|
|
|
int methodMatches(const char* method, struct Route* route)
|
|
|
|
{
|
2022-03-19 21:28:17 -04:00
|
|
|
switch (route->type) {
|
|
|
|
case GET:
|
|
|
|
return method[0] == 'G' || method[0] == 'g';
|
|
|
|
case POST:
|
2022-03-19 21:53:18 -04:00
|
|
|
return (method[0] == 'P' || method[0] == 'p') && (method[1] == 'O' || method[1] == 'o');
|
2022-03-19 21:28:17 -04:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
2022-03-15 23:22:28 -04:00
|
|
|
}
|
|
|
|
|
2022-03-18 11:23:19 -04:00
|
|
|
static HttpResult
|
2022-03-19 22:25:20 -04:00
|
|
|
add_query_param(void* queryParamsV, enum MHD_ValueKind kind, const char* key,
|
|
|
|
const char* value)
|
2022-03-17 16:59:08 -04:00
|
|
|
{
|
|
|
|
(void) kind; /* Unused. Silent compiler warning. */
|
|
|
|
Object* queryParams = queryParamsV;
|
|
|
|
|
|
|
|
Object pair = startList(stringFromSlice(key, strlen(key)));
|
2022-03-19 22:25:20 -04:00
|
|
|
Object parsed;
|
|
|
|
if (isDigit(value[0])) {
|
|
|
|
parsed = parseEval(value, NULL);
|
|
|
|
} else {
|
|
|
|
parsed = stringFromSlice(value, strlen(value));
|
|
|
|
}
|
|
|
|
nf_addToList(&pair, parsed);
|
2022-03-17 16:59:08 -04:00
|
|
|
nf_addToList(queryParams, pair);
|
|
|
|
|
|
|
|
return MHD_YES;
|
|
|
|
}
|
|
|
|
|
2022-03-18 11:23:19 -04:00
|
|
|
static HttpResult
|
2022-03-19 21:28:17 -04:00
|
|
|
answer_to_connection(void* cls, struct MHD_Connection* connection,
|
|
|
|
const char* url, const char* method,
|
|
|
|
const char* version, const char* upload_data,
|
|
|
|
size_t* upload_data_size, void** con_cls)
|
2022-03-15 21:43:53 -04:00
|
|
|
{
|
2022-03-19 21:28:17 -04:00
|
|
|
char* page = NULL;
|
2022-03-18 11:23:19 -04:00
|
|
|
printf("%s URL: '%s' :: ", method, url);
|
|
|
|
printf("version: %s\n", version);
|
|
|
|
printf("upload_data: %s\n", upload_data);
|
|
|
|
for (int i = 0; i < routeCount; i++) {
|
|
|
|
if (methodMatches(method, &routes[i]) && strcmp(url, routes[i].path) == 0) {
|
|
|
|
Object queryParams = listObject();
|
2022-03-19 22:25:20 -04:00
|
|
|
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, add_query_param, &queryParams);
|
2022-03-18 11:23:19 -04:00
|
|
|
|
2022-03-21 12:33:35 -04:00
|
|
|
Object res = numberObject(1010);//structObject(requestDefinition);
|
|
|
|
//res.structObject->fields[0] = queryParams;
|
2022-03-18 11:23:19 -04:00
|
|
|
Object route = cloneObject(routes[i].routeAction);
|
|
|
|
|
|
|
|
Object result = listEvalLambda(&route, &res, routes[i].env);
|
|
|
|
cleanObject(&res);
|
|
|
|
page = result.string;
|
|
|
|
break;
|
|
|
|
}
|
2022-03-15 21:43:53 -04:00
|
|
|
}
|
|
|
|
|
2022-03-18 11:23:19 -04:00
|
|
|
if (!page) {
|
|
|
|
printf("no route found!\n");
|
|
|
|
page = "<html><body><h1>404, Dumbass.</h1></body></html>";
|
|
|
|
}
|
2022-03-15 21:43:53 -04:00
|
|
|
|
2022-03-18 11:23:19 -04:00
|
|
|
(void) cls; /* Unused. Silent compiler warning. */
|
|
|
|
(void) url; /* Unused. Silent compiler warning. */
|
|
|
|
(void) method; /* Unused. Silent compiler warning. */
|
|
|
|
(void) version; /* Unused. Silent compiler warning. */
|
|
|
|
(void) upload_data; /* Unused. Silent compiler warning. */
|
|
|
|
(void) upload_data_size; /* Unused. Silent compiler warning. */
|
|
|
|
(void) con_cls; /* Unused. Silent compiler warning. */
|
|
|
|
|
2022-03-19 21:28:17 -04:00
|
|
|
struct MHD_Response* response = MHD_create_response_from_buffer(
|
|
|
|
strlen(page), (void*) page, MHD_RESPMEM_PERSISTENT);
|
|
|
|
HttpResult ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
|
2022-03-18 11:23:19 -04:00
|
|
|
MHD_destroy_response(response);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int initialized = 0;
|
2022-03-19 21:28:17 -04:00
|
|
|
|
2022-03-18 11:23:19 -04:00
|
|
|
void initialize()
|
|
|
|
{
|
|
|
|
if (!initialized) {
|
|
|
|
Object o = parseEval("(struct Request (queryParams))", global());
|
|
|
|
cleanObject(&o);
|
2022-03-27 18:52:56 -04:00
|
|
|
requestDefinition = getStructIndex("Request");
|
2022-03-18 11:23:19 -04:00
|
|
|
}
|
|
|
|
initialized = 1;
|
2022-03-15 21:43:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int start(int port)
|
|
|
|
{
|
2022-03-18 11:23:19 -04:00
|
|
|
initialize();
|
2022-03-19 21:28:17 -04:00
|
|
|
struct MHD_Daemon* daemon = MHD_start_daemon(
|
2022-03-18 11:23:19 -04:00
|
|
|
MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD,
|
|
|
|
port, NULL, NULL, &answer_to_connection, NULL, MHD_OPTION_END);
|
2022-03-15 21:43:53 -04:00
|
|
|
|
2022-03-19 21:28:17 -04:00
|
|
|
if (NULL == daemon) {
|
2022-03-18 11:23:19 -04:00
|
|
|
return 1;
|
2022-03-19 21:28:17 -04:00
|
|
|
}
|
2022-03-15 21:43:53 -04:00
|
|
|
|
2022-03-18 11:23:19 -04:00
|
|
|
return 0;
|
2022-03-15 21:43:53 -04:00
|
|
|
}
|
2022-03-20 03:50:43 -04:00
|
|
|
|
|
|
|
void addRouteO(Object path, Object textFunc, struct Environment* env, enum RouteType type)
|
|
|
|
{
|
|
|
|
char* p = malloc(sizeof(char) * strlen(path.string) + 1);
|
|
|
|
strcpy(p, path.string);
|
|
|
|
|
|
|
|
struct Route r;
|
|
|
|
r.path = p;
|
|
|
|
r.routeAction = cloneObject(textFunc);
|
|
|
|
r.env = env;
|
|
|
|
r.type = type;
|
|
|
|
env->refs += 1;
|
|
|
|
addRoute(r);
|
|
|
|
}
|
|
|
|
|
2022-03-24 16:56:52 -04:00
|
|
|
Object addGetRoute(Object* params, int length, struct Environment* env)
|
2022-03-20 03:50:43 -04:00
|
|
|
{
|
2022-03-24 16:56:52 -04:00
|
|
|
Object path = params[0];
|
|
|
|
Object textFunc = params[1];
|
2022-03-20 03:50:43 -04:00
|
|
|
addRouteO(path, textFunc, env, GET);
|
|
|
|
return numberObject(1);
|
|
|
|
}
|
|
|
|
|
2022-03-24 16:56:52 -04:00
|
|
|
Object addPostRoute(Object* params, int length, struct Environment* env)
|
2022-03-20 03:50:43 -04:00
|
|
|
{
|
2022-03-24 16:56:52 -04:00
|
|
|
Object path = params[0];
|
|
|
|
Object textFunc = params[1];
|
2022-03-20 03:50:43 -04:00
|
|
|
addRouteO(path, textFunc, env, POST);
|
|
|
|
return numberObject(1);
|
|
|
|
}
|
|
|
|
|
2022-03-24 16:56:52 -04:00
|
|
|
Object startServer(Object* params, int length, struct Environment* env)
|
2022-03-20 03:50:43 -04:00
|
|
|
{
|
2022-03-24 16:56:52 -04:00
|
|
|
Object portObject = params[0];
|
|
|
|
|
2022-03-20 03:50:43 -04:00
|
|
|
int port = 8888;
|
|
|
|
if (portObject.type == TYPE_NUMBER) {
|
|
|
|
port = portObject.number;
|
|
|
|
}
|
|
|
|
return numberObject(start(port));
|
|
|
|
}
|