[[http-namespace]]
= HTTP Namespace Support

Spring Integration provides an `http` namespace and the corresponding schema definition.
To include it in your configuration, provide the following namespace declaration in your application context configuration file:

[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xmlns:int-http="http://www.springframework.org/schema/integration/http"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration
    https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/http
    https://www.springframework.org/schema/integration/http/spring-integration-http.xsd">
    ...
</beans>
----

[[inbound]]
== Inbound

The XML namespace provides two components for handling HTTP inbound requests: `inbound-channel-adapter` and `inbound-gateway`.
In order to process requests without returning a dedicated response, use the `inbound-channel-adapter`.
The following example shows how to configure one:

[source,xml]
----
<int-http:inbound-channel-adapter id="httpChannelAdapter" channel="requests"
    supported-methods="PUT, DELETE"/>
----

To process requests that do expect a response, use an `inbound-gateway`.
The following example shows how to configure one:

[source,xml]
----
<int-http:inbound-gateway id="inboundGateway"
    request-channel="requests"
    reply-channel="responses"/>
----

[[http-request-mapping]]
== Request Mapping Support

NOTE: Spring Integration 3.0 improved the REST support by introducing the https://docs.spring.io/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html[`IntegrationRequestMappingHandlerMapping`].
The implementation relies on the enhanced REST support provided by Spring Framework 3.1 or higher.

The parsing of the HTTP inbound gateway or the HTTP inbound channel adapter registers an `integrationRequestMappingHandlerMapping` bean of type https://docs.spring.io/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html[`IntegrationRequestMappingHandlerMapping`], in case one is not yet registered.
This particular implementation of the https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html[`HandlerMapping`] delegates its logic to https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.html[`RequestMappingInfoHandlerMapping`].
The implementation provides functionality similar to the https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html[`org.springframework.web.bind.annotation.RequestMapping`] annotation in Spring MVC.

NOTE: For more information, see https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping[Mapping Requests With `@RequestMapping`].

For this purpose, Spring Integration 3.0 introduces the `<request-mapping>` element.
You can add this optional element to `<http:inbound-channel-adapter>` and `<http:inbound-gateway>`.
It works in conjunction with the `path` and `supported-methods` attributes.
The following example shows how to configure it on an inbound gateway:

[source,xml]
----
<inbound-gateway id="inboundController"
    request-channel="requests"
    reply-channel="responses"
    path="/foo/{fooId}"
    supported-methods="GET"
    view-name="foo"
    error-code="oops">
   <request-mapping headers="User-Agent"
     params="myParam=myValue"
     consumes="application/json"
     produces="!text/plain"/>
</inbound-gateway>
----

Based on the preceding configuration, the namespace parser creates an instance of the `IntegrationRequestMappingHandlerMapping` (if none exists) and an `HttpRequestHandlingController` bean and associates with it an instance of https://docs.spring.io/spring-integration/api/org/springframework/integration/http/inbound/RequestMapping.html[`RequestMapping`].
This `RequestMapping` instance is, in turn, converted to the Spring MVC https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/RequestMappingInfo.html[`RequestMappingInfo`].

The `<request-mapping>` element provides the following attributes:

* `headers`
* `params`
* `consumes`
* `produces`

With the `path` and `supported-methods` attributes of the `<http:inbound-channel-adapter>` or the `<http:inbound-gateway>`, `<request-mapping>` attributes translate directly into the respective options provided by the `org.springframework.web.bind.annotation.RequestMapping` annotation in Spring MVC.

The `<request-mapping>` element lets you configure several Spring Integration HTTP inbound endpoints to the same `path` (or even the same `supported-methods`) and lets you provide different downstream message flows based on incoming HTTP requests.

Alternatively, you can also declare only one HTTP inbound endpoint and apply routing and filtering logic within the Spring Integration flow to achieve the same result.
This lets you get the `Message` into the flow as early as possibly.
The following example shows how to do so:

[source,xml]
----
<int-http:inbound-gateway request-channel="httpMethodRouter"
    supported-methods="GET,DELETE"
    path="/process/{entId}"
    payload-expression="#pathVariables.entId"/>

<int:router input-channel="httpMethodRouter" expression="headers.http_requestMethod">
    <int:mapping value="GET" channel="in1"/>
    <int:mapping value="DELETE" channel="in2"/>
</int:router>

<int:service-activator input-channel="in1" ref="service" method="getEntity"/>

<int:service-activator input-channel="in2" ref="service" method="delete"/>
----

For more information regarding handler mappings, see https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html[the Spring Framework Web Servlet documentation] or https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html[the Spring Framework Web Reactive documentation].

IMPORTANT: The `IntegrationRequestMappingHandlerMapping` extends the Spring MVC `RequestMappingHandlerMapping` class, inheriting most of its logic, especially `handleNoMatch(Set, String, HttpServletRequest)`, which throws a specific `4xx` error for the HTTP response, when mapping doesn't match for some reason, preventing calls to any remaining mapping handlers in the application context.
For this reason, configuring the same path for both Spring Integration and Spring MVC request mappings (e.g. `POST` in one and `GET` in the other) is not supported; the MVC mapping will not be found..

[[http-cors]]
== Cross-origin Resource Sharing (CORS) Support

Starting with version 4.2, you can configure the `<http:inbound-channel-adapter>` and `<http:inbound-gateway>` with a `<cross-origin>` element.
It represents the same options as Spring MVC's `@CrossOrigin` for `@Controller` annotations and allows the configuration of cross-origin resource sharing (CORS) for Spring Integration HTTP endpoints:

* `origin`: List of allowed origins.
The `pass:[*]` means that all origins are allowed.
These values are placed in the `Access-Control-Allow-Origin` header of both the pre-flight and actual responses.
The default value is `pass:[*]`.
* `allowed-headers`: Indicates which request headers can be used during the actual request.
The `pass:[*]` means that all headers requested by the client are allowed.
This property controls the value of the pre-flight response's `Access-Control-Allow-Headers` header.
The default value is `pass:[*]`.
* `exposed-headers`: List of response headers that the user-agent lets the client access.
This property controls the value of the actual response's `Access-Control-Expose-Headers` header.
* `method`: The HTTP request methods to allow: `GET`, `POST`, `HEAD`, `OPTIONS`, `PUT`, `PATCH`, `DELETE`, `TRACE`.
Methods specified here overrides those in `supported-methods`.
* `allow-credentials`: Set to `true` if the browser should include any cookies associated to the domain of the request or `false` if it should not.
An empty string ("") means undefined.
If `true`, the pre-flight response includes the `Access-Control-Allow-Credentials=true` header.
The default value is `true`.
* `max-age`: Controls the cache duration for pre-flight responses.
Setting this to a reasonable value can reduce the number of pre-flight request-response interactions required by the browser.
This property controls the value of the `Access-Control-Max-Age` header in the pre-flight response.
A value of `-1` means undefined.
The default value is 1800 seconds (30 minutes).

The CORS Java Configuration is represented by the `org.springframework.integration.http.inbound.CrossOrigin` class, instances of which can be injected into the `HttpRequestHandlingEndpointSupport` beans.

[[http-response-statuscode]]
== Response Status Code

Starting with version 4.1, you can configure the `<http:inbound-channel-adapter>` with a `status-code-expression` to override the default `200 OK` status.
The expression must return an object that can be converted to an `org.springframework.http.HttpStatus` enum value.
The `evaluationContext` has a `BeanResolver` and, starting with version 5.1, is supplied with the `RequestEntity<?>` as root object.
An example might be to resolve, at runtime, some scoped bean that returns a status code value.
However, most likely, it is set to a fixed value such as `status-code=expression="204"` (No Content), or `status-code-expression="T(org.springframework.http.HttpStatus).NO_CONTENT"`.
By default, `status-code-expression` is null, meaning that the normal '200 OK' response status is returned.
Using the `RequestEntity<?>` as root object, the status code can be conditional e.g. on the request method, some header, URI content or even request body.
The following example shows how to set the status code to `ACCEPTED`:

[source,xml]
----
<http:inbound-channel-adapter id="inboundController"
       channel="requests" view-name="foo" error-code="oops"
       status-code-expression="T(org.springframework.http.HttpStatus).ACCEPTED">
   <request-mapping headers="BAR"/>
</http:inbound-channel-adapter>
----

The `<http:inbound-gateway>` resolves the 'status code' from the `http_statusCode` header of the reply `Message`.
Starting with version 4.2, the default response status code when no reply is received within the `reply-timeout` is `500 Internal Server Error`.
There are two ways to modify this behavior:

* Add a `reply-timeout-status-code-expression`.
This has the same semantics as the `status-code-expression` on the inbound adapter.
* Add an `error-channel` and return an appropriate message with an HTTP status code header, as the following example shows:
+
[source, xml]
----
<int:chain input-channel="errors">
    <int:header-enricher>
        <int:header name="http_statusCode" value="504" />
    </int:header-enricher>
    <int:transformer expression="payload.failedMessage" />
</int:chain>
----

The payload of the `ErrorMessage` is a `MessageTimeoutException`.
It must be transformed to something that can be converted by the gateway, such as a `String`.
A good candidate is the exception's message property, which is the value used when you use the `expression` technique.

If the error flow times out after a main flow timeout, `500 Internal Server Error` is returned, or, if the `reply-timeout-status-code-expression` is present, it is evaluated.

NOTE: Previously, the default status code for a timeout was `200 OK`.
To restore that behavior, set `reply-timeout-status-code-expression="200"`.

Also starting with version 5.4, an error that is encountered while preparing the request message is sent to the error channel (if provided).
A decision about throwing an appropriate exception should be done in the error flow by examining the exception.
Previously, any exceptions were simply thrown, causing an HTTP 500 server error response status, but in some cases the problem can be caused by incorrect request params, so a `ResponseStatusException` with a 4xx client error status should be thrown instead.
See `ResponseStatusException` for more information.
The `ErrorMessage` sent to this error channel contains the original exception as the payload for analysis.
[[uri-template-variables-and-expressions]]
== URI Template Variables and Expressions

By using the `path` attribute in conjunction with the `payload-expression` attribute and the `header` element, you have a high degree of flexibility for mapping inbound request data.

In the following example configuration, an inbound channel adapter is configured to accept requests using the following URI:

[source]
----
/first-name/{firstName}/last-name/{lastName}
----

When you use the `payload-expression` attribute, the `+{firstName}+` URI template variable maps to be the `Message` payload, while the `+{lastName}+` URI template variable maps to the `lname` message header, as defined in the following example:

[source,xml]
----
<int-http:inbound-channel-adapter id="inboundAdapterWithExpressions"
    path="/first-name/{firstName}/last-name/{lastName}"
    channel="requests"
    payload-expression="#pathVariables.firstName">
    <int-http:header name="lname" expression="#pathVariables.lastName"/>
</int-http:inbound-channel-adapter>
----

For more information about URI template variables, see https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping-uri-templates[uri template patterns] in the Spring Reference Manual.

Since Spring Integration 3.0, in addition to the existing `#pathVariables` and `#requestParams` variables being available in payload and header expressions, we added other useful expression variables:

* `#requestParams`: The `MultiValueMap` from the `ServletRequest` `parameterMap`.
* `#pathVariables`: The `Map` from URI Template placeholders and their values.
* `#matrixVariables`: The `Map` of `MultiValueMap` according to the https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-matrix-variables[Spring MVC Specification].
Note that `#matrixVariables` requires Spring MVC 3.2 or higher.
* `#requestAttributes`: The `org.springframework.web.context.request.RequestAttributes` associated with the current request.
* `#requestHeaders`: The `org.springframework.http.HttpHeaders` object from the current request.
* `#cookies`: The `MultiValueMap<String, Cookie>` of `jakarta.servlet.http.Cookie` instances from the current request.

Note that all these values (and others) can be accessed within expressions in the downstream message flow through the `ThreadLocal` `org.springframework.web.context.request.RequestAttributes` variable, if that message flow is single-threaded and lives within the request thread.
The following example configures a transformer that uses an `expression` attribute:

[source,xml]
----
<int-:transformer
    expression="T(org.springframework.web.context.request.RequestContextHolder).
                  requestAttributes.request.queryString"/>

----

[[outbound]]
== Outbound

To configure the outbound gateway, you can use the namespace support.
The following code snippet shows the available configuration options for an outbound HTTP gateway:

[source,xml]
----
<int-http:outbound-gateway id="example"
    request-channel="requests"
    url="http://localhost/test"
    http-method="POST"
    extract-request-payload="false"
    expected-response-type="java.lang.String"
    charset="UTF-8"
    request-factory="requestFactory"
    reply-timeout="1234"
    reply-channel="replies"/>
----

Most importantly, notice that the 'http-method' and 'expected-response-type' attributes are provided.
Those are two of the most commonly configured values.
The default `http-method` is `POST`, and the default response type is null.
With a null response type, the payload of the reply `Message` contains the `ResponseEntity`, as long as its HTTP status is a success (non-successful status codes throw exceptions).
If you expect a different type, such as a `String`, provide that as a fully-qualified class name (`java.lang.String` in the preceding example).
See also the note about empty response bodies in xref:http/outbound.adoc[HTTP Outbound Components].

IMPORTANT: Beginning with Spring Integration 2.1, the `request-timeout` attribute of the HTTP outbound gateway was renamed to `reply-timeout` to better reflect its intent.

[IMPORTANT]
=====
Since Spring Integration 2.2, Java serialization over HTTP is no longer enabled by default.
Previously, when setting the `expected-response-type` attribute to a `Serializable` object, the `Accept` header was not properly set up.
Since Spring Integration 2.2, the `SerializingHttpMessageConverter` has now been updated to set the `Accept` header to `application/x-java-serialized-object`.

However, because this could cause incompatibility with existing applications, it was decided to no longer automatically add this converter to the HTTP endpoints.
If you wish to use Java serialization, you can add the `SerializingHttpMessageConverter` to the appropriate endpoints, by using the `message-converters` attribute (when you use XML configuration) or by using the `setMessageConverters()` method (in Java configuration).
Alternatively, you may wish to consider using JSON instead, which is enabled by having https://github.com/FasterXML/jackson[the Jackson library] on the classpath.
=====

Beginning with Spring Integration 2.2, you can also determine the HTTP method dynamically by using SpEL and the `http-method-expression` attribute.
Note that this attribute is mutually exclusive with `http-method`.
You can also use the `expected-response-type-expression` attribute instead of `expected-response-type` and provide any valid SpEL expression that determines the type of the response.
The following configuration example uses `expected-response-type-expression`:

[source,xml]
----
<int-http:outbound-gateway id="example"
    request-channel="requests"
    url="http://localhost/test"
    http-method-expression="headers.httpMethod"
    extract-request-payload="false"
    expected-response-type-expression="payload"
    charset="UTF-8"
    request-factory="requestFactory"
    reply-timeout="1234"
    reply-channel="replies"/>
----

If your outbound adapter is to be used in a unidirectional way, you can use an `outbound-channel-adapter` instead.
This means that a successful response executes without sending any messages to a reply channel.
In the case of any non-successful response status code, it throws an exception.
The configuration looks very similar to the gateway, as the following example shows:

[source,xml]
----
<int-http:outbound-channel-adapter id="example"
    url="http://localhost/example"
    http-method="GET"
    channel="requests"
    charset="UTF-8"
    extract-payload="false"
    expected-response-type="java.lang.String"
    request-factory="someRequestFactory"
    order="3"
    auto-startup="false"/>
----

[NOTE]
=====
To specify the URL, you can use either the 'url' attribute or the 'url-expression' attribute.
The 'url' attribute takes a simple string (with placeholders for URI variables, as described below).
The 'url-expression' is a SpEL expression, with the `Message` as the root object, which enables dynamic urls.
The URL that results from the expression evaluation can still have placeholders for URI variables.

In previous releases, some users used the place holders to replace the entire URL with a URI variable.
Changes in Spring 3.1 can cause some issues with escaped characters, such as '?'.
For this reason, we recommend 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 by using the `uri-variable` element.
This element is available for the HTTP outbound gateway and the HTTP outbound channel adapter.
The following example maps the `zipCode` URI variable to an expression:

[source,xml]
----
<int-http:outbound-gateway id="trafficGateway"
    url="https://local.yahooapis.com/trafficData?appid=YdnDemo&amp;zip={zipCode}"
    request-channel="trafficChannel"
    http-method="GET"
    expected-response-type="java.lang.String">
    <int-http:uri-variable name="zipCode" expression="payload.getZip()"/>
</int-http:outbound-gateway>
----

The `uri-variable` element defines two attributes: `name` and `expression`.
The `name` attribute identifies the name of the URI variable, while the `expression` attribute is used to set the actual value.
By using the `expression` attribute, you can leverage the full power of the Spring Expression Language (SpEL), which gives you full dynamic access to the message payload and the message headers.
For example, in the preceding configuration, the `getZip()` method is invoked on the payload object of the `Message` and the result of that method is used as the value of the URI variable named 'zipCode'.

Since Spring Integration 3.0, HTTP outbound endpoints support the `uri-variables-expression` attribute to specify an `expression` that should be evaluated, resulting in a `Map` of all URI variable placeholders within the URL template.
It provides a mechanism whereby you can use different variable expressions, based on the outbound message.
This attribute is mutually exclusive with the `<uri-variable/>` element.
The following example shows how to use the `uri-variables-expression` attribute:

[source,xml]
----
<int-http:outbound-gateway
     url="https://foo.host/{foo}/bars/{bar}"
     request-channel="trafficChannel"
     http-method="GET"
     uri-variables-expression="@uriVariablesBean.populate(payload)"
     expected-response-type="java.lang.String"/>
----

`uriVariablesBean` might be defined as follows:

[source,java]
----
public class UriVariablesBean {
    private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();

    public Map<String, ?> populate(Object payload) {
        Map<String, Object> variables = new HashMap<String, Object>();
        if (payload instanceOf String.class)) {
            variables.put("foo", "foo"));
        }
        else {
            variables.put("foo", EXPRESSION_PARSER.parseExpression("headers.bar"));
        }
        return variables;
    }

}
----

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 by using those expressions in the context of the outbound `Message`.

