diff --git a/main.c b/main.c index 1028b43e..3f92bbf9 100644 --- a/main.c +++ b/main.c @@ -219,7 +219,7 @@ static void init_server_name(void) { static void *mongoose_callback(enum mg_event ev, struct mg_connection *conn) { if (ev == MG_EVENT_LOG) { - printf("%s\n", mg_get_request_info(conn)->log_message); + printf("%s\n", mg_get_log_message(conn)); } return NULL; diff --git a/mongoose.c b/mongoose.c index d7e4d6ad..cf523a96 100644 --- a/mongoose.c +++ b/mongoose.c @@ -497,10 +497,12 @@ struct mg_connection { char *path_info; // PATH_INFO part of the URL char *body; // Pointer to not-read yet buffered body data char *next_request; // Pointer to the buffered next request + char *log_message; // Placeholder for the mongoose error log message int must_close; // 1 if connection must be closed int buf_size; // Buffer size int request_len; // Size of the request + headers in a buffer int data_len; // Total size of data in a buffer + int status_code; // HTTP reply status code, e.g. 200 }; const char **mg_get_valid_option_names(void) { @@ -508,9 +510,20 @@ const char **mg_get_valid_option_names(void) { } static void *call_user(struct mg_connection *conn, enum mg_event event) { - conn->request_info.user_data = conn->ctx->user_data; - return conn->ctx->user_callback == NULL ? NULL : - conn->ctx->user_callback(event, conn); + return conn == NULL || conn->ctx == NULL || conn->ctx->user_callback == NULL ? + NULL : conn->ctx->user_callback(event, conn); +} + +void *mg_get_user_data(struct mg_connection *conn) { + return conn != NULL && conn->ctx != NULL ? conn->ctx->user_data : NULL; +} + +const char *mg_get_log_message(const struct mg_connection *conn) { + return conn == NULL ? NULL : conn->log_message; +} + +int mg_get_reply_status_code(const struct mg_connection *conn) { + return conn == NULL ? -1 : conn->status_code; } static int get_option_index(const char *name) { @@ -565,7 +578,7 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) { // Do not lock when getting the callback value, here and below. // I suppose this is fine, since function cannot disappear in the // same way string option can. - conn->request_info.log_message = buf; + conn->log_message = buf; if (call_user(conn, MG_EVENT_LOG) == NULL) { fp = conn->ctx->config[ERROR_LOG_FILE] == NULL ? NULL : mg_fopen(conn->ctx->config[ERROR_LOG_FILE], "a+"); @@ -591,7 +604,7 @@ static void cry(struct mg_connection *conn, const char *fmt, ...) { } } } - conn->request_info.log_message = NULL; + conn->log_message = NULL; } // Return fake connection structure. Used for logging, if connection @@ -849,7 +862,7 @@ static int should_keep_alive(const struct mg_connection *conn) { const char *http_version = conn->request_info.http_version; const char *header = mg_get_header(conn, "Connection"); if (conn->must_close || - conn->request_info.status_code == 401 || + conn->status_code == 401 || mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0 || (header != NULL && mg_strcasecmp(header, "keep-alive") != 0) || (header == NULL && http_version && strcmp(http_version, "1.1"))) { @@ -873,7 +886,7 @@ static void send_http_error(struct mg_connection *conn, int status, va_list ap; int len; - conn->request_info.status_code = status; + conn->status_code = status; if (call_user(conn, MG_HTTP_ERROR) == NULL) { buf[0] = '\0'; @@ -2289,7 +2302,7 @@ static int check_authorization(struct mg_connection *conn, const char *path) { } static void send_authorization_request(struct mg_connection *conn) { - conn->request_info.status_code = 401; + conn->status_code = 401; (void) mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n" "Content-Length: 0\r\n" @@ -2582,7 +2595,7 @@ static void handle_directory_request(struct mg_connection *conn, free(data.entries); conn->num_bytes_sent += mg_printf(conn, "%s", ""); - conn->request_info.status_code = 200; + conn->status_code = 200; } // Send len bytes from the opened file to the client. @@ -2639,7 +2652,7 @@ static void handle_file_request(struct mg_connection *conn, const char *path, get_mime_type(conn->ctx, path, &mime_vec); cl = stp->size; - conn->request_info.status_code = 200; + conn->status_code = 200; range[0] = '\0'; if ((fp = mg_fopen(path, "rb")) == NULL) { @@ -2653,7 +2666,7 @@ static void handle_file_request(struct mg_connection *conn, const char *path, r1 = r2 = 0; hdr = mg_get_header(conn, "Range"); if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0) { - conn->request_info.status_code = 206; + conn->status_code = 206; (void) fseeko(fp, r1, SEEK_SET); cl = n == 2 ? r2 - r1 + 1: cl - r1; (void) mg_snprintf(conn, range, sizeof(range), @@ -2680,7 +2693,7 @@ static void handle_file_request(struct mg_connection *conn, const char *path, "Connection: %s\r\n" "Accept-Ranges: bytes\r\n" "%s\r\n", - conn->request_info.status_code, msg, date, lm, etag, (int) mime_vec.len, + conn->status_code, msg, date, lm, etag, (int) mime_vec.len, mime_vec.ptr, cl, suggest_connection_header(conn), range); if (strcmp(conn->request_info.request_method, "HEAD") != 0) { @@ -2729,7 +2742,6 @@ static int parse_http_message(char *buf, int len, struct mg_request_info *ri) { // Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port ri->remote_user = ri->request_method = ri->uri = ri->http_version = NULL; ri->num_headers = 0; - ri->status_code = -1; buf[request_length - 1] = '\0'; @@ -3144,21 +3156,21 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) { // Make up and send the status line status_text = "OK"; if ((status = get_header(&ri, "Status")) != NULL) { - conn->request_info.status_code = atoi(status); + conn->status_code = atoi(status); status_text = status; while (isdigit(* (unsigned char *) status_text) || *status_text == ' ') { status_text++; } } else if (get_header(&ri, "Location") != NULL) { - conn->request_info.status_code = 302; + conn->status_code = 302; } else { - conn->request_info.status_code = 200; + conn->status_code = 200; } if (get_header(&ri, "Connection") != NULL && !mg_strcasecmp(get_header(&ri, "Connection"), "keep-alive")) { conn->must_close = 1; } - (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->request_info.status_code, + (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text); // Send headers @@ -3241,10 +3253,10 @@ static void put_file(struct mg_connection *conn, const char *path) { FILE *fp; int rc; - conn->request_info.status_code = mg_stat(path, &st) == 0 ? 200 : 201; + conn->status_code = mg_stat(path, &st) == 0 ? 200 : 201; if ((rc = put_dir(path)) == 0) { - mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->request_info.status_code); + mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->status_code); } else if (rc == -1) { send_http_error(conn, 500, http_500_error, "put_dir(%s): %s", path, strerror(ERRNO)); @@ -3256,13 +3268,13 @@ static void put_file(struct mg_connection *conn, const char *path) { range = mg_get_header(conn, "Content-Range"); r1 = r2 = 0; if (range != NULL && parse_range_header(range, &r1, &r2) > 0) { - conn->request_info.status_code = 206; + conn->status_code = 206; // TODO(lsm): handle seek error (void) fseeko(fp, r1, SEEK_SET); } - if (forward_body_data(conn, fp, INVALID_SOCKET, NULL)) - (void) mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", - conn->request_info.status_code); + if (forward_body_data(conn, fp, INVALID_SOCKET, NULL)) { + (void) mg_printf(conn, "HTTP/1.1 %d OK\r\n\r\n", conn->status_code); + } (void) fclose(fp); } } @@ -3412,7 +3424,7 @@ static void handle_ssi_file_request(struct mg_connection *conn, } static void send_options(struct mg_connection *conn) { - conn->request_info.status_code = 200; + conn->status_code = 200; (void) mg_printf(conn, "HTTP/1.1 200 OK\r\n" @@ -3456,7 +3468,7 @@ static void handle_propfind(struct mg_connection *conn, const char* path, const char *depth = mg_get_header(conn, "Depth"); conn->must_close = 1; - conn->request_info.status_code = 207; + conn->status_code = 207; mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n" "Connection: close\r\n" "Content-Type: text/xml; charset=utf-8\r\n\r\n"); @@ -3694,7 +3706,7 @@ static void log_access(const struct mg_connection *conn) { src_addr, ri->remote_user == NULL ? "-" : ri->remote_user, date, ri->request_method ? ri->request_method : "-", ri->uri ? ri->uri : "-", ri->http_version, - conn->request_info.status_code, conn->num_bytes_sent); + conn->status_code, conn->num_bytes_sent); log_header(conn, "Referer", fp); log_header(conn, "User-Agent", fp); fputc('\n', fp); @@ -3848,7 +3860,6 @@ static int load_dll(struct mg_context *ctx, const char *dll_name, // Dynamically load SSL library. Set up ctx->ssl_ctx pointer. static int set_ssl_option(struct mg_context *ctx) { - static struct mg_request_info fake_request_info; int i, size; const char *pem = ctx->config[SSL_CERTIFICATE]; @@ -3873,7 +3884,6 @@ static int set_ssl_option(struct mg_context *ctx) { } if (ctx->user_callback != NULL) { - fake_request_info.user_data = ctx->user_data; ctx->user_callback(MG_INIT_SSL, (struct mg_connection *) ctx->ssl_ctx); } @@ -3928,11 +3938,12 @@ static int set_acl_option(struct mg_context *ctx) { } static void reset_per_request_attributes(struct mg_connection *conn) { - conn->path_info = conn->body = conn->next_request = NULL; + conn->path_info = conn->body = conn->next_request = conn->log_message = NULL; conn->num_bytes_sent = conn->consumed_content = 0; conn->content_len = -1; conn->request_len = conn->data_len = 0; conn->must_close = 0; + conn->status_code = -1; } static void close_socket_gracefully(struct mg_connection *conn) { diff --git a/mongoose.h b/mongoose.h index 2fdf9348..90336769 100644 --- a/mongoose.h +++ b/mongoose.h @@ -34,16 +34,13 @@ struct mg_connection; // Handle for the individual connection // This structure contains information about the HTTP request. struct mg_request_info { - void *user_data; // User-defined pointer passed to mg_start() char *request_method; // "GET", "POST", etc char *uri; // URL-decoded URI char *http_version; // E.g. "1.0", "1.1" char *query_string; // URL part after '?' (not including '?') or NULL char *remote_user; // Authenticated user, or NULL if no auth used - char *log_message; // Mongoose error log message, MG_EVENT_LOG only long remote_ip; // Client's IP address int remote_port; // Client's port - int status_code; // HTTP reply status code, e.g. 200 int is_ssl; // 1 if SSL-ed, 0 if not int num_headers; // Number of headers struct mg_header { @@ -151,9 +148,12 @@ int mg_modify_passwords_file(const char *passwords_file_name, const char *password); -// Return mg_request_info structure associated with the request. -// Always succeeds. +// Return information associated with the request. +// These functions always succeed. const struct mg_request_info *mg_get_request_info(const struct mg_connection *); +void *mg_get_user_data(struct mg_connection *); +const char *mg_get_log_message(const struct mg_connection *); +int mg_get_reply_status_code(const struct mg_connection *); // Send data to the client. diff --git a/test/embed.c b/test/embed.c index 0d4e602d..4033507f 100644 --- a/test/embed.c +++ b/test/embed.c @@ -119,9 +119,10 @@ static void test_get_request_info(struct mg_connection *conn, static void test_error(struct mg_connection *conn, const struct mg_request_info *ri) { + (void) ri; mg_printf(conn, "HTTP/1.1 %d XX\r\n" - "Conntection: close\r\n\r\n", ri->status_code); - mg_printf(conn, "Error: [%d]", ri->status_code); + "Conntection: close\r\n\r\n", mg_get_reply_status_code(conn)); + mg_printf(conn, "Error: [%d]", mg_get_reply_status_code(conn)); } static void test_post(struct mg_connection *conn, diff --git a/test/unit_test.c b/test/unit_test.c index 35646499..ea2befdf 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -64,10 +64,10 @@ static void test_should_keep_alive(void) { parse_http_request(req4, sizeof(req4), &conn.request_info); ASSERT(should_keep_alive(&conn) == 1); - conn.request_info.status_code = 401; + conn.status_code = 401; ASSERT(should_keep_alive(&conn) == 0); - conn.request_info.status_code = 200; + conn.status_code = 200; conn.must_close = 1; ASSERT(should_keep_alive(&conn) == 0); } @@ -138,7 +138,7 @@ static void *event_handler(enum mg_event event, "%s", (int) strlen(fetch_data), fetch_data); return ""; } else if (event == MG_EVENT_LOG) { - printf("%s\n", request_info->log_message); + printf("%s\n", mg_get_log_message(conn)); } return NULL;