diff options
-rw-r--r-- | src/clog.c | 161 |
1 files changed, 136 insertions, 25 deletions
@@ -21,7 +21,8 @@ KORE_SECCOMP_FILTER("clog", int init(int); int post(struct http_request *); int posts(struct http_request *); -int render_posts(struct http_request *, const char *); +int render_posts_html(struct http_request *, const char *); +int render_posts_json(struct http_request *, const char *); static void process_md_output(const MD_CHAR *, MD_SIZE size, void *); static int render_md(char *, struct kore_buf *); @@ -32,30 +33,54 @@ int init(int state) { // Register the database - int err = kore_pgsql_register( + return kore_pgsql_register( database, "host=postgres port=5432 user=postgres password=postgres dbname=clog sslmode=disable" ); - return err; } int post(struct http_request *req) { - const char *resource; + int err; + + const char *accept, *resource; + resource = req->path + strlen("/posts/"); kore_log(LOG_DEBUG, "Resource /posts/%s", resource); - return render_posts(req, resource); + + err = http_request_header(req, "accept", &accept); + if (err == KORE_RESULT_OK) { + kore_log(LOG_DEBUG, "Accept: %s", accept); + if (strcmp(accept, "application/json") == 0) { + return render_posts_json(req, resource); + } + } + + return render_posts_html(req, resource); } int posts(struct http_request *req) { - return render_posts(req, NULL); + int err; + + const char *accept; + + err = http_request_header(req, "accept", &accept); + err = http_request_header(req, "accept", &accept); + if (err == KORE_RESULT_OK) { + kore_log(LOG_DEBUG, "Accept: %s", accept); + if (strcmp(accept, "application/json") == 0) { + return render_posts_json(req, NULL); + } + } + + return render_posts_html(req, NULL); } int -render_posts(struct http_request *req, const char *resource) +render_posts_html(struct http_request *req, const char *resource) { // Errors int err; @@ -81,8 +106,7 @@ render_posts(struct http_request *req, const char *resource) // kore_pgsql_register()). We also say we will perform a synchronous // query (KORE_PGSQL_SYNC). err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); - kore_log(LOG_DEBUG, "kore_pgsql_setup: %d", err); - if (!err) + if (err == KORE_RESULT_ERROR) { kore_buf_appendf( resp_buf, @@ -94,26 +118,25 @@ render_posts(struct http_request *req, const char *resource) } // Query for posts, check for error. - if (!resource) { - // Query all posts. - err = kore_pgsql_query( + if (resource) { + // Query a post. + err = kore_pgsql_query_params( &sql, "SELECT id, title, created_at::DATE, body FROM posts " - "ORDER BY updated_at DESC;" + "WHERE id = $1;", + 0, // return string data + 1, // param count + KORE_PGSQL_PARAM_TEXT(resource) ); } else { - // Query a post. - err = kore_pgsql_query_params( + // Query all posts. + err = kore_pgsql_query( &sql, "SELECT id, title, created_at::DATE, body FROM posts " - "WHERE id = $1 " - "ORDER BY updated_at DESC;", - 0, - 1, - KORE_PGSQL_PARAM_TEXT(resource) + "ORDER BY updated_at DESC;" ); } - if (!err) { + if (err == KORE_RESULT_ERROR) { kore_buf_appendf( resp_buf, (const char *) asset_error_html, @@ -135,7 +158,8 @@ render_posts(struct http_request *req, const char *resource) // Allocate a buffer to render the markdown as HTML into. struct kore_buf *html_buf = kore_buf_alloc(0); // Render MD. - if (!render_md(body, html_buf)) { + err = render_md(body, html_buf); + if (err == KORE_RESULT_ERROR) { kore_log(LOG_ERR, "Error rendering markdown for entry %s.", id); kore_buf_free(html_buf); continue; @@ -164,7 +188,94 @@ out: ; kore_pgsql_cleanup(&sql); kore_buf_free(resp_buf); - return (KORE_RESULT_OK); + return KORE_RESULT_OK; +} + +int +render_posts_json(struct http_request *req, const char *resource) { + // Errors + int err; + + // Buffer for response + struct kore_buf *resp_buf = kore_buf_alloc(0); + + // SQL vars + struct kore_pgsql sql; + int rows; + + // JSON results form PostgreSQL. + char *json; + + // Setup SQL + kore_pgsql_init(&sql); + + // Initialise our kore_pgsql data structure with the database name + // we want to connect to (note that we registered this earlier with + // kore_pgsql_register()). We also say we will perform a synchronous + // query (KORE_PGSQL_SYNC). + err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); + if (err == KORE_RESULT_ERROR) + { + kore_buf_appendf( + resp_buf, + (const char *) asset_error_html, + "There was an error processing the request." + ); + kore_pgsql_logerror(&sql); + goto out; + } + + if (resource) { + err = kore_pgsql_query_params( + &sql, + "SELECT JSON_AGG(ROW_TO_JSON(row)) FROM (" + "SELECT id, title, body, created_at, updated_at FROM " + "posts WHERE id = $1" + ") row;", + 0, // return string data + 1, // param count + KORE_PGSQL_PARAM_TEXT(resource) + ); + } else { + err = kore_pgsql_query( + &sql, + "SELECT JSON_AGG(ROW_TO_JSON(row)) FROM (" + "SELECT id, title, body, created_at, updated_at FROM " + "posts ORDER BY updated_at DESC " + ") row;" + ); + } + if (err == KORE_RESULT_ERROR) { + kore_buf_appendf( + resp_buf, + (const char *) asset_error_html, + "There was an error processing the request." + ); + kore_pgsql_logerror(&sql); + goto out; + } + + rows = kore_pgsql_ntuples(&sql); + if (rows == 1) { + json = kore_pgsql_getvalue(&sql, 0, 0); + kore_buf_append( + resp_buf, + json, + strlen(json) + ); + } // else { + +out: ; + + // Finish building response. + http_response_header(req, "content-type", "application/json; charset=utf-8"); + http_response(req, HTTP_STATUS_OK, resp_buf->data, resp_buf->offset); + + // Cleanup. + kore_pgsql_cleanup(&sql); + kore_buf_free(resp_buf); + + return KORE_RESULT_OK; } static int @@ -186,10 +297,10 @@ render_md(char *in, struct kore_buf *out) if(err != 0) { kore_log(LOG_ERR, "Parsing Markdown failed.\n"); - return -1; + return KORE_RESULT_ERROR; } - return 1; + return KORE_RESULT_OK; } static void |