aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-08-20 11:13:28 +0200
committerChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-08-20 11:13:28 +0200
commit2b8a7df25878f546ace25373f44baeb026cf6d2b (patch)
tree8b236fdc42bc66beb16cc59b86258a7794285420 /src
parent488ecf8632b7204b5da218643eb1631e2d3386ff (diff)
downloadmoa-zs-2b8a7df25878f546ace25373f44baeb026cf6d2b.tar.gz
moa-zs-2b8a7df25878f546ace25373f44baeb026cf6d2b.tar.bz2
moa-zs-2b8a7df25878f546ace25373f44baeb026cf6d2b.zip
Add Custom Http Headers to HTTP Clients
- Change app2mzs schema: Add Custom Headers to ClientType Element. - Set custom headers in ClientFactory. - Parse custom headers from spring environment. - Merge custom headers from two different profiles. - Add example to application.yaml. - Test conversion of custom headers from spring profile - Test merging and overriding custom headers.
Diffstat (limited to 'src')
-rw-r--r--src/main/java/at/gv/egiz/moazs/client/ClientFactory.java10
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java3
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java62
-rw-r--r--src/main/resources/application.yaml10
-rw-r--r--src/main/resources/mzs/app2mzs.xsd9
-rw-r--r--src/test/java/at/gv/egiz/moazs/ConfigUtilTest.java80
6 files changed, 169 insertions, 5 deletions
diff --git a/src/main/java/at/gv/egiz/moazs/client/ClientFactory.java b/src/main/java/at/gv/egiz/moazs/client/ClientFactory.java
index d0a445b..94eb712 100644
--- a/src/main/java/at/gv/egiz/moazs/client/ClientFactory.java
+++ b/src/main/java/at/gv/egiz/moazs/client/ClientFactory.java
@@ -1,5 +1,6 @@
package at.gv.egiz.moazs.client;
+import at.gv.egiz.moazs.preprocess.ConfigUtil;
import at.gv.egiz.moazs.util.FileUtils;
import at.gv.egiz.moazs.util.StoreSOAPBodyBinaryInRepositoryInterceptor;
import at.gv.zustellung.app2mzs.xsd.ClientType;
@@ -10,6 +11,7 @@ import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsClientFactoryBean;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
+import org.apache.cxf.message.Message;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.slf4j.Logger;
@@ -23,6 +25,7 @@ import javax.xml.ws.BindingProvider;
import javax.xml.ws.soap.SOAPBinding;
import static at.gv.zustellung.app2mzs.xsd.KeyStoreType.keyStoreTypeBuilder;
+import static java.util.stream.Collectors.toMap;
@Component
public class ClientFactory {
@@ -32,14 +35,16 @@ public class ClientFactory {
private final StoreSOAPBodyBinaryInRepositoryInterceptor storeResponseInterceptor;
private final SSLContextCreator sslContextCreator;
private final FileUtils fileUtils;
+ private final ConfigUtil configUtil;
@Autowired
public ClientFactory(StoreSOAPBodyBinaryInRepositoryInterceptor storeResponseInterceptor,
SSLContextCreator creator,
- FileUtils fileUtils) {
+ FileUtils fileUtils, ConfigUtil configUtil) {
this.storeResponseInterceptor = storeResponseInterceptor;
this.sslContextCreator = creator;
this.fileUtils = fileUtils;
+ this.configUtil = configUtil;
}
/**
@@ -68,6 +73,9 @@ public class ClientFactory {
httpClientPolicy.setReceiveTimeout(params.getReceiveTimeout().longValueExact());
http.setClient(httpClientPolicy);
+ var customHeaders = configUtil.convertHeadersToMap(params.getCustomHTTPHeader());
+ client.getRequestContext().put(Message.PROTOCOL_HEADERS, customHeaders);
+
if (params.getURL().startsWith("https")) {
TLSClientParameters tlsParams = setupTLSParams(params.getSSL());
http.setTlsClientParameters(tlsParams);
diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java
index 0637f98..ed67154 100644
--- a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java
+++ b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java
@@ -43,7 +43,8 @@ public class ConfigProfileGenerator {
private ConfigProfileGenerator(
SpringPropertiesFacade properties,
ConfigUtil util,
- MzsDeliveryRequestValidator validator, boolean verifyCompletenessOfDefaultConfiguration,
+ MzsDeliveryRequestValidator validator,
+ boolean verifyCompletenessOfDefaultConfiguration,
String profilePrefix,
String defaultConfigKey) {
this.util = util;
diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java
index f49132f..ec7b7c8 100644
--- a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java
+++ b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigUtil.java
@@ -5,15 +5,19 @@ import at.gv.zustellung.app2mzs.xsd.*;
import org.springframework.stereotype.Component;
import java.math.BigInteger;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Stream;
import static at.gv.zustellung.app2mzs.xsd.ClientType.clientTypeBuilder;
import static at.gv.zustellung.app2mzs.xsd.ConfigType.configTypeBuilder;
+import static at.gv.zustellung.app2mzs.xsd.CustomHTTPHeaderType.*;
import static at.gv.zustellung.app2mzs.xsd.ForwardResponseToServiceType.forwardResponseToServiceTypeBuilder;
import static at.gv.zustellung.app2mzs.xsd.KeyStoreType.keyStoreTypeBuilder;
import static at.gv.zustellung.app2mzs.xsd.MsgResponseSinksType.msgResponseSinksTypeBuilder;
import static at.gv.zustellung.app2mzs.xsd.SSLType.SSLTypeBuilder;
import static at.gv.zustellung.app2mzs.xsd.SaveResponseToFileType.saveResponseToFileTypeBuilder;
+import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
@Component
@@ -41,6 +45,7 @@ public class ConfigUtil {
public static final String FORWARD_RESPONSE_TO_SERVICE_KEY = "forward-response-to-service";
public static final String MZS_CLIENT_KEY = "mzs-client";
public static final String SERVICE_TIMEOUT_KEY = "service-timeout";
+ public static final String CUSTOM_HTTP_HEADERS_KEY = "custom-http-headers";
/**
@@ -95,11 +100,16 @@ public class ConfigUtil {
SSLType ssl = sslParams.isEmpty()
? null : buildSSL(sslParams);
+ var customHeaderParams = filterMapByPrefix(clientParams, CUSTOM_HTTP_HEADERS_KEY);
+ var customHeaders = customHeaderParams.isEmpty()
+ ? null : convertMapToHeaders(customHeaderParams);
+
return clientTypeBuilder()
.withURL(url)
.withSSL(ssl)
.withConnectionTimeout(connectionTimeout)
.withReceiveTimeout(receiveTimeout)
+ .withCustomHTTPHeader(customHeaders)
.build();
}
@@ -243,6 +253,10 @@ public class ConfigUtil {
builder.withReceiveTimeout(primary.getReceiveTimeout());
}
+ if (primary.getCustomHTTPHeader() != null) {
+ builder.withCustomHTTPHeader(merge(primary.getCustomHTTPHeader(), fallback.getCustomHTTPHeader()));
+ }
+
return builder.build();
}
@@ -282,6 +296,26 @@ public class ConfigUtil {
}
+ private List<CustomHTTPHeaderType> merge(List<CustomHTTPHeaderType> primary, List<CustomHTTPHeaderType> fallback) {
+
+ if (fallback == null) return primary;
+
+ var primaryMap = convertHeadersToMap(primary);
+ var fallbackMap = convertHeadersToMap(fallback);
+
+ Map<String, String> mergedMap = Stream.of(fallbackMap, primaryMap)
+ .flatMap(map -> map.entrySet().stream())
+ .collect(toMap(
+ Map.Entry::getKey,
+ entry -> entry.getValue().get(0),
+ (v1, v2) -> v2
+ ));
+
+ return convertMapToHeaders(mergedMap);
+
+ }
+
+
private MsgResponseSinksType merge(MsgResponseSinksType primary, MsgResponseSinksType fallback) {
if (fallback == null) {
@@ -340,4 +374,32 @@ public class ConfigUtil {
}
+ /**
+ * Convert a Map that is indexed by header names into a List of CustomHTTPHeaders.
+ * @param customHeaderMap map of headers, indexed by header names.
+ * @return List of CustomHTTPHeaders
+ */
+ public List<CustomHTTPHeaderType> convertMapToHeaders(Map<String, String> customHeaderMap) {
+ return customHeaderMap.entrySet().stream()
+ .map(e -> customHTTPHeaderTypeBuilder()
+ .withName(e.getKey())
+ .withValue(e.getValue())
+ .build())
+ .collect(toList());
+ }
+
+
+ /**
+ * Convert a List of CustomHTTPHeaders into a Map that is indexed by the header names. Values are wrapped in Lists.
+ * @param customHeaders List of CustomHTTPHeaders
+ * @return Map of headers, indexed by header names.
+ */
+ public Map<String, List<String>> convertHeadersToMap(List<CustomHTTPHeaderType> customHeaders) {
+ return customHeaders
+ .stream()
+ .collect(toMap(
+ h -> h.getName(),
+ h -> List.of(h.getValue())));
+ }
+
}
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index ce4d892..0380cf5 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -61,11 +61,15 @@ delivery-request-configuration-profiles:
# Mandatory
url: http://localhost:8082/tnvz/
+ connection-timeout: 0
+ receive-timeout: 0
# Optional
- # ssl: ...
- # connection-timeout: ...
- # receive-timeout: ...
+ #ssl: ...
+ #custom-http-headers:
+ # X-PVP-NAME-1: VALUE-X
+ # X-PVP-NAME-2: VALUE-Y
+ # ...
# Mandatory
# Parameters for the connection to msg.
diff --git a/src/main/resources/mzs/app2mzs.xsd b/src/main/resources/mzs/app2mzs.xsd
index d19ff3b..7ae243b 100644
--- a/src/main/resources/mzs/app2mzs.xsd
+++ b/src/main/resources/mzs/app2mzs.xsd
@@ -3,6 +3,7 @@
<xs:import namespace="http://reference.e-government.gv.at/namespace/zustellung/mzs/persondata#" schemaLocation="mzs_mypersondata_en.xsd"/>
<xs:import namespace="http://reference.e-government.gv.at/namespace/zustellung/msg/phase2/20181206#" schemaLocation="../zusemsg/zuse_p2.xsd"/>
<xs:import namespace="http://reference.e-government.gv.at/namespace/zustellung/tnvz/phase2/20181206#" schemaLocation="../zusetnvz/zusetnvz_p2.xsd"/>
+
<xs:element name="DeliveryRequest" type="DeliveryRequestType"/>
<xs:complexType name="DeliveryRequestType">
<xs:sequence>
@@ -98,6 +99,7 @@
<xs:element ref="SSL" minOccurs="0"/>
<xs:element name="ConnectionTimeout" minOccurs="0" type="xs:nonNegativeInteger" />
<xs:element name="ReceiveTimeout" minOccurs="0" type="xs:nonNegativeInteger" />
+ <xs:element ref="CustomHTTPHeader" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="SSL" type="SSLType" />
@@ -118,6 +120,13 @@
<xs:element name="FileType" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
+ <xs:element name="CustomHTTPHeader" type="CustomHTTPHeaderType"/>
+ <xs:complexType name="CustomHTTPHeaderType">
+ <xs:sequence>
+ <xs:element name="Name" type="xs:string" />
+ <xs:element name="Value" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
<xs:element name="MsgResponseSinks" type="MsgResponseSinksType"/>
<xs:complexType name="MsgResponseSinksType">
<xs:sequence>
diff --git a/src/test/java/at/gv/egiz/moazs/ConfigUtilTest.java b/src/test/java/at/gv/egiz/moazs/ConfigUtilTest.java
new file mode 100644
index 0000000..d7ac0a1
--- /dev/null
+++ b/src/test/java/at/gv/egiz/moazs/ConfigUtilTest.java
@@ -0,0 +1,80 @@
+package at.gv.egiz.moazs;
+
+import at.gv.egiz.moazs.preprocess.ConfigUtil;
+import at.gv.zustellung.app2mzs.xsd.ConfigType;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static at.gv.zustellung.app2mzs.xsd.ClientType.clientTypeBuilder;
+import static at.gv.zustellung.app2mzs.xsd.ConfigType.configTypeBuilder;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ConfigUtilTest {
+
+ private ConfigUtil configUtil;
+
+ @Before
+ public void setup() {
+ configUtil = new ConfigUtil();
+ }
+
+ @Test
+ public void convertTNVZClientsCustomHttpHeaders() {
+ var prefix = ConfigUtil.TNVZ_CLIENT_KEY + "." + ConfigUtil.CUSTOM_HTTP_HEADERS_KEY + ".";
+ var map = Map.of(
+ prefix + "X-PVP-VERSION", "2.1",
+ prefix + "X-PVP-BINDING", "http",
+ prefix + "X-PVP-PARTICIPANT_ID", "AT:L9:MA2412"
+ );
+
+ ConfigType config = configUtil.convert(map);
+ var customHeaderMap = configUtil.convertHeadersToMap(config.getTNVZClient().getCustomHTTPHeader());
+
+ assertThat(customHeaderMap).containsEntry("X-PVP-VERSION", List.of("2.1"));
+ assertThat(customHeaderMap).containsEntry("X-PVP-BINDING", List.of("http"));
+ assertThat(customHeaderMap).containsEntry("X-PVP-PARTICIPANT_ID", List.of("AT:L9:MA2412"));
+ assertThat(customHeaderMap).hasSize(3);
+ }
+
+ @Test
+ public void overrideCustomHeaders() {
+
+ var fallbackConfig = createConfig(Map.of(
+ "X-header-1", "fallback-value-a",
+ "X-header-2", "fallback-value-b"
+ ));
+
+ var primaryConfig = createConfig(Map.of(
+ "X-header-2", "primary-value-c",
+ "X-header-3", "primary-value-d"
+ ));
+
+ ConfigType mergedConfig = configUtil.merge(primaryConfig, fallbackConfig);
+ var mergedHeaderMap = configUtil.convertHeadersToMap(mergedConfig.getTNVZClient().getCustomHTTPHeader());
+
+ assertThat(mergedHeaderMap).containsEntry("X-header-1", List.of("fallback-value-a"));
+ assertThat(mergedHeaderMap).containsEntry("X-header-2", List.of("primary-value-c"));
+ assertThat(mergedHeaderMap).containsEntry("X-header-3", List.of("primary-value-d"));
+ assertThat(mergedHeaderMap).hasSize(3);
+
+ }
+
+ private ConfigType createConfig(Map<String, String> headerMap) {
+
+ var headers = configUtil.convertMapToHeaders(headerMap);
+
+ var client = clientTypeBuilder()
+ .withCustomHTTPHeader(headers)
+ .build();
+
+ return configTypeBuilder()
+ .withTNVZClient(client)
+ .build();
+ }
+
+
+
+}