Merge error page changes from httpd: send Content-Length:, change
authorreyk <reyk@openbsd.org>
Thu, 1 Jan 2015 14:54:06 +0000 (14:54 +0000)
committerreyk <reyk@openbsd.org>
Thu, 1 Jan 2015 14:54:06 +0000 (14:54 +0000)
Date: from asctime to the preferred HTTP/1.1 format, and use the
popular "Comic Sans" style (can be changed in the configuration).

usr.sbin/relayd/relay_http.c
usr.sbin/relayd/relayd.h

index e462034..a6a6219 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: relay_http.c,v 1.38 2015/01/01 14:21:06 reyk Exp $    */
+/*     $OpenBSD: relay_http.c,v 1.39 2015/01/01 14:54:06 reyk Exp $    */
 
 /*
  * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -871,6 +871,17 @@ relay_lookup_query(struct ctl_relay_event *cre, struct kv *kv)
        return (ret);
 }
 
+ssize_t
+relay_http_time(time_t t, char *tmbuf, size_t len)
+{
+       struct tm                tm;
+
+       /* New HTTP/1.1 RFC 7231 prefers IMF-fixdate from RFC 5322 */
+       if (t == -1 || gmtime_r(&t, &tm) == NULL)
+               return (-1);
+       else
+               return (strftime(tmbuf, len, "%a, %d %h %Y %T %Z", &tm));
+}
 
 void
 relay_abort_http(struct rsession *con, u_int code, const char *msg,
@@ -879,11 +890,10 @@ relay_abort_http(struct rsession *con, u_int code, const char *msg,
        struct relay            *rlay = con->se_relay;
        struct bufferevent      *bev = con->se_in.bev;
        const char              *httperr = NULL, *text = "";
-       char                    *httpmsg;
-       time_t                   t;
-       struct tm               *lt;
+       char                    *httpmsg, *body = NULL;
        char                     tmbuf[32], hbuf[128];
        const char              *style, *label = NULL;
+       int                      bodylen;
 
        if ((httperr = relay_httperror_byid(code)) == NULL)
                httperr = "Unknown Error";
@@ -905,29 +915,26 @@ relay_abort_http(struct rsession *con, u_int code, const char *msg,
        if (print_host(&rlay->rl_conf.ss, hbuf, sizeof(hbuf)) == NULL)
                goto done;
 
-       /* RFC 2616 "tolerates" asctime() */
-       time(&t);
-       lt = localtime(&t);
-       tmbuf[0] = '\0';
-       if (asctime_r(lt, tmbuf) != NULL)
-               tmbuf[strlen(tmbuf) - 1] = '\0';        /* skip final '\n' */
+       if (relay_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0)
+               goto done;
 
        /* Do not send details of the Internal Server Error */
-       if (code != 500)
+       switch (code) {
+       case 500:
+               break;
+       default:
                text = msg;
+               break;
+       }
 
        /* A CSS stylesheet allows minimal customization by the user */
-       if ((style = rlay->rl_proto->style) == NULL)
-               style = "body { background-color: #a00000; color: white; }";
+       style = (rlay->rl_proto->style != NULL) ? rlay->rl_proto->style :
+           "body { background-color: #a00000; color: white; font-family: "
+           "'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', sans-serif; }\n"
+           "hr { border: 0; border-bottom: 1px dashed; }\n";
 
        /* Generate simple HTTP+HTML error document */
-       if (asprintf(&httpmsg,
-           "HTTP/1.0 %03d %s\r\n"
-           "Date: %s\r\n"
-           "Server: %s\r\n"
-           "Connection: close\r\n"
-           "Content-Type: text/html\r\n"
-           "\r\n"
+       if ((bodylen = asprintf(&body,
            "<!DOCTYPE html>\n"
            "<html>\n"
            "<head>\n"
@@ -941,10 +948,22 @@ relay_abort_http(struct rsession *con, u_int code, const char *msg,
            "<hr><address>%s at %s port %d</address>\n"
            "</body>\n"
            "</html>\n",
-           code, httperr, tmbuf, RELAYD_SERVERNAME,
            code, httperr, style, httperr, text,
            label == NULL ? "" : label,
-           RELAYD_SERVERNAME, hbuf, ntohs(rlay->rl_conf.port)) == -1)
+           RELAYD_SERVERNAME, hbuf, ntohs(rlay->rl_conf.port))) == -1)
+               goto done;
+
+       /* Generate simple HTTP+HTML error document */
+       if (asprintf(&httpmsg,
+           "HTTP/1.0 %03d %s\r\n"
+           "Date: %s\r\n"
+           "Server: %s\r\n"
+           "Connection: close\r\n"
+           "Content-Type: text/html\r\n"
+           "Content-Length: %d\r\n"
+           "\r\n"
+           "%s",
+           code, httperr, tmbuf, RELAYD_SERVERNAME, bodylen, body) == -1)
                goto done;
 
        /* Dump the message without checking for success */
@@ -952,6 +971,7 @@ relay_abort_http(struct rsession *con, u_int code, const char *msg,
        free(httpmsg);
 
  done:
+       free(body);
        if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1)
                relay_close(con, msg);
        else {
index ab2b534..e319645 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: relayd.h,v 1.201 2014/12/21 00:54:49 guenther Exp $   */
+/*     $OpenBSD: relayd.h,v 1.202 2015/01/01 14:54:06 reyk Exp $       */
 
 /*
  * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -1187,6 +1187,7 @@ const char
 const char
        *relay_httperror_byid(u_int);
 int     relay_httpdesc_init(struct ctl_relay_event *);
+ssize_t         relay_http_time(time_t, char *, size_t);
 
 /* relay_udp.c */
 void    relay_udp_privinit(struct relayd *, struct relay *);