IMPORTANT
The `uriVariablesExpression` property provides a very powerful mechanism for evaluating URI variables.
We anticipate that people mostly use simple expressions, such as the preceding example.
However, you can also configure something such as `"@uriVariablesBean.populate(#root)"` with an expression in the returned map being `variables.put("thing1", EXPRESSION_PARSER.parseExpression(message.getHeaders().get("thing2", String.class)));`, where the expression is dynamically provided in the message header named `thing2`.
Since the header may come from an untrusted source, the HTTP outbound endpoints use `SimpleEvaluationContext` when evaluating these expressions.
The `SimpleEvaluationContext` uses only a subset of SpEL features.
If you trust your message sources and wish to use the restricted SpEL constructs, set the `trustedSpel` property of the outbound endpoint to `true`.

You can achieve scenarios that need to supply a dynamic set of URI variables on a per-message basis by using a custom `url-expression` and some utilities for building and encoding URL parameters.
The following example shows how to do so:

[source,xml]
----
url-expression="T(org.springframework.web.util.UriComponentsBuilder)
                           .fromHttpUrl('https://HOST:PORT/PATH')
                           .queryParams(payload)
                           .build()
                           .toUri()"
----

The `queryParams()` method expects a `MultiValueMap<String, String>` as an argument, so you can build a real set of URL query parameters in advance, before performing the request.

