Return-Path: X-Original-To: apmail-camel-commits-archive@www.apache.org Delivered-To: apmail-camel-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CD4EA17369 for ; Sat, 13 Jun 2015 10:33:14 +0000 (UTC) Received: (qmail 96560 invoked by uid 500); 13 Jun 2015 10:33:14 -0000 Delivered-To: apmail-camel-commits-archive@camel.apache.org Received: (qmail 96509 invoked by uid 500); 13 Jun 2015 10:33:14 -0000 Mailing-List: contact commits-help@camel.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@camel.apache.org Delivered-To: mailing list commits@camel.apache.org Received: (qmail 96500 invoked by uid 99); 13 Jun 2015 10:33:14 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 13 Jun 2015 10:33:14 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5F81BDFF16; Sat, 13 Jun 2015 10:33:14 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: forsthofer@apache.org To: commits@camel.apache.org Message-Id: <3715361eb5644c78b7ebd42214f05a37@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: camel git commit: CAMEL-8810 Camel CXF may propagate wrong Content-Length headers Thanks to Stephan Siano Date: Sat, 13 Jun 2015 10:33:14 +0000 (UTC) Repository: camel Updated Branches: refs/heads/camel-2.15.x 57da1472e -> e82251b7d CAMEL-8810 Camel CXF may propagate wrong Content-Length headers Thanks to Stephan Siano Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/e82251b7 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/e82251b7 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/e82251b7 Branch: refs/heads/camel-2.15.x Commit: e82251b7da283861e4690f4e5dccfeeefdabe2b8 Parents: 57da147 Author: Franz Forsthofer Authored: Sat Jun 13 12:29:19 2015 +0200 Committer: Franz Forsthofer Committed: Sat Jun 13 12:29:19 2015 +0200 ---------------------------------------------------------------------- .../camel/component/cxf/DefaultCxfBinding.java | 6 +- .../cxf/CxfPayloadRouterContentLengthTest.java | 179 +++++++++++++++++++ .../cxf/CxfPayloadRouterContentLengthBeans.xml | 53 ++++++ 3 files changed, 237 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/e82251b7/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java index 7616568..71ed7d5 100644 --- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java +++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/DefaultCxfBinding.java @@ -690,7 +690,11 @@ public class DefaultCxfBinding implements CxfBinding, HeaderFilterStrategyAware if (transportHeaders.size() > 0) { cxfContext.put(Message.PROTOCOL_HEADERS, transportHeaders); - } + } else { + // no propagated transport headers does really mean no headers, not the ones + // from the previous request or response propagated with the invocation context + cxfContext.remove(Message.PROTOCOL_HEADERS); + } } protected static Object getContentFromCxf(Message message, DataFormat dataFormat) { http://git-wip-us.apache.org/repos/asf/camel/blob/e82251b7/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthTest.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthTest.java b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthTest.java new file mode 100644 index 0000000..fc55c95 --- /dev/null +++ b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthTest.java @@ -0,0 +1,179 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.camel.component.cxf; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.spring.SpringCamelContext; +import org.apache.camel.test.AvailablePortFinder; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.camel.util.IOHelper; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.support.AbstractXmlApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class CxfPayloadRouterContentLengthTest extends CamelTestSupport { + + /* + * The response message is generated directly. The issue here is that the + * xsi and xs namespaces are defined on the SOAP envelope but are used + * within the payload. This can cause issues with some type conversions in + * PAYLOAD mode, as the Camel-CXF endpoint will return some kind of window + * within the StAX parsing (and the namespace definitions are outside). + * + * If some CXF implementation bean is used as the service the namespaces + * will be defined within the payload (and everything works fine). + */ + private static final String RESPONSE_STRING = "This is the response string"; + private static final String RESPONSE_MESSAGE = "" + + "" + + RESPONSE_STRING + + "" + ""; + private static final String REQUEST_MESSAGE = "" + + "foo" + + ""; + + // The Camel-Test with CXF will re-use jetty instances, so the ports1 to 6 are already blocked + private static final int JETTY_PORT = AvailablePortFinder.getNextAvailable(); + private Server server; + private AbstractXmlApplicationContext applicationContext; + + static { + System.setProperty("CXFTestSupport.jettyPort", Integer.toString(JETTY_PORT)); + } + + @Override + protected CamelContext createCamelContext() throws Exception { + return SpringCamelContext.springCamelContext(applicationContext); + } + + @Before + public void setUp() throws Exception { + /* + * We start a Jetty for the service in order to have better control over + * the response The response must contain only a Content-Type and a + * Content-Length but no other header + */ + log.info("Starting jetty server at port {}", JETTY_PORT); + server = new Server(JETTY_PORT); + server.setHandler(new AbstractHandler() { + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + response.setContentType("text/xml"); + // the Content-Length is correct for this response message + response.setContentLength(RESPONSE_MESSAGE.length()); + response.setStatus(HttpServletResponse.SC_OK); + baseRequest.setHandled(true); + PrintWriter pw = response.getWriter(); + pw.write(RESPONSE_MESSAGE); + pw.close(); + } + }); + // Do not send a Server header + server.setSendServerVersion(false); + server.start(); + // Load the CXF endpoints for the route + log.info("Start Routing Scenario at port {}", CXFTestSupport.getPort1()); + applicationContext = new ClassPathXmlApplicationContext( + "org/apache/camel/component/cxf/CxfPayloadRouterContentLengthBeans.xml"); + super.setUp(); + assertNotNull("Should have created a valid spring context", applicationContext); + } + + @After + public void tearDown() throws Exception { + // close the spring context + IOHelper.close(applicationContext); + // stop the jetty server + if (server != null && server.isRunning()) { + server.stop(); + server.join(); + } + super.tearDown(); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + from("cxf:bean:proxyEndpoint?dataFormat=PAYLOAD") // + .removeHeaders(".*") + // call an external Web service in payload mode + .to("cxf:bean:serviceEndpoint?dataFormat=PAYLOAD"); + } + }; + } + + @Test + public void testInvokeRouter() throws IOException { + CloseableHttpClient httpclient = HttpClients.createDefault(); + long contentLength = 0; + boolean isChunked = false; + String receivedContent = null; + try { + HttpPost httppost = new HttpPost("http://localhost:" + CXFTestSupport.getPort1() + "/TEST/PROXY"); + StringEntity reqEntity = new StringEntity(REQUEST_MESSAGE, ContentType.TEXT_XML); + reqEntity.setChunked(false); + httppost.setEntity(reqEntity); + CloseableHttpResponse response = httpclient.execute(httppost); + try { + HttpEntity respEntity = response.getEntity(); + contentLength = respEntity.getContentLength(); + isChunked = respEntity.isChunked(); + receivedContent = EntityUtils.toString(respEntity); + EntityUtils.consume(response.getEntity()); + } finally { + response.close(); + } + } finally { + httpclient.close(); + } + assertNotNull(receivedContent); + // chunked encoding is fine, we don't need to check the content length + if (!isChunked) { + assertEquals(receivedContent.length(), contentLength); + } + assertTrue("[" + receivedContent + "] does not contain [" + RESPONSE_STRING + "]", + receivedContent.contains(RESPONSE_STRING)); + // check whether the response was cut off by the client because the + // Content-Length was wrong + assertTrue("[" + receivedContent + "] does not contain the closing Envelope tag.", + receivedContent.matches(".*\\")); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/e82251b7/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthBeans.xml ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthBeans.xml b/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthBeans.xml new file mode 100644 index 0000000..ccc13cc --- /dev/null +++ b/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/CxfPayloadRouterContentLengthBeans.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file