Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,12 @@ public Builder property(String name, Object value) {
}
if (value == null) {
filterProps.remove(name);
contextProps.remove(name);
} else {
filterProps.put(name, value);
// CXF-9235: also write to the top-level context so that the transport layer
// can find the property via Message.getContextualProperty()
contextProps.put(name, value);
}
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.apache.cxf.jaxrs.client.spec;

import java.io.IOException;
import java.util.Map;

import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
Expand All @@ -28,15 +29,21 @@
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.transport.http.Headers;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

public class InvocationBuilderImplTest {

private static final String FILTER_PROPS_KEY = "jaxrs.filter.properties";

public static class TestFilter implements ClientRequestFilter {

/** {@inheritDoc}*/
Expand Down Expand Up @@ -83,4 +90,58 @@ public void testHeadersMethod() {
response = builder.get();
assertEquals("", response.readEntity(String.class));
}

/**
* CXF-9235: Invocation.Builder.property() must write the property value into BOTH:
*
* (a) the nested "jaxrs.filter.properties" sub-map inside the ClientConfiguration
* request context — this is what context.getProperty() reads inside a
* ClientRequestFilter (via MessagePropertyHolder / Exchange.get(PROPERTY_KEY)).
*
* (b) the flat top-level ClientConfiguration request context — this is what the
* HTTP transport reads via Message.getContextualProperty() in
* Headers.setProtocolHeadersInConnection().
*
* Before the fix only (a) was written. The transport (b) path was silently missing,
* meaning a property like "set.content.type.for.empty.request" set on the
* Invocation.Builder had no effect on the conduit.
*/
@Test
public void testPropertyWrittenToBothFilterPropsAndFlatContext() {
Client client = ClientBuilder.newClient().register(TestFilter.class);
Builder builder = client.target("http://localhost:8080/notReal").request();

// ---- set ----
builder.property(Headers.SET_EMPTY_REQUEST_CT_PROPERTY, Boolean.FALSE);

InvocationBuilderImpl builderImpl = (InvocationBuilderImpl) builder;
Map<String, Object> requestContext =
WebClient.getConfig(builderImpl.getWebClient()).getRequestContext();

// (a) Must be in the nested filterProps sub-map that a ClientRequestFilter reads.
// This path was already written before the fix; we guard it stays working.
Map<String, Object> filterProps =
CastUtils.cast((Map<?, ?>) requestContext.get(FILTER_PROPS_KEY));
assertTrue("jaxrs.filter.properties sub-map must exist after Builder.property()",
filterProps != null && filterProps.containsKey(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));
assertEquals("Value in filterProps must match what was set",
Boolean.FALSE, filterProps.get(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));

// (b) Must also be present flat in the top-level context — the path the HTTP
// transport reads via Message.getContextualProperty(). This was the bug in
// CXF-9235: only (a) was written, so the transport never saw the property.
assertEquals("Flat request context must contain the property for the transport layer (CXF-9235)",
Boolean.FALSE, requestContext.get(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));

// ---- remove (null value) ----
builder.property(Headers.SET_EMPTY_REQUEST_CT_PROPERTY, null);

// (a) removed from filterProps
assertNull("Null value must remove property from filterProps sub-map",
filterProps.get(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));

// (b) removed from flat context
assertFalse("Null value must remove property from the flat transport context (CXF-9235)",
requestContext.containsKey(Headers.SET_EMPTY_REQUEST_CT_PROPERTY));
}
}
Loading