You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-commits@axis.apache.org by ro...@apache.org on 2026/01/26 15:06:01 UTC

(axis-axis2-c-core) 03/04: Add custom User-Agent header support via message context property (AXIS2C-1612)

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

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-c-core.git

commit b15b11b4c73ace35efeeeb79e8418d9ca3507053
Author: Robert Lazarski <ro...@gmail.com>
AuthorDate: Mon Jan 26 04:04:41 2026 -1000

    Add custom User-Agent header support via message context property (AXIS2C-1612)
    
    Allow users to specify a custom User-Agent string by setting the
    "User-Agent" property on the message context. When this property is set,
    both the libcurl and non-libcurl HTTP transports will use the custom value
    instead of the default "Axis2C/<version>".
    
    Usage:
      axutil_property_t *ua = axutil_property_create(env);
      axutil_property_set_value(ua, env, "MyApp/1.0");
      axis2_msg_ctx_set_property(msg_ctx, env, "User-Agent", ua);
    
    Changes:
    - axis2_libcurl.c: Check for User-Agent property before setting header
    - http_sender.c: Same logic for non-libcurl transport
    - test_http_transport.cc: Add unit tests for property mechanism
    
    Co-Authored-By: Claude Opus 4.5 <no...@anthropic.com>
---
 src/core/transport/http/sender/http_sender.c       |  27 +++++-
 .../transport/http/sender/libcurl/axis2_libcurl.c  |  44 ++++++++-
 test/core/transport/http/test_http_transport.cc    | 100 +++++++++++++++++++++
 3 files changed, 168 insertions(+), 3 deletions(-)

diff --git a/src/core/transport/http/sender/http_sender.c b/src/core/transport/http/sender/http_sender.c
index 62045961f..9cdd47203 100644
--- a/src/core/transport/http/sender/http_sender.c
+++ b/src/core/transport/http/sender/http_sender.c
@@ -761,8 +761,31 @@ axis2_http_sender_send(
         axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_COOKIE, cookie_str);
     }
 
-    /* User-Agent:Axis2/C header */
-    axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_USER_AGENT, AXIS2_USER_AGENT);
+    /* AXIS2C-1612: User-Agent header - check for custom value */
+    {
+        axutil_property_t *user_agent_property = NULL;
+        axis2_char_t *user_agent_value = NULL;
+
+        user_agent_property = (axutil_property_t *)axis2_msg_ctx_get_property(
+            msg_ctx, env, AXIS2_HTTP_HEADER_USER_AGENT);
+
+        if (user_agent_property)
+        {
+            user_agent_value = (axis2_char_t *)axutil_property_get_value(
+                user_agent_property, env);
+        }
+
+        if (user_agent_value)
+        {
+            axis2_http_sender_util_add_header(env, request,
+                AXIS2_HTTP_HEADER_USER_AGENT, user_agent_value);
+        }
+        else
+        {
+            axis2_http_sender_util_add_header(env, request,
+                AXIS2_HTTP_HEADER_USER_AGENT, AXIS2_USER_AGENT);
+        }
+    }
 
     http_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_TRANSPORT_HEADER_PROPERTY);
     if(http_property)
diff --git a/src/core/transport/http/sender/libcurl/axis2_libcurl.c b/src/core/transport/http/sender/libcurl/axis2_libcurl.c
index f6afd82c2..d20afbe2e 100644
--- a/src/core/transport/http/sender/libcurl/axis2_libcurl.c
+++ b/src/core/transport/http/sender/libcurl/axis2_libcurl.c
@@ -148,7 +148,49 @@ axis2_libcurl_send(
     handler = data->handler;
     curl_easy_reset(handler);
     curl_easy_setopt(handler, CURLOPT_ERRORBUFFER, data->errorbuffer);
-    headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_USER_AGENT_AXIS2C);
+
+    /* AXIS2C-1612: Check for custom User-Agent property */
+    {
+        axutil_property_t *user_agent_property = NULL;
+        axis2_char_t *user_agent_value = NULL;
+
+        user_agent_property = (axutil_property_t *)axis2_msg_ctx_get_property(
+            msg_ctx, env, AXIS2_HTTP_HEADER_USER_AGENT);
+
+        if (user_agent_property)
+        {
+            user_agent_value = (axis2_char_t *)axutil_property_get_value(
+                user_agent_property, env);
+        }
+
+        if (user_agent_value)
+        {
+            axis2_char_t *user_agent_header = NULL;
+            int header_len = axutil_strlen(AXIS2_HTTP_HEADER_USER_AGENT) +
+                             axutil_strlen(user_agent_value) + 3;
+
+            user_agent_header = AXIS2_MALLOC(env->allocator,
+                header_len * sizeof(axis2_char_t));
+            if (user_agent_header)
+            {
+                sprintf(user_agent_header, "%s: %s",
+                    AXIS2_HTTP_HEADER_USER_AGENT, user_agent_value);
+                headers = curl_slist_append(headers, user_agent_header);
+                /* curl_slist_append copies the string, so free our copy */
+                AXIS2_FREE(env->allocator, user_agent_header);
+            }
+            else
+            {
+                /* Fallback to default on allocation failure */
+                headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_USER_AGENT_AXIS2C);
+            }
+        }
+        else
+        {
+            headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_USER_AGENT_AXIS2C);
+        }
+    }
+
     headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_ACCEPT_);
     headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_EXPECT_);
 
diff --git a/test/core/transport/http/test_http_transport.cc b/test/core/transport/http/test_http_transport.cc
index 79fc16cc9..45c66e5ec 100644
--- a/test/core/transport/http/test_http_transport.cc
+++ b/test/core/transport/http/test_http_transport.cc
@@ -39,6 +39,8 @@
 #endif
 #include <axis2_simple_http_svr_conn.h>
 #include <axis2_http_transport_utils.h>
