1b9e57f4550cd1d7692f0b8fcc1781c2c99c8f14
[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 import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
25
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 import reactor.core.publisher.Mono;
35 import reactor.netty.http.client.HttpClient;
36
37 import javax.net.ssl.SSLException;
38 import java.util.Map;
39
40 import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.RESPONSE_CODE;
41 import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.SERVICE_NAME;
42 import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
43
44
45 public class AaiReactiveWebClientFactory {
46
47     private static final Logger LOGGER = LoggerFactory.getLogger(AaiReactiveWebClientFactory.class);
48
49     private final String aaiUserName;
50     private final String aaiUserPassword;
51     private final Map<String, String> aaiHeaders;
52     private final Boolean enableAaiCertAuth;
53     private final String trustStorePath;
54     private final String trustStorePasswordPath;
55     private final String keyStorePath;
56     private final String keyStorePasswordPath;
57     private final SslFactory sslFactory;
58
59     /**
60      * Creating AaiReactiveWebClientFactory.
61      *
62      * @param configuration - configuration object
63      * @param sslFactory - factory for ssl setup
64      */
65     public AaiReactiveWebClientFactory(SslFactory sslFactory, AaiClientConfiguration configuration) {
66         this.aaiUserName = configuration.aaiUserName();
67         this.aaiUserPassword = configuration.aaiUserPassword();
68         this.aaiHeaders = configuration.aaiHeaders();
69         this.trustStorePath = configuration.trustStorePath();
70         this.trustStorePasswordPath = configuration.trustStorePasswordPath();
71         this.keyStorePath = configuration.keyStorePath();
72         this.keyStorePasswordPath = configuration.keyStorePasswordPath();
73         this.enableAaiCertAuth = configuration.enableAaiCertAuth();
74         this.sslFactory = sslFactory;
75     }
76
77     /**
78      * Construct Reactive WebClient with appropriate settings.
79      *
80      * @return WebClient
81      */
82     public WebClient build() throws SSLException {
83         LOGGER.debug("Setting ssl context");
84         
85         SslContext sslContext = createSslContext();
86
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 }