2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2018 European Software Marketing Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
20 package org.onap.aaf.rproxy;
23 import java.net.URISyntaxException;
24 import java.util.Enumeration;
25 import java.util.UUID;
26 import javax.annotation.Resource;
27 import javax.servlet.http.HttpServletRequest;
28 import org.onap.aaf.fproxy.data.CredentialCacheData;
29 import org.onap.aaf.fproxy.data.CredentialCacheData.CredentialType;
30 import org.onap.aaf.rproxy.config.ForwardProxyProperties;
31 import org.onap.aaf.rproxy.config.PrimaryServiceProperties;
32 import org.onap.aaf.rproxy.logging.ReverseProxyMethodLogTimeAnnotation;
33 import org.onap.aaf.rproxy.utils.ReverseProxyUtils;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.springframework.beans.factory.annotation.Autowired;
37 import org.springframework.beans.factory.annotation.Value;
38 import org.springframework.boot.context.properties.EnableConfigurationProperties;
39 import org.springframework.http.HttpEntity;
40 import org.springframework.http.HttpHeaders;
41 import org.springframework.http.HttpMethod;
42 import org.springframework.http.ResponseEntity;
43 import org.springframework.web.bind.annotation.RequestBody;
44 import org.springframework.web.bind.annotation.RequestHeader;
45 import org.springframework.web.bind.annotation.RequestMapping;
46 import org.springframework.web.bind.annotation.RestController;
47 import org.springframework.web.client.HttpClientErrorException;
48 import org.springframework.web.client.RestTemplate;
51 @EnableConfigurationProperties({ForwardProxyProperties.class, PrimaryServiceProperties.class})
52 public class ReverseProxyService {
54 private static final Logger LOGGER = LoggerFactory.getLogger(ReverseProxyService.class);
56 private String validatedTransactionId;
58 @Resource(name = "ForwardProxyProperties")
59 private ForwardProxyProperties forwardProxyProperties;
61 @Resource(name = "PrimaryServiceProperties")
62 private PrimaryServiceProperties primaryServiceProperties;
65 private RestTemplate restTemplate;
67 @Value("${transactionid.header.name}")
68 private String transactionIdHeader;
70 @RequestMapping("/**")
71 @ReverseProxyMethodLogTimeAnnotation
72 public ResponseEntity<String> handleRequest(HttpServletRequest request,
73 @RequestHeader(value = "${transactionid.header.name}", defaultValue = "") String transactionId,
74 @RequestBody(required = false) String requestBody, HttpMethod requestMethod) throws URISyntaxException {
75 validatedTransactionId = getValidTransactionId(transactionId);
77 // Extract Request Permissions and store in Forward Proxy cache
78 CredentialCacheData credentialCacheData = getCredentialDataFromRequest(request);
79 if (credentialCacheData != null) {
80 postCredentialsToCache(credentialCacheData);
83 // Call out to Primary Service & Return Response
84 URI requestURI = new URI(request.getRequestURI());
86 LOGGER.debug("Request URI: {}", request.getRequestURI());
88 // Get Request Endpoint & substitute in local values
89 URI primaryServiceURI = new URI(primaryServiceProperties.getProtocol(), requestURI.getUserInfo(),
90 primaryServiceProperties.getHost(), Integer.parseInt(primaryServiceProperties.getPort()),
91 requestURI.getPath(), requestURI.getQuery(), requestURI.getFragment());
93 LOGGER.debug("Primary Service URI:{}, HTTP Method: {}", primaryServiceURI, requestMethod);
95 HttpHeaders requestHeaders = setForwardedRequestHeaders(request);
96 HttpEntity<String> httpEntity = new HttpEntity<>(requestBody, requestHeaders);
98 return restTemplate.exchange(primaryServiceURI, requestMethod, httpEntity, String.class);
101 private String getValidTransactionId(String transactionId) {
102 LOGGER.debug("Request transaction ID: {}", transactionId);
103 if (transactionId == null || !ReverseProxyUtils.validTransactionId(transactionId)) {
104 transactionId = UUID.randomUUID().toString();
106 LOGGER.debug("Validated transaction ID: {}", transactionId);
107 return transactionId;
110 private HttpHeaders setForwardedRequestHeaders(HttpServletRequest httpServletRequest) {
111 HttpHeaders httpHeaders = new HttpHeaders();
112 Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
113 while (headerNames.hasMoreElements()) {
114 String headerName = headerNames.nextElement();
115 if (!headerName.equals(transactionIdHeader)) {
116 httpHeaders.set(headerName, httpServletRequest.getHeader(headerName));
119 // Always set transaction ID
120 httpHeaders.set(transactionIdHeader, validatedTransactionId);
126 * Retrieves credential data from request.
128 * @param request The request to retrieve credentials from
129 * @return The retrieved credential data, or null if no credentials are found in request
131 private CredentialCacheData getCredentialDataFromRequest(HttpServletRequest request) {
132 CredentialCacheData credentialCacheData = null;
133 String authValue = request.getHeader(HttpHeaders.AUTHORIZATION);
134 if (authValue != null) {
135 credentialCacheData = new CredentialCacheData(HttpHeaders.AUTHORIZATION, authValue, CredentialType.HEADER);
137 return credentialCacheData;
141 * Posts credential data to credential cache endpoint
143 * @param credentialCacheData The credential data to post
144 * @throws URISyntaxException
146 private void postCredentialsToCache(CredentialCacheData credentialCacheData) throws URISyntaxException {
147 URI forwardProxyURI = new URI(forwardProxyProperties.getProtocol(), null, forwardProxyProperties.getHost(),
148 forwardProxyProperties.getPort(), forwardProxyProperties.getCacheurl() + "/" + validatedTransactionId,
151 ResponseEntity<String> response =
152 restTemplate.postForEntity(forwardProxyURI, credentialCacheData, String.class);
154 if (!response.getStatusCode().is2xxSuccessful()) {
155 throw new HttpClientErrorException(response.getStatusCode(),
156 "Error posting to credential cache. Message: " + response.getBody());
161 public String toString() {
162 return this.getClass().getName() + ": Forward proxy host:" + forwardProxyProperties.getHost()
163 + ": Primary service host:" + primaryServiceProperties.getHost();