Skip to content

Commit

Permalink
CAMEL-9309: Make it easier to turn on|off java transport over http
Browse files Browse the repository at this point in the history
Conflicts:
	components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
	components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpBinding.java
	components/camel-http-common/src/main/java/org/apache/camel/http/common/HttpCommonEndpoint.java
	components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/CamelContinuationServlet.java
	components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/DefaultJettyHttpBinding.java
	components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpBinding.java
	components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
	components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpProducer.java
	components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/JettyHttpEndpoint9.java
	components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/javabody/HttpJavaBodyTest.java
	components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/jettyproducer/JettyHttpProducerJavaBodyTest.java
  • Loading branch information
davsclaus committed Nov 12, 2015
1 parent 190d7c8 commit 13e43c1
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ public boolean isTransferException() {
* in the response as a application/x-java-serialized-object content type (for example using Jetty or Servlet Camel components).
* On the producer side the exception will be deserialized and thrown as is, instead of the AhcOperationFailedException.
* The caused exception is required to be serialized.
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*/
public void setTransferException(boolean transferException) {
this.transferException = transferException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,4 +499,12 @@ public void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy) {
this.headerFilterStrategy = headerFilterStrategy;
}

public boolean isAllowJavaSerializedObject() {
return allowJavaSerializedObject;
}

public void setAllowJavaSerializedObject(boolean allowJavaSerializedObject) {
this.allowJavaSerializedObject = allowJavaSerializedObject;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,23 @@ public interface HttpBinding {
*/
void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy);

/**
* Whether to allow java serialization when a request uses context-type=application/x-java-serialized-object
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*/
boolean isAllowJavaSerializedObject();

/**
* Whether to allow java serialization when a request uses context-type=application/x-java-serialized-object
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*
* @param allowJavaSerializedObject <tt>true</tt> to allow serializing java objects
*/
void setAllowJavaSerializedObject(boolean allowJavaSerializedObject);


}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.Iterator;
import java.util.List;

import org.apache.camel.Component;
import org.apache.camel.Consumer;
import org.apache.camel.PollingConsumer;
import org.apache.camel.Processor;
Expand Down Expand Up @@ -238,6 +237,9 @@ public HttpBinding getBinding() {
binding = new DefaultHttpBinding(this);
// create a new binding and use the options from this endpoint
binding.setEagerCheckContentAvailable(isEagerCheckContentAvailable());
if (getComponent() != null) {
binding.setAllowJavaSerializedObject(getComponent().isAllowJavaSerializedObject());
}
}
return binding;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.component.http.CamelServlet;
import org.apache.camel.component.http.HttpConstants;
import org.apache.camel.component.http.HttpConsumer;
import org.apache.camel.component.http.HttpMessage;
import org.apache.camel.component.http.helper.HttpHelper;
Expand Down Expand Up @@ -85,6 +86,14 @@ protected void service(final HttpServletRequest request, final HttpServletRespon
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}

// we do not support java serialized objects unless explicit enabled
String contentType = request.getContentType();
if (HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT.equals(contentType) && !consumer.getEndpoint().getComponent().isAllowJavaSerializedObject()) {
System.out.println("415 miser !!!");
response.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
return;
}

final Exchange result = (Exchange) request.getAttribute(EXCHANGE_ATTRIBUTE_NAME);
if (result == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class DefaultJettyHttpBinding implements JettyHttpBinding {
private HeaderFilterStrategy httpProtocolHeaderFilterStrategy = new HttpProtocolHeaderFilterStrategy();
private boolean throwExceptionOnFailure;
private boolean transferException;
private boolean allowJavaSerializedObject;

public DefaultJettyHttpBinding() {

}
Expand Down Expand Up @@ -99,6 +101,14 @@ public void setTransferException(boolean transferException) {
this.transferException = transferException;
}

public boolean isAllowJavaSerializedObject() {
return allowJavaSerializedObject;
}

public void setAllowJavaSerializedObject(boolean allowJavaSerializedObject) {
this.allowJavaSerializedObject = allowJavaSerializedObject;
}

protected void populateResponse(Exchange exchange, JettyContentExchange httpExchange,
Message in, HeaderFilterStrategy strategy, int responseCode) throws IOException {
Message answer = exchange.getOut();
Expand Down Expand Up @@ -173,11 +183,17 @@ protected Object extractResponseBody(Exchange exchange, JettyContentExchange htt

// if content type is serialized java object, then de-serialize it to a Java object
if (contentType != null && HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT.equals(contentType)) {
try {
InputStream is = exchange.getContext().getTypeConverter().mandatoryConvertTo(InputStream.class, httpExchange.getResponseContentBytes());
return HttpHelper.deserializeJavaObjectFromStream(is);
} catch (Exception e) {
throw new RuntimeCamelException("Cannot deserialize body to Java object", e);
// only deserialize java if allowed
if (isAllowJavaSerializedObject() || isTransferException()) {
try {
InputStream is = exchange.getContext().getTypeConverter().mandatoryConvertTo(InputStream.class, httpExchange.getResponseContentBytes());
return HttpHelper.deserializeJavaObjectFromStream(is);
} catch (Exception e) {
throw new RuntimeCamelException("Cannot deserialize body to Java object", e);
}
} else {
// empty body
return null;
}
} else {
// just grab the raw content body
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public interface JettyHttpBinding {
/**
* Whether to transfer exception back as a serialized java object
* if processing failed due to an exception
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*
* @param transferException <tt>true</tt> to transfer exception
*/
Expand All @@ -78,9 +81,30 @@ public interface JettyHttpBinding {
/**
* Whether to transfer exception back as a serialized java object
* if processing failed due to an exception
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*
* @return <tt>true</tt> to transfer exception
*/
boolean isTransferException();

/**
* Whether to allow java serialization when a request uses context-type=application/x-java-serialized-object
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*
* @param allowJavaSerializedObject <tt>true</tt> to allow serializing java objects
*/
void setAllowJavaSerializedObject(boolean allowJavaSerializedObject);

/**
* Whether to allow java serialization when a request uses context-type=application/x-java-serialized-object
* <p/>
* This is by default turned off. If you enable this then be aware that Java will deserialize the incoming
* data from the request to Java and that can be a potential security risk.
*/
boolean isAllowJavaSerializedObject();

}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ public synchronized JettyHttpBinding getJettyBinding(HttpClient httpClient) {
jettyBinding.setHeaderFilterStrategy(getHeaderFilterStrategy());
jettyBinding.setThrowExceptionOnFailure(isThrowExceptionOnFailure());
jettyBinding.setTransferException(isTransferException());
if (getComponent() != null) {
jettyBinding.setAllowJavaSerializedObject(getComponent().isAllowJavaSerializedObject());
}
}
return jettyBinding;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.apache.camel.component.http.HttpConstants;
import org.apache.camel.component.http.HttpMethods;
import org.apache.camel.component.http.helper.HttpHelper;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.impl.DefaultAsyncProducer;
import org.apache.camel.spi.HeaderFilterStrategy;
import org.apache.camel.util.ExchangeHelper;
Expand Down Expand Up @@ -139,17 +140,20 @@ private void processInternal(Exchange exchange, AsyncCallback callback) throws E
if (contentType != null) {
httpExchange.setRequestContentType(contentType);
}

if (contentType != null && HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT.equals(contentType)) {
// serialized java object
Serializable obj = exchange.getIn().getMandatoryBody(Serializable.class);
// write object to output stream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
HttpHelper.writeObjectToStream(bos, obj);
httpExchange.setRequestContent(bos.toByteArray());
} finally {
IOHelper.close(bos, "body", LOG);
if (getEndpoint().getComponent().isAllowJavaSerializedObject() || getEndpoint().isTransferException()) {
// serialized java object
Serializable obj = exchange.getIn().getMandatoryBody(Serializable.class);
// write object to output stream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
HttpHelper.writeObjectToStream(bos, obj);
httpExchange.setRequestContent(bos.toByteArray());
} finally {
IOHelper.close(bos, "body", LOG);
}
} else {
throw new RuntimeCamelException("Content-type " + HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT + " is not allowed");
}
} else {
Object body = exchange.getIn().getBody();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public JettyHttpEndpoint9(JettyHttpComponent component, String uri, URI httpURL)
public HttpBinding getBinding() {
if (this.binding == null) {
this.binding = new AttachmentHttpBinding(this);
if (getComponent() != null) {
this.binding.setAllowJavaSerializedObject(getComponent().isAllowJavaSerializedObject());
}
}
return this.binding;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
*/
package org.apache.camel.component.jetty.javabody;

import org.apache.camel.CamelExecutionException;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.http.HttpConstants;
import org.apache.camel.component.jetty.BaseJettyTest;
import org.apache.camel.component.http.HttpComponent;
import org.apache.camel.component.jetty.BaseJettyTest;
import org.apache.camel.component.jetty.JettyHttpComponent;
import org.junit.Ignore;
import org.junit.Test;

/**
Expand All @@ -34,7 +39,14 @@ public boolean isUseRouteBuilder() {
}

@Test
@Ignore
public void testHttpSendJavaBodyAndReceiveString() throws Exception {
JettyHttpComponent jetty = context.getComponent("jetty", JettyHttpComponent.class);
jetty.setAllowJavaSerializedObject(true);

HttpComponent http = context.getComponent("http", HttpComponent.class);
http.setAllowJavaSerializedObject(true);

context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
Expand Down Expand Up @@ -65,7 +77,14 @@ public void process(Exchange exchange) throws Exception {
}

@Test
@Ignore
public void testHttpSendJavaBodyAndReceiveJavaBody() throws Exception {
JettyHttpComponent jetty = context.getComponent("jetty", JettyHttpComponent.class);
jetty.setAllowJavaSerializedObject(true);

HttpComponent http = context.getComponent("http", HttpComponent.class);
http.setAllowJavaSerializedObject(true);

context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
Expand Down Expand Up @@ -97,7 +116,14 @@ public void process(Exchange exchange) throws Exception {
}

@Test
@Ignore
public void testHttpSendStringAndReceiveJavaBody() throws Exception {
JettyHttpComponent jetty = context.getComponent("jetty", JettyHttpComponent.class);
jetty.setAllowJavaSerializedObject(true);

HttpComponent http = context.getComponent("http", HttpComponent.class);
http.setAllowJavaSerializedObject(true);

context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
Expand All @@ -123,4 +149,81 @@ public void process(Exchange exchange) throws Exception {
assertEquals("Camel rocks", reply.getName());
}

@Test
public void testNotAllowedReceive() throws Exception {
JettyHttpComponent jetty = context.getComponent("jetty", JettyHttpComponent.class);
jetty.setAllowJavaSerializedObject(false);

HttpComponent http = context.getComponent("http", HttpComponent.class);
http.setAllowJavaSerializedObject(true);

context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
onException(Exception.class).to("mock:error");

from("jetty:http://localhost:{{port}}/myapp/myservice")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String body = exchange.getIn().getBody(String.class);
assertNotNull(body);
assertEquals("Hello World", body);

MyCoolBean reply = new MyCoolBean(456, "Camel rocks");
exchange.getOut().setBody(reply);
exchange.getOut().setHeader(Exchange.CONTENT_TYPE, HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT);
}
});
}
});
context.start();

try {
template.requestBody("http://localhost:{{port}}/myapp/myservice", "Hello World", MyCoolBean.class);
fail("Should fail");
} catch (Exception e) {
// expected
}
}

@Test
@Ignore
public void testNotAllowed() throws Exception {
JettyHttpComponent jetty = context.getComponent("jetty", JettyHttpComponent.class);
jetty.setAllowJavaSerializedObject(false);

HttpComponent http = context.getComponent("http", HttpComponent.class);
http.setAllowJavaSerializedObject(true);

context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("jetty:http://localhost:{{port}}/myapp/myservice")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String body = exchange.getIn().getBody(String.class);
assertNotNull(body);
assertEquals("Hello World", body);

MyCoolBean reply = new MyCoolBean(456, "Camel rocks");
exchange.getOut().setBody(reply);
exchange.getOut().setHeader(Exchange.CONTENT_TYPE, HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT);
}
});
}
});
context.start();

MyCoolBean cool = new MyCoolBean(123, "Camel");

try {
template.requestBodyAndHeader("http://localhost:{{port}}/myapp/myservice", cool,
Exchange.CONTENT_TYPE, HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT, MyCoolBean.class);
fail("Should fail");
} catch (CamelExecutionException e) {
HttpOperationFailedException cause = assertIsInstanceOf(HttpOperationFailedException.class, e.getCause());
assertEquals(415, cause.getStatusCode());
}
}

}
Loading

0 comments on commit 13e43c1

Please sign in to comment.