+#include <axis2_msg_ctx.h>
+#include <axis2_http_transport.h>
 
 #include "../../../cutest/include/cut_http_server.h"
 
@@ -1221,3 +1223,101 @@ TEST_F(TestHTTPTransport, DISABLED_test_AXIS2C_1480_large_body)
 
     printf("Finished AXIS2C-1480 large body test ..........\n\n");
 }
+
+/**
+ * Test for AXIS2C-1612: Custom HTTP HEADER USER AGENT
+ *
+ * This test verifies that custom User-Agent strings can be set via
+ * the message context property AXIS2_HTTP_HEADER_USER_AGENT ("User-Agent").
+ * When this property is set, the HTTP transport should use it instead of
+ * the default "Axis2C/<version>" User-Agent string.
+ *
+ * This test validates the property setting/retrieval mechanism. Full
+ * integration testing (verifying the header is actually sent) would require
+ * a mock server that captures request headers.
+ */
+TEST_F(TestHTTPTransport, test_AXIS2C_1612_custom_user_agent_property)
+{
+    axis2_msg_ctx_t *msg_ctx = NULL;
+    axutil_property_t *user_agent_property = NULL;
+    axutil_property_t *retrieved_property = NULL;
+    axis2_char_t *custom_user_agent = (axis2_char_t *)"MyApp/1.0 (Custom User Agent)";
+    axis2_char_t *retrieved_value = NULL;
+
+    printf("Starting AXIS2C-1612 test (custom User-Agent property)\n");
+
+    /* Create a message context */
+    msg_ctx = axis2_msg_ctx_create(m_env, NULL, NULL, NULL);
+    ASSERT_NE(msg_ctx, nullptr) << "Failed to create msg_ctx";
+
+    /* Create property with custom User-Agent value */
+    user_agent_property = axutil_property_create(m_env);
+    ASSERT_NE(user_agent_property, nullptr) << "Failed to create property";
+
+    /* Set the property value - don't let property own it since it's a string literal */
+    axutil_property_set_value(user_agent_property, m_env, custom_user_agent);
+    axutil_property_set_own_value(user_agent_property, m_env, AXIS2_FALSE);
+
+    /* Set the property on msg_ctx using the standard User-Agent key */
+    axis2_msg_ctx_set_property(msg_ctx, m_env, AXIS2_HTTP_HEADER_USER_AGENT, user_agent_property);
+
+    /* Retrieve the property and verify it matches */
+    retrieved_property = (axutil_property_t *)axis2_msg_ctx_get_property(
+        msg_ctx, m_env, AXIS2_HTTP_HEADER_USER_AGENT);
+    ASSERT_NE(retrieved_property, nullptr)
+        << "AXIS2C-1612: User-Agent property should be retrievable from msg_ctx";
+
+    retrieved_value = (axis2_char_t *)axutil_property_get_value(retrieved_property, m_env);
+    ASSERT_NE(retrieved_value, nullptr)
+        << "AXIS2C-1612: User-Agent property value should not be NULL";
+
+    ASSERT_STREQ(retrieved_value, custom_user_agent)
+        << "AXIS2C-1612: Retrieved User-Agent should match set value";
+
+    printf("  Custom User-Agent set: '%s'\n", custom_user_agent);
+    printf("  Retrieved User-Agent:  '%s'\n", retrieved_value);
+    printf("  Property mechanism verified successfully\n");
+
+    /* Verify the default constant is what we expect */
+    printf("  Default User-Agent constant: '%s'\n", AXIS2_USER_AGENT);
+    ASSERT_NE(strstr(AXIS2_USER_AGENT, "Axis2C"), nullptr)
+        << "Default User-Agent should contain 'Axis2C'";
+
+    /* Cleanup - msg_ctx_free will free the property */
+    axis2_msg_ctx_free(msg_ctx, m_env);
+
+    printf("Finished AXIS2C-1612 test ..........\n\n");
+}
+
+/**
+ * Test for AXIS2C-1612: Verify default User-Agent when property not set
+ *
+ * This test verifies that when the User-Agent property is NOT set,
+ * the default value is used (no property should be returned).
+ */
+TEST_F(TestHTTPTransport, test_AXIS2C_1612_default_user_agent_when_not_set)
+{
+    axis2_msg_ctx_t *msg_ctx = NULL;
+    axutil_property_t *retrieved_property = NULL;
+
+    printf("Starting AXIS2C-1612 default User-Agent test\n");
+
+    /* Create a message context without setting User-Agent property */
+    msg_ctx = axis2_msg_ctx_create(m_env, NULL, NULL, NULL);
+    ASSERT_NE(msg_ctx, nullptr);
+
+    /* Try to retrieve User-Agent property - should be NULL (not set) */
+    retrieved_property = (axutil_property_t *)axis2_msg_ctx_get_property(
+        msg_ctx, m_env, AXIS2_HTTP_HEADER_USER_AGENT);
+
+    /* When not set, the transport code falls back to AXIS2_USER_AGENT constant */
+    ASSERT_EQ(retrieved_property, nullptr)
+        << "AXIS2C-1612: When not set, property should be NULL (code uses default)";
+
+    printf("  No custom User-Agent property set\n");
+    printf("  Transport will use default: '%s'\n", AXIS2_USER_AGENT);
+
+    axis2_msg_ctx_free(msg_ctx, m_env);
+
+    printf("Finished AXIS2C-1612 default test ..........\n\n");
+}