This is an automated email from the ASF dual-hosted git repository.

ChristopherSchultz pushed a commit to branch use-posts-for-writes
in repository https://gitbox.apache.org/repos/asf/tomcat-connectors.git

commit 4da085a3f26359efa5b5c2c22f9c0141b4a7b0e4
Author: ChristopherSchultz <[email protected]>
AuthorDate: Tue Oct 20 16:16:13 2026 +0000

    Add POST parameter handling
---
 native/common/jk_status.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 155 insertions(+)

diff --git a/native/common/jk_status.c b/native/common/jk_status.c
index 842b403b1..be47871af 100644
--- a/native/common/jk_status.c
+++ b/native/common/jk_status.c
@@ -37,6 +37,7 @@
 #include "jk_url.h"
 
 #define HUGE_BUFFER_SIZE (8*1024)
+#define JK_STATUS_POST_MAX_SIZE (64 * 1024)
 
 /**
  * Command line reference:
@@ -1423,6 +1424,147 @@ static int status_parse_uri(jk_ws_service_t *s,
     return JK_TRUE;
 }
 
+/*
+ * Parses a POST request into the service's parameter map.
+ *
+ * Only works for application/x-www-form-urlencoded content-type
+ * and a non-chunked transfer encoding.
+ *
+ * If any errors occur, the parameter map will not be modified.
+ *
+ * Returns JK_TRUE on success, JK_FALSE on failure.
+ */
+static int status_parse_post(jk_ws_service_t *s,
+                             status_endpoint_t *p,
+                             jk_log_context_t *l)
+{
+    status_worker_t *w = p->worker;
+    const char *content_type = NULL;
+    unsigned int content_type_count = 0;
+    unsigned int i;
+    unsigned int len;
+    unsigned int offset = 0;
+    char *body;
+    status_endpoint_t post_p;
+    jk_ws_service_t post_s;
+
+    JK_TRACE_ENTER(l);
+
+    /* Reject chunked requests and invalid body lengths. */
+    if (s->is_chunked ||
+        s->content_length < 1 ||
+        s->content_length > JK_STATUS_POST_MAX_SIZE) {
+        jk_log(l, JK_LOG_WARNING,
+               "Status worker '%s' rejected POST with invalid content length",
+               w->name);
+        JK_TRACE_EXIT(l);
+        return JK_FALSE;
+    }
+
+    /*
+     * Require exactly one Content-Type header with the expected
+     * media type. Parameters such as charset=UTF-8 are not accepted.
+     */
+    for (i = 0; i < s->num_headers; i++) {
+        if (s->headers_names[i] &&
+            !strcmp(s->headers_names[i], "Content-Type")) {
+            content_type = s->headers_values[i];
+            content_type_count++;
+        }
+    }
+
+    if (content_type_count != 1 || !content_type ||
+        strcasecmp(content_type, "application/x-www-form-urlencoded") != 0) {
+        jk_log(l, JK_LOG_WARNING,
+               "Status worker '%s' rejected POST with invalid Content-Type",
+               w->name);
+        JK_TRACE_EXIT(l);
+        return JK_FALSE;
+    }
+
+    /*
+     * Keep POST parsing unambiguous: this initial implementation
+     * accepts body parameters only, with no existing parameter map.
+     */
+    if (p->req_params || (s->query_string && s->query_string[0])) {
+        jk_log(l, JK_LOG_WARNING,
+               "Status worker '%s' rejected POST with existing URI parameters",
+               w->name);
+        JK_TRACE_EXIT(l);
+        return JK_FALSE;
+    }
+
+    len = (unsigned int)s->content_length;
+    body = jk_pool_alloc(s->pool, (size_t)len + 1);
+    if (!body) {
+        jk_log(l, JK_LOG_WARNING,
+               "Status worker '%s' could not allocate POST body",
+               w->name);
+        JK_TRACE_EXIT(l);
+        return JK_FALSE;
+    }
+
+    if (!s->read) {
+        jk_log(l, JK_LOG_WARNING,
+               "Status worker '%s' cannot read POST body",
+               w->name);
+        JK_TRACE_EXIT(l);
+        return JK_FALSE;
+    }
+
+    /* Read the complete body, allowing for partial reads. */
+    while (offset < len) {
+        unsigned int actually_read = 0;
+
+        if (s->read(s, body + offset, len - offset,
+                    &actually_read) != JK_TRUE ||
+            actually_read == 0 ||
+            actually_read > len - offset) {
+            jk_log(l, JK_LOG_WARNING,
+                   "Status worker '%s' failed reading POST body",
+                   w->name);
+            JK_TRACE_EXIT(l);
+            return JK_FALSE;
+        }
+        offset += actually_read;
+    }
+
+    /* The existing parser expects a NUL-terminated string. */
+    if (memchr(body, '\0', len) != NULL) {
+        jk_log(l, JK_LOG_WARNING,
+               "Status worker '%s' rejected POST containing NUL bytes",
+               w->name);
+        JK_TRACE_EXIT(l);
+        return JK_FALSE;
+    }
+    body[len] = '\0';
+
+    /*
+     * Parse into a temporary endpoint. Do not modify the real
+     * parameter map unless the entire parse succeeds.
+     */
+    post_p = *p;
+    post_p.req_params = NULL;
+    post_p.query_string = NULL;
+
+    post_s = *s;
+    post_s.query_string = body;
+
+    if (status_parse_uri(&post_s, &post_p, l) != JK_TRUE) {
+        jk_log(l, JK_LOG_WARNING,
+               "Status worker '%s' failed to parse POST parameters",
+               w->name);
+        JK_TRACE_EXIT(l);
+        return JK_FALSE;
+    }
+
+    p->req_params = post_p.req_params;
+    p->query_string = post_p.query_string;
+
+    JK_TRACE_EXIT(l);
+    return JK_TRUE;
+}
+
 static void write_html_refresh_response(jk_ws_service_t *s,
                                         status_endpoint_t *p,
                                         const char *err,
@@ -4823,6 +4965,19 @@ static int JK_METHOD service(jk_endpoint_t *e,
         JK_TRACE_EXIT(l);
         return JK_FALSE;
     }
+
+    /* If this is a post, merge POST parameters into any existing GET 
parameters */
+    if (!err && !strcmp(s->method, "POST")) {
+        if (status_parse_post(s, p, l) != JK_TRUE) {
+            jk_log(l, JK_LOG_ERROR,
+                   "Status worker '%s' failed to parse POST body",
+                   w->name);
+
+            JK_TRACE_EXIT(l);
+            return JK_FALSE;
+        }
+    }
+
     status_get_string(p, JK_STATUS_ARG_CMD, NULL, &arg, l);
     cmd = status_cmd_int(arg);
     cmd_props = status_cmd_props(cmd);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to