// 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.
+// disclosure is subject to the GNU General Public License v3.
+
+// uncomment one or more of these to see raw http transactions
+//#define DEBUG_HTTP
+//#define REQUEST_BODY_TO_STDERR
+//#define RESPONSE_BODY_TO_STDERR
#include "webcit.h"
new_request_header.key = strdup(buf);
++c;
new_request_header.val = strdup(c);
- striplt(new_request_header.key);
- striplt(new_request_header.val);
+ string_trim(new_request_header.key);
+ 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
}
}
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
}
}
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");
}
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
}
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");
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);
}
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);