INT-4443: Use SimpleEC for uriVariablesExpression

JIRA: https://jira.spring.io/browse/INT-4443

**cherry-pick to 5.0.x, 4.3.x**

Polishing; use data binding accessor in test evaluation contexts.

Add `.withInstanceMethods()`

See https://jira.spring.io/browse/SPR-16588?focusedCommentId=158041&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-158041

* Polishing according PR comments

# Conflicts:
#	build.gradle
#	src/reference/asciidoc/changes-4.3-5.0.adoc

# Conflicts:
#	build.gradle
#	spring-integration-core/src/main/java/org/springframework/integration/expression/ExpressionUtils.java
#	spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java
#	spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java
#	spring-integration-http/src/main/java/org/springframework/integration/http/outbound/AbstractHttpRequestExecutingMessageHandler.java
#	spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-4.3.xsd
#	spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java
#	spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java
#	src/reference/asciidoc/changes-4.2-4.3.adoc
#	src/reference/asciidoc/http.adoc
This commit is contained in:
Gary Russell
2018-03-23 16:03:22 -04:00
committed by Artem Bilan
parent ed79a9521c
commit 705d33a30c
16 changed files with 514 additions and 157 deletions

View File

@@ -523,6 +523,7 @@ Changes in Spring 3.1 can cause some issues with escaped characters, such as '?'
For this reason, it is recommended that if you wish to generate the URL entirely at runtime, you use the 'url-expression' attribute.
=====
[[mapping-uri-variables]]
==== Mapping URI Variables
If your URL contains URI variables, you can map them using the `uri-variable` sub-element.
@@ -581,6 +582,53 @@ NOTE: The `uri-variables-expression` must evaluate to a `Map`.
The values of the Map must be instances of `String` or `Expression`.
This Map is provided to an `ExpressionEvalMap` for further resolution of URI variable placeholders using those expressions in the context of the outbound `Message`.
IMPORTANT
====
The `uriVariablesExpression` property provides a very powerful mechanism for evaluating URI variables.
It is anticipated that simple expressions like the example above will be used.
However, you could also configure something like this `"@uriVariablesBean.populate(#root)"` with an expression in the returned map being `variables.put("foo", EXPRESSION_PARSER.parseExpression(message.getHeaders().get("bar", String.class)));`, where the expression is dynamically provided in the message header `bar`.
Since the header may come from an untrusted source, the HTTP outbound endpoints use a `SimpleEvaluationContext` when evaluating these expressions; allowing only a subset of SpEL features to be used.
If you trust your message sources and wish to use the restricted SpEL constructs, set the `trustedSpel` property of the outbound endpoint to `true`.
====
Scenarios when we need to supply a dynamic set of URI variables on per message basis can be achieved with the custom `url-expression` and some utilities for building and encoding URL parameters:
[source,xml]
----
url-expression="T(org.springframework.web.util.UriComponentsBuilder)
.fromHttpUrl('http://HOST:PORT/PATH')
.queryParams(payload)
.build()
.toUri()"
----
where `queryParams()` expects a `MultiValueMap<String, String>` as an argument, so a real set of URL query parameters can be build in advance, before performing request.
The whole `queryString` can also be presented as an uri variable:
[source,xml]
----
<int-http:outbound-gateway id="proxyGateway" request-channel="testChannel"
url="http://testServer/test?{queryString}">
<int-http:uri-variable name="queryString" expression="'a=A&amp;b=B'"/>
</int-http:outbound-gateway>
----
In this case the URL encoding must be provided manually.
For example the `org.apache.http.client.utils.URLEncodedUtils#format()` can be used for this purpose.
A mentioned, manually built, `MultiValueMap<String, String>` can be converted to the the `List<NameValuePair>` `format()` method argument using this Java Streams snippet:
[source,java]
----
List<NameValuePair> nameValuePairs =
params.entrySet()
.stream()
.flatMap(e -> e
.getValue()
.stream()
.map(v -> new BasicNameValuePair(e.getKey(), v)))
.collect(Collectors.toList());
----
==== Controlling URI Encoding
By default, the URL string is encoded (see http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html[UriComponentsBuilder]) to the URI object before sending the request.