diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | config.example.h | 29 | ||||
-rw-r--r-- | main.c | 62 |
3 files changed, 51 insertions, 43 deletions
diff --git a/TODO b/TODO index 653446f..e9ca196 100644 --- a/TODO +++ b/TODO @@ -1,11 +1,10 @@ -make RSS_TTL optional | id:32a848e82d8b39bb8495f49d491882da320a3c7d -add support for caching | id:472d68f1af5489020f4c5808e805822e3da77ffc rethink logging / debug output | id:5734e2717f28d80ac65d3f2123a0f46c01d4a0c1 if possible determine BLOG_SERVER_URL automatically | id:5ad1fabab42a5776ab1446d09659c7a99a104245 rework timezone offsets without tzset() | id:64d715e826ba9fdbcc72cb1b92a77f004642d2a3 support markdown markup via lowdown | id:90c72d144f21d78d1b56790a927f6eea52df2a2c get rid of as many fixed size buffers as possible | id:9281f3a25aa08f6ba5d67c02e65cd0fb7f0a6b3c templating: give all functions context (index or not, SCRIPT_NAME, entry struct if applicable) | id:930c2e4f2c4c9ec3efef87b6ddd50a6ba6dd4903 +update user documentation to reflect recent config changes | id:ae716d655e71edede2a763bb7c0f6e1d369de571 improve man3 situation | id:bf918930f6361c30f288c42894cbf9b0541c3340 use errno instead of returning HTTP status codes in make_index | id:bfa35c48dcedbecd3a951eba243c4840178289ed templating: unify single_entry and index_entry | id:e6dcb195d890bb0b5186716808d806101d81e4f6 diff --git a/config.example.h b/config.example.h index 655f1b6..b089d21 100644 --- a/config.example.h +++ b/config.example.h @@ -88,14 +88,33 @@ */ /*! - * @brief TTL of RSS feed + * @brief Time a browsers should cache a response of sternenblog * - * TTL (time to live) of the RSS feed in minutes. Feed readers may use this - * value to determine how often to refresh the RSS feed. + * Time in seconds that should be the value of the `max-age` field + * of the `Cache-Control` header. It determines the time in seconds + * a response of sternenblog should be considered “fresh”. * - * @see https://cyber.harvard.edu/rss/rss.html#ltttlgtSubelementOfLtchannelgt + * During this time browsers will used the cached version of the + * response (if present) for a given URL. This is useful to reduce + * server load, since browsers will request resources less often + * which means they have to be generated less often as well + * (especially the index). + * + * The value should be at least the time you expect users to spend + * on your website although you might want to go lower if your + * website updates _very_ frequently. + * + * The header will also be set for the feeds, but the RSS + * `ttl` element won't be generated based on this value. + * + * Optional setting. + * + * Requires HTTP/1.1, but sternenblog won't check the used protocol version + * before sending this header. + * + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control */ -#define BLOG_RSS_TTL 60 +#define BLOG_CACHE_MAX_AGE 3600 //! @} diff --git a/main.c b/main.c index 2636236..55d8000 100644 --- a/main.c +++ b/main.c @@ -100,6 +100,8 @@ // reduce memory usage by only using get_text in the inner loop // and unmapping the file directly afterwards +void send_standard_headers(int status, char content_type[]); + /*! * @brief Outputs the CGI response for the index page of the blog * @@ -158,9 +160,7 @@ int main(void) { if(script_name == NULL) { fputs("Missing SCRIPT_NAME", stderr); - send_header("Content-type", "text/html"); - send_header("Status", "500 Internal Server Error"); - terminate_headers(); + send_standard_headers(500, "text/html"); template_header(); template_error(500); @@ -183,23 +183,34 @@ int main(void) { return EXIT_SUCCESS; } +void send_standard_headers(int status, char content_type[]) { + send_header("Status", http_status_line(status)); + send_header("Content-type", content_type); + +#ifdef BLOG_CACHE_MAX_AGE + char max_age[256]; + int result = snprintf(max_age, sizeof max_age, "max-age=%d", BLOG_CACHE_MAX_AGE); + if(result > 0 && max_age[sizeof max_age - 1] == '\0') { + send_header("Cache-Control", max_age); + } +#endif + + terminate_headers(); +} + void blog_index(char script_name[]) { struct entry *entries = NULL; int count = make_index(BLOG_DIR, script_name, 0, &entries); - send_header("Content-type", "text/html"); - if(count < 0) { - send_header("Status", "500 Internal Server Error"); - terminate_headers(); + send_standard_headers(500, "text/html"); template_header(); template_error(500); template_footer(); } else { - send_header("Status", "200 OK"); - terminate_headers(); + send_standard_headers(200, "text/html"); template_header(); @@ -222,8 +233,6 @@ void blog_index(char script_name[]) { } void blog_entry(char script_name[], char path_info[]) { - send_header("Content-type", "text/html"); - struct entry entry; int status = make_entry(BLOG_DIR, script_name, path_info, &entry); @@ -231,17 +240,13 @@ void blog_entry(char script_name[], char path_info[]) { status = 500; } - if(status != 200) { - send_header("Status", http_status_line(status)); - terminate_headers(); + send_standard_headers(status, "text/html"); + if(status != 200) { template_header(); template_error(status); template_footer(); } else { - send_header("Status", "200 OK"); - terminate_headers(); - template_header(); template_single_entry(entry); template_footer(); @@ -257,17 +262,13 @@ void blog_rss(char script_name[]) { int count = make_index(BLOG_DIR, script_name, 1, &entries); if(count < 0) { - send_header("Status", "500 Internal Server Error"); - send_header("Content-type", "text/plain"); - terminate_headers(); + send_standard_headers(500, "text/plain"); puts("Internal Server Error"); return; } - send_header("Status", "200 OK"); - send_header("Content-type", "application/rss+xml"); - terminate_headers(); + send_standard_headers(200, "application/rss+xml"); struct xml_context ctx; new_xml_context(&ctx); @@ -304,13 +305,6 @@ void blog_rss(char script_name[]) { } } - char ttl_string[32]; - if(snprintf(ttl_string, sizeof ttl_string, "%d", BLOG_RSS_TTL) >= 0) { - xml_open_tag(&ctx, "ttl"); - xml_escaped(&ctx, ttl_string); - xml_close_tag(&ctx, "ttl"); - } - char *rss_link = catn_alloc(3, BLOG_SERVER_URL, script_name, "/rss.xml"); if(rss_link != NULL) { xml_empty_tag(&ctx, "atom:link", 3, @@ -368,9 +362,7 @@ void blog_atom(char script_name[]) { int count = make_index(BLOG_DIR, script_name, 1, &entries); if(count < 0) { - send_header("Status", http_status_line(500)); - send_header("Content-type", "text/plain"); - terminate_headers(); + send_standard_headers(500, "text/plain"); puts("Internal Server Error"); @@ -384,9 +376,7 @@ void blog_atom(char script_name[]) { char *self_url = catn_alloc(3, BLOG_SERVER_URL, script_name, "/atom.xml"); char *html_url = catn_alloc(2, BLOG_SERVER_URL, script_name); - send_header("Status", http_status_line(200)); - send_header("Content-type", "application/atom+xml"); - terminate_headers(); + send_standard_headers(200, "application/atom+xml"); xml_raw(&ctx, "<?xml version=\"1.0\" encoding=\"utf-8\"?>"); xml_open_tag_attrs(&ctx, "feed", 1, "xmlns", "http://www.w3.org/2005/Atom"); |