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…
	
	Add table
		Add a link
		
	
		Reference in a new issue