C based API

This commit is contained in:
Senad Uka
2024-10-13 16:21:50 +02:00
parent a1cf3a40a3
commit 68eb5c24f9
11 changed files with 293522 additions and 0 deletions

88
apiv2/src/database.c Normal file
View File

@@ -0,0 +1,88 @@
#include "database.h"
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jansson.h>
static sqlite3 *db;
int db_init() {
int rc = sqlite3_open("database.db", &db);
if (rc) {
return rc;
}
// Initialize tables if necessary
const char *sql = "CREATE TABLE IF NOT EXISTS data (id INTEGER PRIMARY KEY, value TEXT);";
char *errmsg = 0;
rc = sqlite3_exec(db, sql, 0, 0, &errmsg);
if (rc != SQLITE_OK) {
sqlite3_free(errmsg);
}
return rc;
}
char* db_query(const char *query) {
// Prepare SQL statement
const char *sql = "SELECT * FROM data WHERE value LIKE ?;";
sqlite3_stmt *stmt;
char *response = NULL;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
return strdup("{\"error\": \"Failed to prepare statement\"}");
}
// Bind the query parameter
sqlite3_bind_text(stmt, 1, query, -1, SQLITE_TRANSIENT);
// Build JSON response
json_t *json_arr = json_array();
while (sqlite3_step(stmt) == SQLITE_ROW) {
json_t *json_obj = json_object();
int id = sqlite3_column_int(stmt, 0);
const unsigned char *value = sqlite3_column_text(stmt, 1);
json_object_set_new(json_obj, "id", json_integer(id));
json_object_set_new(json_obj, "value", json_string((const char *)value));
json_array_append_new(json_arr, json_obj);
}
char *json_str = json_dumps(json_arr, JSON_INDENT(2));
response = strdup(json_str);
// Cleanup
free(json_str);
json_decref(json_arr);
sqlite3_finalize(stmt);
return response;
}
int db_insert(const char *value) {
const char *sql = "INSERT INTO data (value) VALUES (?);";
sqlite3_stmt *stmt;
int rc;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
return 1;
}
// Bind the value parameter
sqlite3_bind_text(stmt, 1, value, -1, SQLITE_TRANSIENT);
// Execute the statement
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if (rc != SQLITE_DONE) {
return 1;
}
return 0;
}
void db_close() {
sqlite3_close(db);
}

113
apiv2/src/main.c Normal file
View File

@@ -0,0 +1,113 @@
#include "mongoose.h"
#include "database.h"
#include <stdlib.h>
#include <stdio.h>
#include <jansson.h>
static const char *s_http_port = "8001";
static const char *s_root_dir = "."; // Serve current directory
static void handle_get(struct mg_connection *c, struct mg_http_message *hm) {
char query[256] = {0};
char *response;
// Parse query parameter 'q'
mg_http_get_var(&hm->query, "q", query, sizeof(query));
response = db_query(query);
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s", response);
free(response);
}
static void handle_post(struct mg_connection *c, struct mg_http_message *hm) {
char *response;
int result;
// Get the JSON data from the body
char *body = malloc(hm->body.len + 1);
memcpy(body, hm->body.buf, hm->body.len);
body[hm->body.len] = '\0';
// Parse JSON data
json_error_t error;
json_t *root = json_loads(body, 0, &error);
free(body);
if (!root) {
mg_http_reply(c, 400, "Content-Type: text/plain\r\n", "Invalid JSON data: %s", error.text);
return;
}
// Extract data from JSON
const char *value = json_string_value(json_object_get(root, "value"));
if (!value) {
mg_http_reply(c, 400, "Content-Type: text/plain\r\n", "Missing 'value' in JSON data");
json_decref(root);
return;
}
// Store data in the database
result = db_insert(value);
if (result == 0) {
mg_http_reply(c, 200, "Content-Type: text/plain\r\n", "Data stored successfully");
} else {
mg_http_reply(c, 500, "Content-Type: text/plain\r\n", "Failed to store data");
}
json_decref(root);
}
static void handle_api_call(struct mg_connection *c, struct mg_http_message *hm) {
if (mg_casecmp(&hm->method, "GET") == 0) {
handle_get(c, hm);
} else if (mg_casecmp(&hm->method, "POST") == 0) {
handle_post(c, hm);
} else {
mg_http_reply(c, 405, "Content-Type: text/plain\r\n", "Method Not Allowed");
}
}
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/api"), NULL)) {
handle_api_call(c, hm);
} else {
struct mg_http_serve_opts opts = {.root_dir = s_root_dir};
mg_http_serve_dir(c, hm, &opts);
}
}
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr);
// Initialize the database
if (db_init() != 0) {
printf("Failed to initialize database\n");
return 1;
}
printf("Starting RESTful API on port %s\n", s_http_port);
// Start listening for connections
if (mg_http_listen(&mgr, s_http_port, fn, NULL) == NULL) {
printf("Failed to create listener\n");
return 1;
}
for (;;) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
db_close();
return 0;
}