Commit 15a26393 authored by Sergey Lyubka's avatar Sergey Lyubka

Added better diagnostic to send_http_error()

parent c20f26db
...@@ -498,13 +498,21 @@ static const char *status_code_to_str(int status_code) { ...@@ -498,13 +498,21 @@ static const char *status_code_to_str(int status_code) {
} }
} }
static void send_http_error(struct connection *conn, int code) { static void send_http_error(struct connection *conn, int code,
const char *fmt, ...) {
const char *message = status_code_to_str(code); const char *message = status_code_to_str(code);
char headers[200], body[200]; char headers[200], body[200];
va_list ap;
int body_len, headers_len; int body_len, headers_len;
conn->mg_conn.status_code = code; conn->mg_conn.status_code = code;
body_len = mg_snprintf(body, sizeof(body), "%d %s\n", code, message); body_len = mg_snprintf(body, sizeof(body), "%d %s\n", code, message);
if (fmt != NULL) {
body[body_len++] = '\n';
va_start(ap, fmt);
body_len += mg_snprintf(body + body_len, sizeof(body) - body_len, fmt, ap);
va_end(ap);
}
if (code >= 300 && code <= 399) { if (code >= 300 && code <= 399) {
// 3xx errors do not have body // 3xx errors do not have body
body_len = 0; body_len = 0;
...@@ -906,7 +914,7 @@ static void open_cgi_endpoint(struct connection *conn, const char *prog) { ...@@ -906,7 +914,7 @@ static void open_cgi_endpoint(struct connection *conn, const char *prog) {
conn->endpoint.cgi_sock = fds[0]; conn->endpoint.cgi_sock = fds[0];
} else { } else {
closesocket(fds[0]); closesocket(fds[0]);
send_http_error(conn, 500); send_http_error(conn, 500, "start_process(%s) failed", prog);
} }
closesocket(fds[1]); closesocket(fds[1]);
...@@ -1036,7 +1044,7 @@ static struct connection *accept_new_connection(struct mg_server *server) { ...@@ -1036,7 +1044,7 @@ static struct connection *accept_new_connection(struct mg_server *server) {
} }
static void close_conn(struct connection *conn) { static void close_conn(struct connection *conn) {
DBG(("closing %p %d %d", conn, conn->flags, conn->endpoint_type)); DBG(("%p %d %d", conn, conn->flags, conn->endpoint_type));
LINKED_LIST_REMOVE(&conn->link); LINKED_LIST_REMOVE(&conn->link);
closesocket(conn->client_sock); closesocket(conn->client_sock);
free(conn->request); // It's OK to free(NULL), ditto below free(conn->request); // It's OK to free(NULL), ditto below
...@@ -1671,7 +1679,8 @@ static void write_to_client(struct connection *conn) { ...@@ -1671,7 +1679,8 @@ static void write_to_client(struct connection *conn) {
0; 0;
#endif #endif
DBG(("Written %d of %d(%d): [%.*s ...]", n, io->len, io->size, 40, io->buf)); DBG(("%p Written %d of %d(%d): [%.*s ...]",
conn, n, io->len, io->size, 40, io->buf));
if (is_error(n)) { if (is_error(n)) {
conn->flags |= CONN_CLOSE; conn->flags |= CONN_CLOSE;
...@@ -2287,7 +2296,7 @@ static void handle_mkcol(struct connection *conn, const char *path) { ...@@ -2287,7 +2296,7 @@ static void handle_mkcol(struct connection *conn, const char *path) {
} else if (errno == ENOENT) { } else if (errno == ENOENT) {
status_code = 409; status_code = 409;
} }
send_http_error(conn, status_code); send_http_error(conn, status_code, NULL);
} }
static int remove_directory(const char *dir) { static int remove_directory(const char *dir) {
...@@ -2318,14 +2327,14 @@ static void handle_delete(struct connection *conn, const char *path) { ...@@ -2318,14 +2327,14 @@ static void handle_delete(struct connection *conn, const char *path) {
file_stat_t st; file_stat_t st;
if (!stat(path, &st)) { if (!stat(path, &st)) {
send_http_error(conn, 404); send_http_error(conn, 404, NULL);
} else if (S_ISDIR(st.st_mode)) { } else if (S_ISDIR(st.st_mode)) {
remove_directory(path); remove_directory(path);
send_http_error(conn, 204); send_http_error(conn, 204, NULL);
} else if (!remove(path) == 0) { } else if (!remove(path) == 0) {
send_http_error(conn, 204); send_http_error(conn, 204, NULL);
} else { } else {
send_http_error(conn, 423); send_http_error(conn, 423, NULL);
} }
} }
...@@ -2361,12 +2370,12 @@ static void handle_put(struct connection *conn, const char *path) { ...@@ -2361,12 +2370,12 @@ static void handle_put(struct connection *conn, const char *path) {
conn->mg_conn.status_code); conn->mg_conn.status_code);
close_local_endpoint(conn); close_local_endpoint(conn);
} else if (rc == -1) { } else if (rc == -1) {
send_http_error(conn, 500); send_http_error(conn, 500, "put_dir: %s", strerror(errno));
} else if (cl_hdr == NULL) { } else if (cl_hdr == NULL) {
send_http_error(conn, 411); send_http_error(conn, 411, NULL);
} else if ((conn->endpoint.fd = } else if ((conn->endpoint.fd =
open(path, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) { open(path, O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {
send_http_error(conn, 500); send_http_error(conn, 500, "open(%s): %s", path, strerror(errno));
} else { } else {
DBG(("PUT [%s] %d", path, conn->local_iobuf.len)); DBG(("PUT [%s] %d", path, conn->local_iobuf.len));
conn->endpoint_type = EP_PUT; conn->endpoint_type = EP_PUT;
...@@ -3029,7 +3038,7 @@ static void handle_lsp_request(struct connection *conn, const char *path, ...@@ -3029,7 +3038,7 @@ static void handle_lsp_request(struct connection *conn, const char *path,
(p = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, (p = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE,
fileno(fp), 0)) == MAP_FAILED || fileno(fp), 0)) == MAP_FAILED ||
(L = luaL_newstate()) == NULL) { (L = luaL_newstate()) == NULL) {
send_http_error(conn, 500); send_http_error(conn, 500, "mmap(%s): %s", path, strerror(errno));
} else { } else {
// We're not sending HTTP headers here, Lua page must do it. // We're not sending HTTP headers here, Lua page must do it.
prepare_lua_environment(&conn->mg_conn, L); prepare_lua_environment(&conn->mg_conn, L);
...@@ -3066,7 +3075,8 @@ static void open_local_endpoint(struct connection *conn) { ...@@ -3066,7 +3075,8 @@ static void open_local_endpoint(struct connection *conn) {
const char *cl = mg_get_header(&conn->mg_conn, "Content-Length"); const char *cl = mg_get_header(&conn->mg_conn, "Content-Length");
if (!strcmp(conn->mg_conn.request_method, "POST") && if (!strcmp(conn->mg_conn.request_method, "POST") &&
(cl == NULL || to64(cl) > USE_POST_SIZE_LIMIT)) { (cl == NULL || to64(cl) > USE_POST_SIZE_LIMIT)) {
send_http_error(conn, 500); send_http_error(conn, 500, "POST size > %zu",
(size_t) USE_POST_SIZE_LIMIT);
} }
} }
#endif #endif
...@@ -3079,7 +3089,7 @@ static void open_local_endpoint(struct connection *conn) { ...@@ -3079,7 +3089,7 @@ static void open_local_endpoint(struct connection *conn) {
if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) { if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) {
send_options(conn); send_options(conn);
} else if (conn->server->config_options[DOCUMENT_ROOT] == NULL) { } else if (conn->server->config_options[DOCUMENT_ROOT] == NULL) {
send_http_error(conn, 404); send_http_error(conn, 404, NULL);
#ifndef NO_AUTH #ifndef NO_AUTH
} else if ((!is_dangerous_dav_request(conn) && !is_authorized(conn, path)) || } else if ((!is_dangerous_dav_request(conn) && !is_authorized(conn, path)) ||
(is_dangerous_dav_request(conn) && !is_authorized_for_dav(conn))) { (is_dangerous_dav_request(conn) && !is_authorized_for_dav(conn))) {
...@@ -3096,7 +3106,7 @@ static void open_local_endpoint(struct connection *conn) { ...@@ -3096,7 +3106,7 @@ static void open_local_endpoint(struct connection *conn) {
handle_put(conn, path); handle_put(conn, path);
#endif #endif
} else if (!exists || must_hide_file(conn, path)) { } else if (!exists || must_hide_file(conn, path)) {
send_http_error(conn, 404); send_http_error(conn, 404, NULL);
} else if (is_directory && } else if (is_directory &&
conn->mg_conn.uri[strlen(conn->mg_conn.uri) - 1] != '/') { conn->mg_conn.uri[strlen(conn->mg_conn.uri) - 1] != '/') {
conn->mg_conn.status_code = 301; conn->mg_conn.status_code = 301;
...@@ -3108,37 +3118,37 @@ static void open_local_endpoint(struct connection *conn) { ...@@ -3108,37 +3118,37 @@ static void open_local_endpoint(struct connection *conn) {
#ifndef NO_DIRECTORY_LISTING #ifndef NO_DIRECTORY_LISTING
send_directory_listing(conn, path); send_directory_listing(conn, path);
#else #else
send_http_error(conn, 501); send_http_error(conn, 501, NULL);
#endif #endif
} else { } else {
send_http_error(conn, 403); send_http_error(conn, 403, NULL);
} }
} else if (match_prefix(lua_pat, sizeof(lua_pat) - 1, path) > 0) { } else if (match_prefix(lua_pat, sizeof(lua_pat) - 1, path) > 0) {
#ifdef USE_LUA #ifdef USE_LUA
handle_lsp_request(conn, path, &st); handle_lsp_request(conn, path, &st);
#else #else
send_http_error(conn, 501); send_http_error(conn, 501, NULL);
#endif #endif
} else if (match_prefix(cgi_pat, strlen(cgi_pat), path) > 0) { } else if (match_prefix(cgi_pat, strlen(cgi_pat), path) > 0) {
if (strcmp(conn->mg_conn.request_method, "POST") && if (strcmp(conn->mg_conn.request_method, "POST") &&
strcmp(conn->mg_conn.request_method, "HEAD") && strcmp(conn->mg_conn.request_method, "HEAD") &&
strcmp(conn->mg_conn.request_method, "GET")) { strcmp(conn->mg_conn.request_method, "GET")) {
send_http_error(conn, 501); send_http_error(conn, 501, NULL);
} else { } else {
#if !defined(NO_CGI) #if !defined(NO_CGI)
open_cgi_endpoint(conn, path); open_cgi_endpoint(conn, path);
#else #else
send_http_error(conn, 501); send_http_error(conn, 501, NULL);
#endif // !NO_CGI #endif // !NO_CGI
} }
} else if (is_not_modified(conn, &st)) { } else if (is_not_modified(conn, &st)) {
send_http_error(conn, 304); send_http_error(conn, 304, NULL);
} else if ((conn->endpoint.fd = open(path, O_RDONLY | O_BINARY)) != -1) { } else if ((conn->endpoint.fd = open(path, O_RDONLY | O_BINARY)) != -1) {
// O_BINARY is required for Windows, otherwise in default text mode // O_BINARY is required for Windows, otherwise in default text mode
// two bytes \r\n will be read as one. // two bytes \r\n will be read as one.
open_file_endpoint(conn, path, &st); open_file_endpoint(conn, path, &st);
} else { } else {
send_http_error(conn, 404); send_http_error(conn, 404, NULL);
} }
} }
...@@ -3176,23 +3186,23 @@ static void process_request(struct connection *conn) { ...@@ -3176,23 +3186,23 @@ static void process_request(struct connection *conn) {
// become invalid. // become invalid.
conn->request = (char *) malloc(conn->request_len); conn->request = (char *) malloc(conn->request_len);
memcpy(conn->request, io->buf, conn->request_len); memcpy(conn->request, io->buf, conn->request_len);
DBG(("==> [%.*s]", conn->request_len, conn->request)); DBG(("%p ==> [%.*s]", conn, conn->request_len, conn->request));
memmove(io->buf, io->buf + conn->request_len, io->len - conn->request_len); memmove(io->buf, io->buf + conn->request_len, io->len - conn->request_len);
io->len -= conn->request_len; io->len -= conn->request_len;
conn->request_len = parse_http_message(conn->request, conn->request_len, conn->request_len = parse_http_message(conn->request, conn->request_len,
&conn->mg_conn); &conn->mg_conn);
} }
DBG(("%d %d", conn->request_len, io->len)); DBG(("%p %d %d", conn, conn->request_len, io->len));
if (conn->request_len < 0 || if (conn->request_len < 0 ||
(conn->request_len > 0 && !is_valid_uri(conn->mg_conn.uri))) { (conn->request_len > 0 && !is_valid_uri(conn->mg_conn.uri))) {
send_http_error(conn, 400); send_http_error(conn, 400, NULL);
} else if (conn->request_len == 0 && io->len > MAX_REQUEST_SIZE) { } else if (conn->request_len == 0 && io->len > MAX_REQUEST_SIZE) {
send_http_error(conn, 413); send_http_error(conn, 413, NULL);
} else if (conn->request_len > 0 && } else if (conn->request_len > 0 &&
strcmp(conn->mg_conn.http_version, "1.0") != 0 && strcmp(conn->mg_conn.http_version, "1.0") != 0 &&
strcmp(conn->mg_conn.http_version, "1.1") != 0) { strcmp(conn->mg_conn.http_version, "1.1") != 0) {
send_http_error(conn, 505); send_http_error(conn, 505, NULL);
} else if (conn->request_len > 0 && conn->endpoint_type == EP_NONE) { } else if (conn->request_len > 0 && conn->endpoint_type == EP_NONE) {
#ifndef NO_WEBSOCKET #ifndef NO_WEBSOCKET
send_websocket_handshake_if_requested(&conn->mg_conn); send_websocket_handshake_if_requested(&conn->mg_conn);
...@@ -3234,6 +3244,7 @@ static void read_from_client(struct connection *conn) { ...@@ -3234,6 +3244,7 @@ static void read_from_client(struct connection *conn) {
n = recv(conn->client_sock, buf, sizeof(buf), 0); n = recv(conn->client_sock, buf, sizeof(buf), 0);
} }
DBG(("%p %d", conn, n));
if (is_error(n)) { if (is_error(n)) {
conn->flags |= CONN_CLOSE; conn->flags |= CONN_CLOSE;
} else if (n > 0) { } else if (n > 0) {
...@@ -3246,7 +3257,7 @@ static void read_from_cgi(struct connection *conn) { ...@@ -3246,7 +3257,7 @@ static void read_from_cgi(struct connection *conn) {
char buf[IOBUF_SIZE]; char buf[IOBUF_SIZE];
int len, n = recv(conn->endpoint.cgi_sock, buf, sizeof(buf), 0); int len, n = recv(conn->endpoint.cgi_sock, buf, sizeof(buf), 0);
DBG(("-> %d", n)); DBG(("%p %d", conn, n));
if (is_error(n)) { if (is_error(n)) {
close_local_endpoint(conn); close_local_endpoint(conn);
} else if (n > 0) { } else if (n > 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment