aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/endpoints.c90
-rw-r--r--src/main.c24
2 files changed, 56 insertions, 58 deletions
diff --git a/src/endpoints.c b/src/endpoints.c
index 8d1c05f..a4ac35a 100644
--- a/src/endpoints.c
+++ b/src/endpoints.c
@@ -8,25 +8,30 @@
#include <microhttpd.h>
+#include "common.h"
+#include "sql.h"
#include <log.h>
#define CONTAINER_IMPLEMENTATION
#define JACSON_IMPLEMENTATION
#define JACSON_EXPORT_RSNPRINTF
#include <jacson.h>
-
-#include "common.h"
-#include "sql.h"
+#define STRINGBUILDER_IMPLEMENTATION
+#include <stringbuilder.h>
+
+#define OUT(arg) jac_sb_append_buf(&resp, arg)
+
+#define REQUIRE_METHOD(methodvar, methodstr, statusp) \
+do { \
+ if (strcmp((methodvar), (methodstr)) != 0) { \
+ *statusp = MHD_HTTP_METHOD_NOT_ALLOWED; \
+ return NULL; \
+ } \
+} while (0)
const char *const JSON_ERROR = "{\"error\":\"%s\"}";
const char *const HTML_ERROR = "<!DOCTYPE html><html><body>Error: %s</body></html>";
-const char *const INSUFFICIENT_ARGUMENTS = "insufficient arguments";
-const char *const INVALID_ARGUMENTS = "invalid arguments";
-const char *const OCCUPIED = "occupied";
-const char *const SERVER_ERRORMSG = "server error";
-const char *const UNKNOWN = "unknown";
-const char *const HTML_PROLOGUE = "<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body>";
-const char *const HTML_EPILOGUE = "</html></body>";
+const char *HTTPHOSTNAME = "http://127.0.0.1:80";
struct global_args {
enum {
@@ -43,19 +48,6 @@ static const struct fmt_const fmts[] = {
[GA_FMT_HTML] = {HTML_ERROR,"text/html"}
};
-// string builder
-struct sb {
- char* str;
- size_t sz;
- size_t ln;
-};
-
-size_t sbprintf(struct sb* s, const char* fmt, ...) {
- va_list l;
- va_start(l, fmt);
- return s->ln += __jacson_vrsnprintf(&s->str, &s->sz, s->ln, fmt, l);
-}
-
struct global_args parse_global_args(struct MHD_Connection *connection) {
const char* key, *val;
struct global_args ret = { .format = GA_FMT_JSON };
@@ -65,62 +57,68 @@ struct global_args parse_global_args(struct MHD_Connection *connection) {
return ret;
}
+void init(const char *db) {
+ sqlite_init(db);
+ const char *new_httphostname = getenv("HTTPHOSTNAME");
+ if (new_httphostname) HTTPHOSTNAME = new_httphostname;
+}
+
// index, path: /
struct MHD_Response *ENDP_(struct MHD_Connection* connection, int *status) {
return get_from_file("www/index.html");
}
enum MHD_Result arg_builder (void *cls, enum MHD_ValueKind kind, const char *key, const char *value) {
- struct sb *html = cls;
- html->ln += __jacson_rsnprintf(&html->str, &html->sz, html->ln, "<li><p style=\"font-style:monospace;\">%s: %s</p></li>", key, value);
+ jac_sb *html = cls;
+ jac_sb_snprintf(html, "<li><p style=\"font-style:monospace;\">%s: %s</p></li>", key, value ? value : "&lt;none&gt;");
return MHD_YES;
}
// path: /getargs
-struct MHD_Response *ENDP_getargs(struct MHD_Connection *connection, int *status) {
- struct sb html = {calloc(64, 1), 63, 0};
- html.ln += __jacson_rsnprintf(&html.str, &html.sz, html.ln,
- "<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body><h3>List of arguments</h3><ol>");
- MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &arg_builder, &html);
- html.ln += __jacson_rsnprintf(&html.str, &html.sz, html.ln, "</ol></body></html>");
- const char *val = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "test");
- if (val) LDEBUGVF(stderr, "test = %s\n", val);
- LDEBUGVF(stderr, "test pointer = %p", val);
- return MHD_create_response_from_buffer(html.ln, html.str, MHD_RESPMEM_MUST_FREE);
+struct MHD_Response *ENDP_getargs(const char *method, struct MHD_Connection *connection, int *status) {
+ jac_sb resp = jac_sb_new(64);
+# include "template/args.html"
+ return MHD_create_response_from_buffer(resp.size, resp.data, MHD_RESPMEM_MUST_FREE);
}
// API, path: /api/linkadd
-struct MHD_Response *ENDP_api_linkadd(struct MHD_Connection *connection, int *status) {
+struct MHD_Response *ENDP_api_linkadd(const char *method, struct MHD_Connection *connection, int *status) {
+ REQUIRE_METHOD(method, "GET", status);
const char *url = NULL, *path = NULL;
char newurl[12] = {0}, *newurlp = newurl;
- struct sb resp = {malloc(64), 63, 0};
+ jac_sb resp = jac_sb_new(64);
struct global_args glob = parse_global_args(connection);
struct MHD_Response *response;
if ((url = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "url")) == NULL || *url == '\0') {
*status = db_error_status(DBERROR_ARGS);
- sbprintf(&resp, fmts[glob.format].error, INSUFFICIENT_ARGUMENTS);
+ jac_sb_snprintf(&resp, fmts[glob.format].error, db_error(DBERROR_ARGS));
goto exit;
}
path = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "try");
- if (*path == '\0') path = NULL;
+ if (path && *path == '\0') path = NULL;
enum dberror err;
if ((err = db_add_url(url, path, &newurlp)) != DBERROR_SUCCESS) {
LWARNVF("Database write failed with error %i. Sql error: %s", err, sqlite3_errmsg(state.db));
*status = db_error_status(err);
- sbprintf(&resp, fmts[glob.format].error, db_error(err));
+ jac_sb_snprintf(&resp, fmts[glob.format].error, db_error(err));
goto exit;
}
- if (glob.format == GA_FMT_JSON) sbprintf(&resp, "{\"url\":\"%s\"}", newurlp);
- else sbprintf(&resp, "%sYour URL: <a href=\"/%s\">/%s</a>%s", HTML_PROLOGUE, newurlp, newurlp, HTML_EPILOGUE);
+ if (glob.format == GA_FMT_JSON)
+ jac_sb_snprintf(&resp, "{\"url\":\"%s\"}", newurlp);
+ else if (glob.format == GA_FMT_HTML) {
+# include "template/linkadd.html"
+ }
exit:
- response = MHD_create_response_from_buffer(resp.ln, resp.str, MHD_RESPMEM_MUST_FREE);
+ response = MHD_create_response_from_buffer(resp.size, resp.data, MHD_RESPMEM_MUST_FREE);
MHD_add_response_header(response, "Content-Type", fmts[glob.format].content_type);
return response;
}
// API, path: /api/linkdel
-struct MHD_Response *ENDP_api_linkdel(struct MHD_Connection *connection, int *status) {
-
+struct MHD_Response *ENDP_api_linkdel(const char *method, struct MHD_Connection *connection, int *status) {
+ return MHD_create_response_from_buffer(4, "TODO", MHD_RESPMEM_PERSISTENT);
}
// API, path: /api/linkget
-struct MHD_Response *ENDP_api_linkget(struct MHD_Connection *connection, int *status) { }
+struct MHD_Response *ENDP_api_linkget(const char *method, struct MHD_Connection *connection, int *status) {
+ return MHD_create_response_from_buffer(4, "TODO", MHD_RESPMEM_PERSISTENT);
+}
diff --git a/src/main.c b/src/main.c
index 431a9a7..67c4559 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,7 +49,7 @@ enum MHD_Result process_connection(void *cls, struct MHD_Connection *connection,
} else if (handler != NULL) {
/* endpoint access */
LINFOF("Accessed endpoint at url %s", url);
- res = handler(connection, &status);
+ res = handler(method, connection, &status);
} else if ((newurl = arg->query(url + 1)) != NULL) {
LINFOF("Redirect from %s to %s", url, newurl);
response = "<!DOCTYPE html><html><body>Recirecting...</body></html>";
@@ -85,8 +85,8 @@ void reload_dylib(const char *so_path, const char *db_path) {
if (!arg.dylib) LCRITVF(1, "Could not open dynamic library: %s\n", dlerror());
arg.query = dlsym(arg.dylib, "db_get_url");
if (!arg.query) LCRITVF(1, "Could not load `db_get_url` from shared library: %s", dlerror());
- arg.constructor = dlsym(arg.dylib, "sqlite_init");
- if (!arg.constructor) LCRITVF(1, "Could not load `sqlite_init` from shared library: %s", dlerror());
+ arg.constructor = dlsym(arg.dylib, "init");
+ if (!arg.constructor) LCRITVF(1, "Could not load `init` from shared library: %s", dlerror());
arg.constructor(db_path);
arg.destructor = dlsym(arg.dylib, "sqlite_deinit");
if (!arg.destructor) LCRITVF(1, "Could not load `sqlite_deinit` from shared library: %s", dlerror());
@@ -118,15 +118,15 @@ int main(int argc, char *argv[]) {
const char *dlpath = DEFAULT_ENDPOINTS_PATH;
const char *dbpath = DEFAULT_DATABASE_PATH;
struct MHD_Daemon *daemon = init(&sig, dlpath, dbpath);
- /* while (reload_library == 0) { */
- /* sigsuspend(&sig); */
- /* if (reload_library == 1) { */
- /* reload_dylib(dlpath, dbpath); */
- /* reload_library = 0; */
- /* } */
- /* } */
- getchar();
- if (arg.destructor) arg.destructor();
+ while (reload_library == 0) {
+ sigsuspend(&sig);
+ if (reload_library == 1) {
+ reload_dylib(dlpath, dbpath);
+ reload_library = 0;
+ }
+ }
+ getchar(); /* to be replaced with fork later */
+ arg.destructor();
dlclose(arg.dylib);
MHD_stop_daemon(daemon);
return 0;