Browse Source

send proper error pages

personal/stbuehler/wip
Thomas Porzelt 14 years ago
parent
commit
34281b50f1
  1. 57
      src/response.c
  2. 1
      src/response.h
  3. 131
      src/utils.c
  4. 5
      src/utils.h

57
src/response.c

@ -33,7 +33,8 @@ void response_send_headers(connection *con) {
if (0 == con->out->length && con->content_handler == NULL
&& con->response.http_status >= 400 && con->response.http_status < 600) {
chunkqueue_append_mem(con->out, CONST_STR_LEN("Custom error\r\n"));
/*chunkqueue_append_mem(con->out, CONST_STR_LEN("Custom error\r\n"));*/
response_send_error_page(con);
}
if (con->content_handler == NULL) {
@ -76,7 +77,17 @@ void response_send_headers(connection *con) {
if (con->keep_alive)
http_header_overwrite(con->response.headers, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
}
g_string_append_printf(head, "%i %s\r\n", con->response.http_status, http_status_string(con->response.http_status));
{
guint len;
gchar status_str[4];
gchar *str = http_status_string(con->response.http_status, &len);
http_status_to_str(con->response.http_status, status_str);
status_str[3] = ' ';
g_string_append_len(head, status_str, 4);
g_string_append_len(head, str, len);
g_string_append_len(head, CONST_STR_LEN("\r\n"));
}
/* Append headers */
{
@ -114,3 +125,45 @@ void response_send_headers(connection *con) {
g_string_append_len(head, CONST_STR_LEN("\r\n"));
chunkqueue_append_string(con->raw_out, head);
}
void response_send_error_page(connection *con) {
gchar status_str[3];
guint len;
gchar *str;
chunkqueue_append_mem(con->out, CONST_STR_LEN(
"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
" <head>\n"
" <title>"
));
http_status_to_str(con->response.http_status, status_str);
chunkqueue_append_mem(con->out, status_str, 3);
chunkqueue_append_mem(con->out, CONST_STR_LEN(" - "));
str = http_status_string(con->response.http_status, &len);
chunkqueue_append_mem(con->out, str, len);
chunkqueue_append_mem(con->out, CONST_STR_LEN(
"</title>\n"
" </head>\n"
" <body>\n"
" <h1>"
));
chunkqueue_append_mem(con->out, status_str, 3);
chunkqueue_append_mem(con->out, CONST_STR_LEN(" - "));
chunkqueue_append_mem(con->out, str, len);
chunkqueue_append_mem(con->out, CONST_STR_LEN(
"</h1>\n"
" </body>\n"
"</html>\n"
));
g_printerr("%u\n", len);
}

1
src/response.h

@ -17,5 +17,6 @@ LI_API void response_reset(response *resp);
LI_API void response_clear(response *resp);
LI_API void response_send_headers(connection *con);
LI_API void response_send_error_page(connection *con);
#endif

131
src/utils.c

@ -171,73 +171,92 @@ void path_simplify(GString *path) {
g_string_set_size(path, out - start);
}
gchar *http_status_string(guint status_code) {
#define SET_LEN_AND_RETURN_STR(x) \
do { \
*len = sizeof(x) - 1; \
return x; \
} while(0)
gchar *http_status_string(guint status_code, guint *len) {
/* RFC 2616 (as well as RFC 2518, RFC 2817, RFC 2295, RFC 2774, RFC 4918) */
switch (status_code) {
/* 1XX information */
case 100: return "Continue";
case 101: return "Switching Protocols";
case 102: return "Processing";
case 100: SET_LEN_AND_RETURN_STR("Continue");
case 101: SET_LEN_AND_RETURN_STR("Switching Protocols");
case 102: SET_LEN_AND_RETURN_STR("Processing");
/* 2XX successful operation */
case 200: return "OK";
case 201: return "Created";
case 202: return "Accepted";
case 203: return "Non-Authoritative Information";
case 204: return "No Content";
case 205: return "Reset Content";
case 206: return "Partial Content";
case 207: return "Multi-Status";
case 200: SET_LEN_AND_RETURN_STR("OK");
case 201: SET_LEN_AND_RETURN_STR("Created");
case 202: SET_LEN_AND_RETURN_STR("Accepted");
case 203: SET_LEN_AND_RETURN_STR("Non-Authoritative Information");
case 204: SET_LEN_AND_RETURN_STR("No Content");
case 205: SET_LEN_AND_RETURN_STR("Reset Content");
case 206: SET_LEN_AND_RETURN_STR("Partial Content");
case 207: SET_LEN_AND_RETURN_STR("Multi-Status");
/* 3XX redirect */
case 300: return "Multiple Choice";
case 301: return "Moved Permanently";
case 302: return "Found";
case 303: return "See Other";
case 304: return "Not Modified";
case 305: return "Use Proxy";
case 306: return "(reserved)";
case 307: return "Temporary Redirect";
case 300: SET_LEN_AND_RETURN_STR("Multiple Choice");
case 301: SET_LEN_AND_RETURN_STR("Moved Permanently");
case 302: SET_LEN_AND_RETURN_STR("Found");
case 303: SET_LEN_AND_RETURN_STR("See Other");
case 304: SET_LEN_AND_RETURN_STR("Not Modified");
case 305: SET_LEN_AND_RETURN_STR("Use Proxy");
case 306: SET_LEN_AND_RETURN_STR("(reserved)");
case 307: SET_LEN_AND_RETURN_STR("Temporary Redirect");
/* 4XX client error */
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 402: return "Payment Required";
case 403: return "Forbidden";
case 404: return "Not Found";
case 405: return "Method Not Allowed";
case 406: return "Not Acceptable";
case 407: return "Proxy Authentication Required";
case 408: return "Request Time-out";
case 409: return "Conflict";
case 410: return "Gone";
case 411: return "Length Required";
case 412: return "Precondition Failed";
case 413: return "Request Entity Too Large";
case 414: return "Request-URI Too Long";
case 415: return "Unsupported Media Type";
case 416: return "Request range not satisfiable";
case 417: return "Expectation Failed";
case 421: return "There are too many connections from your internet address";
case 422: return "Unprocessable Entity";
case 423: return "Locked";
case 424: return "Failed Dependency";
case 425: return "Unordered Collection";
case 426: return "Upgrade Required";
case 400: SET_LEN_AND_RETURN_STR("Bad Request");
case 401: SET_LEN_AND_RETURN_STR("Unauthorized");
case 402: SET_LEN_AND_RETURN_STR("Payment Required");
case 403: SET_LEN_AND_RETURN_STR("Forbidden");
case 404: SET_LEN_AND_RETURN_STR("Not Found");
case 405: SET_LEN_AND_RETURN_STR("Method Not Allowed");
case 406: SET_LEN_AND_RETURN_STR("Not Acceptable");
case 407: SET_LEN_AND_RETURN_STR("Proxy Authentication Required");
case 408: SET_LEN_AND_RETURN_STR("Request Time-out");
case 409: SET_LEN_AND_RETURN_STR("Conflict");
case 410: SET_LEN_AND_RETURN_STR("Gone");
case 411: SET_LEN_AND_RETURN_STR("Length Required");
case 412: SET_LEN_AND_RETURN_STR("Precondition Failed");
case 413: SET_LEN_AND_RETURN_STR("Request Entity Too Large");
case 414: SET_LEN_AND_RETURN_STR("Request-URI Too Long");
case 415: SET_LEN_AND_RETURN_STR("Unsupported Media Type");
case 416: SET_LEN_AND_RETURN_STR("Request range not satisfiable");
case 417: SET_LEN_AND_RETURN_STR("Expectation Failed");
case 421: SET_LEN_AND_RETURN_STR("There are too many connections from your internet address");
case 422: SET_LEN_AND_RETURN_STR("Unprocessable Entity");
case 423: SET_LEN_AND_RETURN_STR("Locked");
case 424: SET_LEN_AND_RETURN_STR("Failed Dependency");
case 425: SET_LEN_AND_RETURN_STR("Unordered Collection");
case 426: SET_LEN_AND_RETURN_STR("Upgrade Required");
/* 5XX server error */
case 500: return "Internal Server Error";
case 501: return "Not Implemented";
case 502: return "Bad Gateway";
case 503: return "Service Unavailable";
case 504: return "Gateway Time-out";
case 505: return "HTTP Version not supported";
case 506: return "Variant Also Negotiates";
case 507: return "Insufficient Storage";
case 509: return "Bandwidth Limit Exceeded";
case 510: return "Not Extended";
case 500: SET_LEN_AND_RETURN_STR("Internal Server Error");
case 501: SET_LEN_AND_RETURN_STR("Not Implemented");
case 502: SET_LEN_AND_RETURN_STR("Bad Gateway");
case 503: SET_LEN_AND_RETURN_STR("Service Unavailable");
case 504: SET_LEN_AND_RETURN_STR("Gateway Time-out");
case 505: SET_LEN_AND_RETURN_STR("HTTP Version not supported");
case 506: SET_LEN_AND_RETURN_STR("Variant Also Negotiates");
case 507: SET_LEN_AND_RETURN_STR("Insufficient Storage");
case 509: SET_LEN_AND_RETURN_STR("Bandwidth Limit Exceeded");
case 510: SET_LEN_AND_RETURN_STR("Not Extended");
/* unknown */
default: return "unknown status";
default: SET_LEN_AND_RETURN_STR("unknown status");
}
}
#undef SET_LEN_AND_RETURN_STR
void http_status_to_str(gint status_code, gchar status_str[]) {
gint status_int;
status_int = status_code;
status_str[0] = status_int / 100;
status_int -= 100 * status_str[0];
status_str[1] = status_int / 10;
status_int -= 10 * status_str[1];
status_str[2] = status_int;
status_str[0] += '0';
status_str[1] += '0';
status_str[2] += '0';
}
gchar counter_format(guint64 *count, guint factor) {

5
src/utils.h

@ -17,7 +17,10 @@ LI_API void url_decode(GString *path);
LI_API void path_simplify(GString *path);
LI_API gchar *http_status_string(guint status_code);
/* returns the description for a given http status code and sets the len to the length of the returned string */
LI_API gchar *http_status_string(guint status_code, guint *len);
/* converts a given 3 digit http status code to a gchar[3] string. e.g. 403 to {'4','0','3'} */
LI_API void http_status_to_str(gint status_code, gchar status_str[]);
/* */
LI_API gchar counter_format(guint64 *count, guint factor);

Loading…
Cancel
Save