diff --git a/function/header-enricher-function/pom.xml b/function/header-enricher-function/pom.xml
new file mode 100644
index 00000000..b7db24e5
--- /dev/null
+++ b/function/header-enricher-function/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+ header-enricher-function
+ 1.0.0-SNAPSHOT
+ header-enricher-function
+ Spring Native Function for applying message header enrichment
+
+
+ org.springframework.cloud.fn
+ spring-functions-parent
+ 1.0.0-SNAPSHOT
+ ../../spring-functions-parent
+
+
+
+
+ org.springframework.cloud.fn
+ payload-converter-function
+ ${project.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-integration
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+ org.springframework.integration
+ spring-integration-test-support
+ test
+
+
+
+
diff --git a/function/header-enricher-function/src/main/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionConfiguration.java b/function/header-enricher-function/src/main/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionConfiguration.java
new file mode 100644
index 00000000..afb025e3
--- /dev/null
+++ b/function/header-enricher-function/src/main/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionConfiguration.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020-2020 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.fn.header.enricher;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.function.Function;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+import org.springframework.integration.transformer.HeaderEnricher;
+import org.springframework.integration.transformer.support.ExpressionEvaluatingHeaderValueMessageProcessor;
+import org.springframework.messaging.Message;
+
+/**
+ * @author Gary Russell
+ * @author Christian Tzolov
+ * @author Soby Chacko
+ */
+@Configuration
+@EnableConfigurationProperties(HeaderEnricherFunctionProperties.class)
+public class HeaderEnricherFunctionConfiguration {
+
+ @Autowired
+ private HeaderEnricherFunctionProperties properties;
+
+ @Bean
+ public Function, Message>> headerEnricherFunction() {
+ return headerEnricher()::transform;
+ }
+
+ @Bean
+ public HeaderEnricher headerEnricher() {
+ Map> headersToAdd = new HashMap<>();
+ Properties props = this.properties.getHeaders();
+ Enumeration> enumeration = props.propertyNames();
+ while (enumeration.hasMoreElements()) {
+ String propertyName = (String) enumeration.nextElement();
+ headersToAdd.put(propertyName, processor(props.getProperty(propertyName)));
+ }
+ HeaderEnricher headerEnricher = new HeaderEnricher(headersToAdd);
+ headerEnricher.setDefaultOverwrite(this.properties.isOverwrite());
+ return headerEnricher;
+ }
+
+ @Bean
+ @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // Need a new processor for each header
+ public ExpressionEvaluatingHeaderValueMessageProcessor> processor(String expression) {
+ return new ExpressionEvaluatingHeaderValueMessageProcessor<>(expression, null);
+ }
+
+}
diff --git a/function/header-enricher-function/src/main/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionProperties.java b/function/header-enricher-function/src/main/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionProperties.java
new file mode 100644
index 00000000..2b24cf6a
--- /dev/null
+++ b/function/header-enricher-function/src/main/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionProperties.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020-2020 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.fn.header.enricher;
+
+
+import java.util.Properties;
+
+import javax.validation.constraints.NotNull;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+/**
+ * Configuration properties for the Header Enricher Processor application.
+ *
+ * @author Gary Russell
+ * @author Artem Bilan
+ * @author Soby Chacko
+ */
+@ConfigurationProperties("header.enricher")
+@Validated
+public class HeaderEnricherFunctionProperties {
+
+ /**
+ * \n separated properties representing headers in which values are SpEL expressions,
+ * e.g foo='bar' \n baz=payload.baz.
+ */
+ private Properties headers;
+
+ /**
+ * set to true to overwrite any existing message headers.
+ */
+ private boolean overwrite = false;
+
+ @NotNull
+ public Properties getHeaders() {
+ return this.headers;
+ }
+
+ public void setHeaders(Properties headers) {
+ this.headers = headers;
+ }
+
+ public boolean isOverwrite() {
+ return this.overwrite;
+ }
+
+ public void setOverwrite(boolean overwrite) {
+ this.overwrite = overwrite;
+ }
+
+}
diff --git a/function/header-enricher-function/src/test/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionApplicationTests.java b/function/header-enricher-function/src/test/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionApplicationTests.java
new file mode 100644
index 00000000..ab11df7e
--- /dev/null
+++ b/function/header-enricher-function/src/test/java/org/springframework/cloud/fn/header/enricher/HeaderEnricherFunctionApplicationTests.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2020-2020 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.fn.header.enricher;
+
+import java.util.function.Function;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.integration.test.matcher.HeaderMatcher;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.test.annotation.DirtiesContext;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+
+/**
+ *
+ * @author Gary Russell
+ * @author Soby Chacko
+ */
+@SpringBootTest(properties = {
+ "header.enricher.headers=foo='bar' \\n baz='fiz' \\n buz=payload \\n jaz=@value",
+ "header.enricher.overwrite = true" })
+@DirtiesContext
+public class HeaderEnricherFunctionApplicationTests {
+
+ @Autowired
+ Function, Message>> headerEnricherFunction;
+
+ @Test
+ public void testDefault() {
+ final Message> message = MessageBuilder.withPayload("hello")
+ .setHeader("baz", "qux").build();
+ final Message> enriched = headerEnricherFunction.apply(message);
+
+ assertThat(enriched, HeaderMatcher.hasHeader("foo", equalTo("bar")));
+ assertThat(enriched, HeaderMatcher.hasHeader("baz", equalTo("fiz")));
+ assertThat(enriched, HeaderMatcher.hasHeader("buz", equalTo("hello")));
+ assertThat(enriched, HeaderMatcher.hasHeader("jaz", equalTo("beanValue")));
+ }
+
+ @SpringBootApplication
+ static class HeaderEnricherTestApplication {
+
+ @Bean
+ public String value() {
+ return "beanValue";
+ }
+
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 8810c22a..5007c6d4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,7 @@
consumer/redis-consumer
function/filter-function
+ function/header-enricher-function
function/spel-function
function/payload-converter-function
function/splitter-function