From 2b8a7df25878f546ace25373f44baeb026cf6d2b Mon Sep 17 00:00:00 2001 From: Christof Rabensteiner Date: Tue, 20 Aug 2019 11:13:28 +0200 Subject: 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. --- .../at/gv/egiz/moazs/client/ClientFactory.java | 10 +++- .../moazs/preprocess/ConfigProfileGenerator.java | 3 +- .../at/gv/egiz/moazs/preprocess/ConfigUtil.java | 62 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) (limited to 'src/main/java/at') 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 merge(List primary, List fallback) { + + if (fallback == null) return primary; + + var primaryMap = convertHeadersToMap(primary); + var fallbackMap = convertHeadersToMap(fallback); + + Map 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 convertMapToHeaders(Map 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> convertHeadersToMap(List customHeaders) { + return customHeaders + .stream() + .collect(toMap( + h -> h.getName(), + h -> List.of(h.getValue()))); + } + } -- cgit v1.2.3