add: endpoint /tags
fix: leaks from config (now using static length for config strings)
This commit is contained in:
parent
0f1cd9c02c
commit
a78815cb32
10 changed files with 147 additions and 16 deletions
5
config.c
5
config.c
|
@ -61,31 +61,26 @@ config_load(IniDispatch *disp, void *config_void)
|
|||
}
|
||||
if(CONFINI_IS_KEY("core", "database"))
|
||||
{
|
||||
config->database = malloc(sizeof(char) * (strlen(disp->value) + 1));
|
||||
strcpy(config->database, disp->value);
|
||||
return 0;
|
||||
}
|
||||
if(CONFINI_IS_KEY("core", "not-found-file"))
|
||||
{
|
||||
config->not_found_file = malloc(sizeof(char) * (strlen(disp->value) + 1));
|
||||
strcpy(config->not_found_file, disp->value);
|
||||
return 0;
|
||||
}
|
||||
if(CONFINI_IS_KEY("core", "not-found-file-type"))
|
||||
{
|
||||
config->not_found_file_type = malloc(sizeof(char) * (strlen(disp->value) + 1));
|
||||
strcpy(config->not_found_file_type, disp->value);
|
||||
return 0;
|
||||
}
|
||||
if(CONFINI_IS_KEY("core", "not-found-content"))
|
||||
{
|
||||
config->not_found_content = malloc(sizeof(char) * (strlen(disp->value) + 1));
|
||||
strcpy(config->not_found_content, disp->value);
|
||||
return 0;
|
||||
}
|
||||
if(CONFINI_IS_KEY("core", "not-found-content-type"))
|
||||
{
|
||||
config->not_found_content_type = malloc(sizeof(char) * (strlen(disp->value) + 1));
|
||||
strcpy(config->not_found_content_type, disp->value);
|
||||
return 0;
|
||||
}
|
||||
|
|
35
endpoints/api_v1_tags.c
Normal file
35
endpoints/api_v1_tags.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <cJSON.h>
|
||||
#include <macros.h>
|
||||
#include <constants.h>
|
||||
#include <endpoints/api_v1_tags.h>
|
||||
#include <logger.h>
|
||||
#include <models/tag.h>
|
||||
|
||||
void
|
||||
api_v1_tags_GET(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response)
|
||||
{
|
||||
(void)args;
|
||||
(void)hm;
|
||||
(void)nc;
|
||||
|
||||
char** all_tags = tag_get_all();
|
||||
|
||||
cJSON *json = cJSON_CreateArray();
|
||||
|
||||
for(int i = 0; all_tags[i] != NULL; ++i)
|
||||
{
|
||||
cJSON *json_tag = cJSON_CreateString(all_tags[i]);
|
||||
if (json_tag == NULL)
|
||||
{
|
||||
LOG_DEBUG("failed to add tag from string '%s'\n", all_tags[i]);
|
||||
free(all_tags[i]);
|
||||
continue;
|
||||
}
|
||||
cJSON_AddItemToArray(json, json_tag);
|
||||
free(all_tags[i]);
|
||||
}
|
||||
|
||||
endpoint_response_json(response, 200, json);
|
||||
cJSON_Delete(json);
|
||||
free(all_tags);
|
||||
}
|
|
@ -25,15 +25,15 @@ typedef enum
|
|||
typedef struct
|
||||
{
|
||||
char *file;
|
||||
char *database;
|
||||
char database[256];
|
||||
log_level_t log_level;
|
||||
run_type_t run_type;
|
||||
char server_port[6];
|
||||
uint16_t discovery_port;
|
||||
char *not_found_file;
|
||||
char *not_found_file_type;
|
||||
char *not_found_content;
|
||||
char *not_found_content_type;
|
||||
char not_found_file[256];
|
||||
char not_found_file_type[256];
|
||||
char not_found_content[256];
|
||||
char not_found_content_type[256];
|
||||
struct mg_serve_http_opts http_server_opts;
|
||||
} config_t;
|
||||
|
||||
|
|
9
include/endpoints/api_v1_tags.h
Normal file
9
include/endpoints/api_v1_tags.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef CORE_ENDPOINTS_API_V1_TAGS_H
|
||||
#define CORE_ENDPOINTS_API_V1_TAGS_H
|
||||
|
||||
#include <router.h>
|
||||
|
||||
void
|
||||
api_v1_tags_GET(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
|
||||
|
||||
#endif /* CORE_ENDPOINTS_API_V1_TAGS_H */
|
|
@ -10,8 +10,10 @@ tag_remove(int id);
|
|||
char*
|
||||
tag_get_tag(int id);
|
||||
|
||||
char**
|
||||
tag_get_all();
|
||||
|
||||
int
|
||||
tag_get_id(const char* tag);
|
||||
|
||||
|
||||
#endif /* CORE_MODELS_TAG_H */
|
||||
|
|
9
main.c
9
main.c
|
@ -25,8 +25,6 @@ terminate(int signum)
|
|||
|
||||
sqlite3_close(global_database);
|
||||
|
||||
free(global_config.database);
|
||||
|
||||
router_free();
|
||||
|
||||
exit(signum);
|
||||
|
@ -51,9 +49,10 @@ main(int argc, const char** argv)
|
|||
/******************** LOAD CONFIG ********************/
|
||||
|
||||
global_config.file = "core.ini";
|
||||
global_config.not_found_file = "404.html";
|
||||
global_config.not_found_content = "404 - NOT FOUND";
|
||||
global_config.not_found_content_type = "text/plain";
|
||||
strcpy(global_config.not_found_file, "404.html");
|
||||
strcpy(global_config.not_found_file_type, "text/html");
|
||||
strcpy(global_config.not_found_content, "404 - NOT FOUND");
|
||||
strcpy(global_config.not_found_content_type, "text/plain");
|
||||
global_config.log_level = LOG_LEVEL_INFO;
|
||||
|
||||
helper_parse_cli(argc, argv, &global_config);
|
||||
|
|
44
models/tag.c
44
models/tag.c
|
@ -77,6 +77,50 @@ tag_get_tag(int id)
|
|||
return result;
|
||||
}
|
||||
|
||||
char**
|
||||
tag_get_all()
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
sqlite3_prepare_v2(global_database, "SELECT tag FROM tags;", -1, &stmt, NULL);
|
||||
|
||||
char **all_tags = malloc(sizeof(char*));
|
||||
|
||||
int row = 0;
|
||||
|
||||
while(true)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = sqlite3_step(stmt);
|
||||
if (s == SQLITE_ROW)
|
||||
{
|
||||
const char *new_tag = (const char *)sqlite3_column_text(stmt, 0);
|
||||
int new_tag_len = strlen(new_tag);
|
||||
row++;
|
||||
|
||||
all_tags = (char**)realloc(all_tags, sizeof(char*) * (row + 1));
|
||||
all_tags[row - 1] = malloc(sizeof(char) * (new_tag_len + 1));
|
||||
strcpy(all_tags[row - 1], new_tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(s == SQLITE_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("error selecting tags from database: %s\n", sqlite3_errstr(s));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
all_tags[row] = NULL;
|
||||
return all_tags;
|
||||
}
|
||||
|
||||
int
|
||||
tag_get_id(const char *tag)
|
||||
{
|
||||
|
|
4
router.c
4
router.c
|
@ -8,6 +8,7 @@
|
|||
#include <endpoints/api_v1_schedules.h>
|
||||
#include <endpoints/api_v1_controllers.h>
|
||||
#include <endpoints/api_v1_relays.h>
|
||||
#include <endpoints/api_v1_tags.h>
|
||||
|
||||
static endpoint_t endpoints[ROUTER_ENDPOINTS_MAX_COUNT];
|
||||
static endpoint_t endpoint_not_found;
|
||||
|
@ -75,6 +76,8 @@ router_init()
|
|||
|
||||
router_register_endpoint("/api/v1/relays/", HTTP_METHOD_GET, api_v1_relays_GET);
|
||||
router_register_endpoint("/api/v1/relays/tag/{str}", HTTP_METHOD_GET, api_v1_relays_tag_STR_GET);
|
||||
|
||||
router_register_endpoint("/api/v1/tags/", HTTP_METHOD_GET, api_v1_tags_GET);
|
||||
}
|
||||
|
||||
endpoint_t*
|
||||
|
@ -304,6 +307,7 @@ router_find_endpoint(const char *uri_str, size_t uri_len, struct mg_str *method_
|
|||
|
||||
if(best_endpoint == NULL)
|
||||
{
|
||||
free(uri);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,3 +97,12 @@ stages:
|
|||
number: !int "{returned_number:d}"
|
||||
controller_id: "{returned_id}"
|
||||
tag: "{returned_tag}"
|
||||
|
||||
- name: "[tags] get tags"
|
||||
request:
|
||||
method: GET
|
||||
url: "http://localhost:5000/api/v1/tags/"
|
||||
response:
|
||||
status_code: 200
|
||||
verify_response_with:
|
||||
function: validate_tag:multiple
|
||||
|
|
34
tests/tavern_utils/validate_tag.py
Normal file
34
tests/tavern_utils/validate_tag.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import json
|
||||
|
||||
def _verify_single(tag):
|
||||
assert isinstance(tag, str), "tag is not a string"
|
||||
|
||||
def single(response):
|
||||
_verify_single(response.json())
|
||||
|
||||
def multiple(response):
|
||||
assert isinstance(response.json(), list), "response is not a list"
|
||||
for tag in response.json():
|
||||
_verify_single(tag)
|
||||
|
||||
#def find(response, name=None, number=None, controller_id=None, tag=None):
|
||||
# print(response.json())
|
||||
# for tag in response.json():
|
||||
# if number != None and number != tag.get("number"):
|
||||
# continue
|
||||
#
|
||||
# if name != None and name != tag.get("name"):
|
||||
# continue
|
||||
#
|
||||
# if controller_id != None and controller_id != tag.get("controller_id"):
|
||||
# continue
|
||||
#
|
||||
# if tag != None:
|
||||
# found_in_response = False
|
||||
# for response_tag in tag.get("tags"):
|
||||
# if response_tag == tag:
|
||||
# found_in_response = True
|
||||
# if not found_in_response:
|
||||
# continue
|
||||
# return
|
||||
# assert False, "tag not found in list"
|
Loading…
Reference in a new issue