INT-2035 Support Simple Cookie Handling
Initial commit - TODO: namspace. Saves off Set-Cookie header in http_transferredCookie MessageHeader. Transferred cookies are converted to Cookie: headers on subsequent outbound messages, thus handling 3 or more interactions. INT-2035 Namespace, Docs Change boolean name; add namspace and documentation. INT-2035 Docs Added docs for cookie handling. INT-2035 Polishing Simplify implementation to just transfer Set-Cookie to Cookie in the inbound side. INT-2035 XSD Docs Updated to reflect new implementation.
This commit is contained in:
committed by
Mark Fisher
parent
497d07bdad
commit
a61b3617f3
@@ -80,6 +80,7 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-timeout", "sendTimeout");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
|
||||
HttpAdapterParsingUtils.configureUriVariableExpressions(builder, element);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "transfer-cookies");
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
@@ -88,6 +89,8 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
|
||||
private volatile String charset = "UTF-8";
|
||||
|
||||
private volatile boolean transferCookies = false;
|
||||
|
||||
private volatile HeaderMapper<HttpHeaders> headerMapper = DefaultHttpHeaderMapper.outboundMapper();
|
||||
|
||||
private final Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
|
||||
@@ -95,7 +98,6 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
private final StandardEvaluationContext evaluationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a handler that will send requests to the provided URI.
|
||||
@@ -215,6 +217,16 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if you wish 'Set-Cookie' headers in responses to be
|
||||
* transferred as 'Cookie' headers in subsequent interactions for
|
||||
* a message.
|
||||
* @param transferCookies the transferCookies to set.
|
||||
*/
|
||||
public void setTransferCookies(boolean transferCookies) {
|
||||
this.transferCookies = transferCookies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInit() {
|
||||
super.onInit();
|
||||
@@ -245,7 +257,11 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
HttpEntity<?> httpRequest = this.generateHttpRequest(requestMessage);
|
||||
ResponseEntity<?> httpResponse = this.restTemplate.exchange(this.uri, this.httpMethod, httpRequest, this.expectedResponseType, uriVariables);
|
||||
if (this.expectReply) {
|
||||
Map<String, ?> headers = this.headerMapper.toHeaders(httpResponse.getHeaders());
|
||||
HttpHeaders httpHeaders = httpResponse.getHeaders();
|
||||
Map<String, Object> headers = this.headerMapper.toHeaders(httpHeaders);
|
||||
if (this.transferCookies) {
|
||||
this.doConvertSetCookie(headers);
|
||||
}
|
||||
if (httpResponse.hasBody()) {
|
||||
Object responseBody = httpResponse.getBody();
|
||||
MessageBuilder<?> replyBuilder = (responseBody instanceof Message<?>) ?
|
||||
@@ -269,6 +285,27 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Set-Cookie to Cookie
|
||||
*/
|
||||
private void doConvertSetCookie(Map<String, Object> headers) {
|
||||
String keyName = null;
|
||||
for (String key : headers.keySet()) {
|
||||
if (key.equalsIgnoreCase(DefaultHttpHeaderMapper.SET_COOKIE)) {
|
||||
keyName = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (keyName != null) {
|
||||
Object cookies = headers.remove(keyName);
|
||||
headers.put(DefaultHttpHeaderMapper.COOKIE, cookies);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Converted Set-Cookie header to Cookie for: "
|
||||
+ cookies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private HttpEntity<?> generateHttpRequest(Message<?> message) throws Exception {
|
||||
Assert.notNull(message, "message must not be null");
|
||||
return (this.extractPayload) ? this.createHttpEntityFromPayload(message)
|
||||
@@ -281,8 +318,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
// payload is already an HttpEntity, just return it as-is
|
||||
return (HttpEntity<?>) payload;
|
||||
}
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
this.headerMapper.fromHeaders(message.getHeaders(), httpHeaders);
|
||||
HttpHeaders httpHeaders = this.mapHeaders(message);
|
||||
if (!shouldIncludeRequestBody()) {
|
||||
return new HttpEntity<Object>(httpHeaders);
|
||||
}
|
||||
@@ -302,8 +338,7 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
}
|
||||
|
||||
private HttpEntity<?> createHttpEntityFromMessage(Message<?> message) {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
this.headerMapper.fromHeaders(message.getHeaders(), httpHeaders);
|
||||
HttpHeaders httpHeaders = mapHeaders(message);
|
||||
if (shouldIncludeRequestBody()) {
|
||||
httpHeaders.setContentType(new MediaType("application", "x-java-serialized-object"));
|
||||
return new HttpEntity<Object>(message, httpHeaders);
|
||||
@@ -311,6 +346,12 @@ public class HttpRequestExecutingMessageHandler extends AbstractReplyProducingMe
|
||||
return new HttpEntity<Object>(httpHeaders);
|
||||
}
|
||||
|
||||
protected HttpHeaders mapHeaders(Message<?> message) {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
this.headerMapper.fromHeaders(message.getHeaders(), httpHeaders);
|
||||
return httpHeaders;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private MediaType resolveContentType(Object content) {
|
||||
MediaType contentType = null;
|
||||
|
||||
@@ -100,7 +100,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper<HttpHeaders>, BeanF
|
||||
|
||||
private static final String CONTENT_TYPE = "Content-Type";
|
||||
|
||||
private static final String COOKIE = "Cookie";
|
||||
public static final String COOKIE = "Cookie";
|
||||
|
||||
private static final String DATE = "Date";
|
||||
|
||||
@@ -146,7 +146,7 @@ public class DefaultHttpHeaderMapper implements HeaderMapper<HttpHeaders>, BeanF
|
||||
|
||||
private static final String SERVER = "Server";
|
||||
|
||||
private static final String SET_COOKIE = "Set-Cookie";
|
||||
public static final String SET_COOKIE = "Set-Cookie";
|
||||
|
||||
private static final String TE = "TE";
|
||||
|
||||
|
||||
@@ -505,6 +505,15 @@ The String "HTTP_REQUEST_HEADERS" will match against any of the standard HTTP Re
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="auto-startup" type="xsd:string" />
|
||||
<xsd:attribute name="transfer-cookies" type="xsd:string" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
When set to "true", if a response contains a 'Set-Cookie' header, it will mapped to a 'Cookie' header. This enables simple
|
||||
cookie handling where subsequent HTTP interactions in the same message flow can use a cookie
|
||||
supplied by the server. Default "false".
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
Reference in New Issue
Block a user