diff options
author | Michael McVady <femtonaut@gmail.com> | 2024-01-12 17:26:24 -0600 |
---|---|---|
committer | Michael McVady <femtonaut@gmail.com> | 2024-01-12 17:26:24 -0600 |
commit | 85a1f20681b4f28b7e5230ef64c2b59e178ce638 (patch) | |
tree | e3f45e05890d25e56a6e2f26034c2d65cd4b73db | |
parent | dd5411a8d709520c19a2e3577064b6c1bc289e64 (diff) |
Flesh out search ...
-rw-r--r-- | assets/html_footer.html (renamed from assets/footer.html) | 0 | ||||
-rw-r--r-- | assets/html_header.html (renamed from assets/header.html) | 0 | ||||
-rw-r--r-- | assets/table_footer.html (renamed from assets/index_footer.html) | 0 | ||||
-rw-r--r-- | assets/table_header.html (renamed from assets/index_header.html) | 2 | ||||
-rw-r--r-- | assets/table_row.html (renamed from assets/index_row.html) | 0 | ||||
-rw-r--r-- | conf/clog.conf | 9 | ||||
-rw-r--r-- | src/clog.c | 123 | ||||
-rw-r--r-- | src/queries.h | 4 |
8 files changed, 113 insertions, 25 deletions
diff --git a/assets/footer.html b/assets/html_footer.html index 6131a40..6131a40 100644 --- a/assets/footer.html +++ b/assets/html_footer.html diff --git a/assets/header.html b/assets/html_header.html index 0ff3660..0ff3660 100644 --- a/assets/header.html +++ b/assets/html_header.html diff --git a/assets/index_footer.html b/assets/table_footer.html index 000ca4b..000ca4b 100644 --- a/assets/index_footer.html +++ b/assets/table_footer.html diff --git a/assets/index_header.html b/assets/table_header.html index a768089..eded2a7 100644 --- a/assets/index_header.html +++ b/assets/table_header.html @@ -1,3 +1 @@ -<h1>clog.bunkergate.org</h1> - <table><tr><th>title</th><th>created</th><th>updated</th></tr> diff --git a/assets/index_row.html b/assets/table_row.html index c9b9c68..c9b9c68 100644 --- a/assets/index_row.html +++ b/assets/table_row.html diff --git a/conf/clog.conf b/conf/clog.conf index 89e9880..cf870b1 100644 --- a/conf/clog.conf +++ b/conf/clog.conf @@ -35,9 +35,18 @@ domain * { methods get } + route ^/search$ { + handler search_entries + methods get + + validate qs:get query v_text + } + route ^/entries/search$ { handler search_entries methods get + + validate qs:get query v_text } route ^/entries/[a-z0-9\-]+$ { @@ -35,6 +35,7 @@ struct entry { struct entry_query { char *id; + char *query; struct entry **entries; int num_entries; @@ -52,7 +53,7 @@ static const char * const error_msg[] = { [HTTP_STATUS_INTERNAL_ERROR] = "There was an error processing the request.", // 500 }; -void entry_query_init(struct entry_query *eq, const char *id); +void entry_query_init(struct entry_query *eq, const char *id, const char *query); void entry_query_cleanup(struct entry_query *eq); int validate_uuid(const char *uuid); @@ -77,12 +78,22 @@ int sql_update(const char *id, const char *title, const char *body); static void process_md_output(const MD_CHAR *html, MD_SIZE size, void *buf); static int render_md(const char *in, struct kore_buf *out); -void entry_query_init(struct entry_query *eq, const char *id) { - if (id != NULL) +void entry_query_init(struct entry_query *eq, const char *id, const char *query) { + if (id != NULL) { eq->id = kore_strdup(id); - else + } + else { eq->id = NULL; + } + if (query != NULL) { + eq->query = kore_strdup(query); + } + else { + eq->query = NULL; + } + + // FIXME: define MAX_ENTRIES and LIMIT queries with it. eq->entries = kore_malloc(sizeof(struct entry *) * 100); eq->num_entries = 0; @@ -90,10 +101,16 @@ void entry_query_init(struct entry_query *eq, const char *id) { } void entry_query_cleanup(struct entry_query *eq) { - if (eq->id != NULL) + if (eq->id != NULL) { kore_free((void *) eq->id); + } eq->id = NULL; + if (eq->query != NULL) { + kore_free((void *) eq->query); + } + eq->query = NULL; + for (int i = 0; i < eq->num_entries; i++) { if (eq->entries[i]->id != NULL) kore_free((void *) eq->entries[i]->id); @@ -108,6 +125,7 @@ void entry_query_cleanup(struct entry_query *eq) { kore_free((void *) eq->entries[i]); } kore_free((void *) eq->entries); + eq->entries = NULL; } int validate_uuid(const char *uuid) { @@ -135,7 +153,7 @@ int validate_uuid(const char *uuid) { } int validate_text(struct http_request *req, char *data) { - kore_log(LOG_NOTICE, "v_example_func called %s", data); + kore_log(LOG_NOTICE, "validate_text called with data '%s'", data); return KORE_RESULT_OK; } @@ -148,9 +166,9 @@ int http_ok_resp( const char *body = kore_buf_stringify(content, NULL); http_response_header(req, "content-type", "text/html; charset=utf-8"); - kore_buf_append(resp_buf, asset_header_html, asset_len_header_html); + kore_buf_append(resp_buf, asset_html_header_html, asset_len_html_header_html); kore_buf_append(resp_buf, body, strlen(body)); - kore_buf_append(resp_buf, asset_footer_html, asset_len_footer_html); + kore_buf_append(resp_buf, asset_html_footer_html, asset_len_html_footer_html); http_response(req, status, resp_buf->data, resp_buf->offset); @@ -166,9 +184,9 @@ int http_err_resp( struct kore_buf *resp_buf = kore_buf_alloc(0); http_response_header(req, "content-type", "text/html; charset=utf-8"); - kore_buf_append(resp_buf, asset_header_html, asset_len_header_html); + kore_buf_append(resp_buf, asset_html_header_html, asset_len_html_header_html); kore_buf_appendf(resp_buf, (const char *) asset_error_html, error_msg[status]); - kore_buf_append(resp_buf, asset_footer_html, asset_len_footer_html); + kore_buf_append(resp_buf, asset_html_footer_html, asset_len_html_footer_html); http_response(req, status, resp_buf->data, resp_buf->offset); @@ -192,7 +210,7 @@ int get_index(struct http_request *req) { content = kore_buf_alloc(0); - entry_query_init(&eq, NULL); + entry_query_init(&eq, NULL, NULL); (void) sql_select(&eq); if (eq.status != QUERY_STATUS_OK) { @@ -200,21 +218,24 @@ int get_index(struct http_request *req) { goto out; } + // Write header. + kore_buf_append(content, asset_header_html, asset_len_header_html); + // Write table header. - kore_buf_append(content, asset_index_header_html, asset_len_index_header_html); + kore_buf_append(content, asset_table_header_html, asset_len_table_header_html); // Iterate over entries and render them. for (row = 0; row < eq.num_entries; row++) { // Append rendered MD entry. kore_buf_appendf( content, - (const char *) asset_index_row_html, + (const char *) asset_table_row_html, eq.entries[row]->id, eq.entries[row]->title, eq.entries[row]->created_at, eq.entries[row]->updated_at ); } // Write table footer. - kore_buf_append(content, asset_index_footer_html, asset_len_index_footer_html); + kore_buf_append(content, asset_table_footer_html, asset_len_table_footer_html); http_ok_resp(req, HTTP_STATUS_OK, content); @@ -238,7 +259,7 @@ int get_entry(struct http_request *req) { content = kore_buf_alloc(0); rendered_body = kore_buf_alloc(0); - entry_query_init(&eq, req->path + strlen("/entries/")); + entry_query_init(&eq, req->path + strlen("/entries/"), NULL); // Check for valid resource UUID kore_log(LOG_DEBUG, "Resource id /entries/%s.", eq.id); @@ -300,7 +321,7 @@ int edit_entry(struct http_request *req) { id = kore_strdup(req->path + strlen("/entries/")); id[strlen(id) - strlen("/edit")] = '\0'; - entry_query_init(&eq, (const char*) id); + entry_query_init(&eq, (const char*) id, NULL); // Check for valid resource UUID kore_log(LOG_DEBUG, "Resource id /entries/%s.", eq.id); @@ -410,13 +431,64 @@ out: ; int search_entries(struct http_request *req) { - // int err = 0; + int err = 0; - kore_log(LOG_INFO, "search ...."); + int row = 0; - http_err_resp(req, HTTP_STATUS_OK); + char *query = NULL; -// out: ; + struct entry_query eq; + + struct kore_buf *content = NULL; + + content = kore_buf_alloc(0); + + http_populate_get(req); + + err = http_argument_get_string(req, "query", &query); + if (err == KORE_RESULT_OK) { + kore_log(LOG_INFO, "query string: '%s'", query); + } + + entry_query_init(&eq, NULL, query); + + (void) sql_select(&eq); + if (eq.status != QUERY_STATUS_OK) { + http_err_resp(req, HTTP_STATUS_INTERNAL_ERROR); + goto out; + } + + // Write header. + kore_buf_append(content, asset_header_html, asset_len_header_html); + + // Write search form. + kore_buf_append(content, asset_search_html, asset_len_search_html); + + if (eq.num_entries > 0) { + // Write table header. + kore_buf_append(content, asset_table_header_html, asset_len_table_header_html); + + // Iterate over entries and render them. + for (row = 0; row < eq.num_entries; row++) { + // Append rendered MD entry. + kore_buf_appendf( + content, + (const char *) asset_table_row_html, + eq.entries[row]->id, eq.entries[row]->title, eq.entries[row]->created_at, eq.entries[row]->updated_at + ); + } + + // Write table footer. + kore_buf_append(content, asset_table_footer_html, asset_len_table_footer_html); + } + + http_ok_resp(req, HTTP_STATUS_OK, content); + +out: ; + + entry_query_cleanup(&eq); + + kore_free(content); return KORE_RESULT_OK; } @@ -449,7 +521,16 @@ int sql_select(struct entry_query *eq) { 1, // param count KORE_PGSQL_PARAM_TEXT(eq->id) ); - } else { + } + else if (eq->query != NULL) { + err = kore_pgsql_query_params(&sql, q_search_entries, + 0, // return string data + 2, // param count + KORE_PGSQL_PARAM_TEXT(eq->query), + KORE_PGSQL_PARAM_TEXT(eq->query) + ); + } + else { // Query for index. err = kore_pgsql_query(&sql, q_select_entries); } diff --git a/src/queries.h b/src/queries.h index a55fafb..7fbe898 100644 --- a/src/queries.h +++ b/src/queries.h @@ -11,13 +11,13 @@ const char *q_select_entries = const char *q_search_entries = "WITH query AS " "( " -" SELECT id, title, created_at::DATE, updated_at::DATE, " +" SELECT id, title, created_at::DATE, updated_at::DATE, body, " " TS_RANK(search_vector, TO_TSQUERY('english', $1)) AS rank " " FROM entries " " WHERE search_vector @@ TO_TSQUERY('english', $2) " " ORDER BY rank DESC " ") " -"SELECT id, title, created_at::DATE, updated_at::DATE FROM query;"; +"SELECT id, title, created_at::DATE, updated_at::DATE, body FROM query;"; const char *q_update_entry = "UPDATE entries " |