Skeleton code for filters.
[citadel.git] / webcit-ng / server / http.c
index 161c070f52a6a13f3af4b8e3f6beb3052bdc02a9..c770cd30e76e046806848e8d2c371f43b81ed1ca 100644 (file)
@@ -1,9 +1,8 @@
 // This module handles HTTP transactions.
 //
-// Copyright (c) 1996-2022 by the citadel.org team
+// Copyright (c) 1996-2023 by the citadel.org team
 //
-// This program is open source software.  Use, duplication, or
-// disclosure are subject to the GNU General Public License v3.
+// This program is open source software.  Use, duplication, or disclosure is subject to the GNU General Public License v3.
 
 #include "webcit.h"
 
@@ -144,7 +143,7 @@ void perform_one_http_transaction(struct client_handle *ch) {
                                string_trim(new_request_header.val);
                                array_append(h.request_headers, &new_request_header);
 #ifdef DEBUG_HTTP
-                               syslog(LOG_DEBUG, "\033[1m\033[35m{ %s: %s\033[0m", new_request_header.key, new_request_header.val);
+                               syslog(LOG_DEBUG, "{ %s: %s", new_request_header.key, new_request_header.val);
 #endif
                        }
                }
@@ -166,7 +165,7 @@ void perform_one_http_transaction(struct client_handle *ch) {
                                kv.val = strdup(eq);
                                array_append(h.request_parms, &kv);
 #ifdef DEBUG_HTTP
-                               syslog(LOG_DEBUG, "\033[1m\033[33m| %s = %s\033[0m", kv.key, kv.val);
+                               syslog(LOG_DEBUG, "| %s = %s", kv.key, kv.val);
 #endif
                        }
                }
@@ -192,9 +191,9 @@ void perform_one_http_transaction(struct client_handle *ch) {
                syslog(LOG_DEBUG, "Client disconnected");
        }
        else {
-//#ifdef DEBUG_HTTP
-               syslog(LOG_DEBUG, "\033[33m\033[1m< %s %s\033[0m", h.method, h.url);
-//#endif
+#ifdef DEBUG_HTTP
+               syslog(LOG_DEBUG, "< %s %s", h.method, h.url);
+#endif
 
                // If there is a request body, read it now.
                char *ccl = header_val(&h, "Content-Length");
@@ -203,14 +202,30 @@ void perform_one_http_transaction(struct client_handle *ch) {
                }
                if (h.request_body_length > 0) {
                        syslog(LOG_DEBUG, "Reading request body (%ld bytes)", h.request_body_length);
-                       h.request_body = malloc(h.request_body_length);
+
+                       // Sometimes we need the request body by itself, sometimes we need it with headers.
+                       // So we save it with synthetic headers, and also provide a pointer into the place where the body begins.
+
+                       char *cct = header_val(&h, "Content-Type");
+                       if (cct) {
+                               h.request_body_with_synth_headers = malloc(h.request_body_length + 1024);
+                               memset(h.request_body_with_synth_headers, h.request_body_length + 1024, 0);
+                               sprintf(h.request_body_with_synth_headers, "Content-Type: %s\r\n\r\n", cct);
+                               h.request_body = h.request_body_with_synth_headers + strlen(h.request_body_with_synth_headers);
+                       }
+                       else {  // a request body absent a Content-Type: header is invalid, but handle it anyway.
+                               h.request_body_with_synth_headers = malloc(h.request_body_length);
+                               memset(h.request_body_with_synth_headers, h.request_body_length, 0);
+                               h.request_body = h.request_body_with_synth_headers;
+                       }
+
                        client_read(ch, h.request_body, h.request_body_length);
 
                        // Write the entire request body to stderr -- not what you want during normal operation.
-                       #ifdef BODY_TO_STDERR
-                       write(2, HKEY("\033[31m"));
+                       #ifdef REQUEST_BODY_TO_STDERR
+                       write(2, HKEY("--- REQUEST BODY BEGIN ---\n"));
                        write(2, h.request_body, h.request_body_length);
-                       write(2, HKEY("\033[0m\n"));
+                       write(2, HKEY("--- REQUEST BODY END ---\n"));
                        #endif
 
                }
@@ -219,15 +234,15 @@ void perform_one_http_transaction(struct client_handle *ch) {
                perform_request(&h);
 
                // Write the entire response body to stderr -- not what you want during normal operation.
-               #ifdef BODY_TO_STDERR
-               write(2, HKEY("\033[32m"));
+               #ifdef RESPONSE_BODY_TO_STDERR
+               write(2, HKEY("--- RESPONSE BODY BEGIN ---\n"));
                write(2, h.response_body, h.response_body_length);
-               write(2, HKEY("\033[0m\n"));
+               write(2, HKEY("--- RESPONSE BODY END ---\n"));
                #endif
 
                // Output the results back to the client.
 #ifdef DEBUG_HTTP
-               syslog(LOG_DEBUG, "\033[33m\033[1m> %03d %s\033[0m", h.response_code, h.response_string);
+               syslog(LOG_DEBUG, "> %03d %s", h.response_code, h.response_string);
 #endif
                client_printf(ch, "HTTP/1.1 %03d %s\r\n", h.response_code, h.response_string);
                client_printf(ch, "Connection: close\r\n");
@@ -243,7 +258,7 @@ void perform_one_http_transaction(struct client_handle *ch) {
                for (i=0; i<number_of_response_headers; ++i) {
                        struct keyval *kv = array_get_element_at(h.response_headers, i);
 #ifdef DEBUG_HTTP
-                       syslog(LOG_DEBUG, "\033[1m\033[35m} %s: %s\033[0m", kv->key, kv->val);
+                       syslog(LOG_DEBUG, "} %s: %s", kv->key, kv->val);
 #endif
                        client_printf(ch, "%s: %s\r\n", kv->key, kv->val);
                }
@@ -281,8 +296,8 @@ void perform_one_http_transaction(struct client_handle *ch) {
        if (h.url) {
                free(h.url);
        }
-       if (h.request_body) {
-               free(h.request_body);
+       if (h.request_body_with_synth_headers) {
+               free(h.request_body_with_synth_headers);
        }
        if (h.response_string) {
                free(h.response_string);