The whole `queryString` can also be presented as a `uri-variable`, as the following example shows:

[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, you must manually provide the URL encoding.
For example, you can use the `org.apache.http.client.utils.URLEncodedUtils#format()` for this purpose.
As mentioned earlier, a manually built `MultiValueMap<String, String>` can be converted to the `List<NameValuePair>` `format()` method argument by using the following 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());
----

[[http-uri-encoding]]
== Controlling URI Encoding

By default, the URL string is encoded (see https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html[`UriComponentsBuilder`]) to the URI object before sending the request.
In some scenarios with a non-standard URI (such as the RabbitMQ REST API), it is undesirable to perform the encoding.
The `<http:outbound-gateway/>` and `<http:outbound-channel-adapter/>` provide an `encoding-mode` attribute.
To disable encoding the URL, set this attribute to `NONE` (by default, it is `TEMPLATE_AND_VALUES`).
If you wish to partially encode some part of the URL, use an `expression` within a `<uri-variable/>`, as the following example shows:

[source,xml]
----
<http:outbound-gateway url="https://somehost/%2f/fooApps?bar={param}" encoding-mode="NONE">
          <http:uri-variable name="param"
            expression="T(org.apache.commons.httpclient.util.URIUtil)
                                             .encodeWithinQuery('Hello World!')"/>
</http:outbound-gateway>
----

With Java DSL this option can be controlled by the `BaseHttpMessageHandlerSpec.encodingMode()` option.
The same configuration applies for similar outbound components in the xref:webflux.adoc[WebFlux module] and xref:ws.adoc[Web Services module].
For much sophisticated scenarios it is recommended to configure an `UriTemplateHandler` on the externally provided `RestTemplate`; or in case of WebFlux - `WebClient` with it `UriBuilderFactory`.

