85ba8ea504a60d5b773ecb64b0c968746aec3219
[dcaegen2/services/sdk.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * DCAEGEN2-SERVICES-SDK
4  * ================================================================================
5  * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.dcaegen2.services.sdk.rest.services.aai.client.service;
22
23 import io.netty.handler.ssl.SslContext;
24
25 import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
26 import org.onap.dcaegen2.services.sdk.rest.services.ssl.SslFactory;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.slf4j.MDC;
30 import org.springframework.http.client.reactive.ClientHttpConnector;
31 import org.springframework.http.client.reactive.ReactorClientHttpConnector;
32 import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
33 import org.springframework.web.reactive.function.client.WebClient;
34
35 import reactor.core.publisher.Mono;
36 import reactor.netty.http.client.HttpClient;
37
38 import javax.net.ssl.SSLException;
39 import java.util.Map;
40
41 import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.RESPONSE_CODE;
42 import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.SERVICE_NAME;
43 import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
44
45
46 public class AaiReactiveWebClientFactory {
47
48     private static final Logger LOGGER = LoggerFactory.getLogger(AaiReactiveWebClientFactory.class);
49
50     private final String aaiUserName;
51     private final String aaiUserPassword;
52     private final Map<String, String> aaiHeaders;
53     private final Boolean enableAaiCertAuth;
54     private final String trustStorePath;
55     private final String trustStorePasswordPath;
56     private final String keyStorePath;
57     private final String keyStorePasswordPath;
58     private final SslFactory sslFactory;
59
60     /**
61      * Creating AaiReactiveWebClientFactory.
62      *
63      * @param configuration - configuration object
64      * @param sslFactory - factory for ssl setup
65      */
66     public AaiReactiveWebClientFactory(SslFactory sslFactory, AaiClientConfiguration configuration) {
67         this.aaiUserName = configuration.aaiUserName();
68         this.aaiUserPassword = configuration.aaiUserPassword();
69         this.aaiHeaders = configuration.aaiHeaders();
70         this.trustStorePath = configuration.trustStorePath();
71         this.trustStorePasswordPath = configuration.trustStorePasswordPath();
72         this.keyStorePath = configuration.keyStorePath();
73         this.keyStorePasswordPath = configuration.keyStorePasswordPath();
74         this.enableAaiCertAuth = configuration.enableAaiCertAuth();
75         this.sslFactory = sslFactory;
76     }
77
78     /**
79      * Construct Reactive WebClient with appropriate settings.
80      *
81      * @return WebClient
82      */
83     public WebClient build() throws SSLException {
84         LOGGER.debug("Setting ssl context");
85         
86         SslContext sslContext = createSslContext();
87
88         ClientHttpConnector reactorClientHttpConnector = new ReactorClientHttpConnector(
89             HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext)));
90
91         return WebClient.builder()
92             .clientConnector(reactorClientHttpConnector)
93             .defaultHeaders(httpHeaders -> httpHeaders.setAll(aaiHeaders))
94             .filter(basicAuthentication(aaiUserName, aaiUserPassword))
95             .filter(logRequest())
96             .filter(logResponse())
97             .build();
98     }
99
100     private SslContext createSslContext() throws SSLException {
101         if (enableAaiCertAuth) {
102             return sslFactory.createSecureContext(
103                 keyStorePath,
104                 keyStorePasswordPath,
105                 trustStorePath,
106                 trustStorePasswordPath
107             );
108         }
109         return sslFactory.createInsecureContext();
110     }
111     
112     private ExchangeFilterFunction logRequest() {
113         return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
114             MDC.put(SERVICE_NAME, String.valueOf(clientRequest.url()));
115             LOGGER.info("Request: {} {}", clientRequest.method(), clientRequest.url());
116             clientRequest.headers()
117                 .forEach((name, values) -> values.forEach(value -> LOGGER.info("{}={}", name, value)));
118             MDC.remove(SERVICE_NAME);
119             return Mono.just(clientRequest);
120         });
121     }
122
123     private ExchangeFilterFunction logResponse() {
124         return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
125             MDC.put(RESPONSE_CODE, String.valueOf(clientResponse.statusCode()));
126             LOGGER.info("Response Status {}", clientResponse.statusCode());
127             MDC.remove(RESPONSE_CODE);
128             return Mono.just(clientResponse);
129         });
130     }
131 }