Java tutorial
/** * Copyright 2018, Radiant Solutions, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package org.venice.beachfront.bfapi.services; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLDecoder; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import org.apache.http.client.HttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; import org.venice.beachfront.bfapi.geoserver.AuthHeaders; import org.venice.beachfront.bfapi.geoserver.GeoserverEnvironment; import org.venice.beachfront.bfapi.model.exception.UserException; import model.logger.Severity; import util.PiazzaLogger; /** * Service that proxies requests to the GeoServer instance */ @Service public class GeoServerProxyService { @Value("${geoserver.timeout}") private int geoserverTimeout; // Class-scoped for mocks. We don't want to autoWire. private RestTemplate restTemplate = new RestTemplate(); @Autowired private PiazzaLogger piazzaLogger; @Autowired private GeoserverEnvironment geoserverEnvironment; @Autowired private HttpClient httpClient; @Autowired private AuthHeaders authHeaders; private HttpEntity<String> requestHeaders; private URL geoserverUrl; @PostConstruct public void initialize() throws MalformedURLException { // Configure a timeout specific to GeoServer. These connections are prone to hanging, and we want to enforce a // quick timeout period so this does not lock up the application. HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory( this.httpClient); requestFactory.setReadTimeout(geoserverTimeout); restTemplate.setRequestFactory(requestFactory); requestHeaders = new HttpEntity<>(authHeaders.get()); geoserverUrl = new URL(geoserverEnvironment.getGeoServerBaseUrl()); } public ResponseEntity<byte[]> proxyRequest(HttpServletRequest request) throws MalformedURLException, IOException, URISyntaxException, UserException { String requestPath = request.getRequestURI(); // Form the complete URI by piecing together the GeoServer URL with the API proxy request parameters URI requestUri = new URI(geoserverUrl.getProtocol(), null, geoserverUrl.getHost(), geoserverUrl.getPort(), requestPath, request.getQueryString(), null); // Double encoding takes place here. First, in the REST Request delivered to API by the client. Second, in the // translation to the URI object. Decode both of these steps to get the real, completely decoded request to // GeoServer. String decodedUrl = URLDecoder.decode(requestUri.toString(), "UTF-8"); decodedUrl = URLDecoder.decode(decodedUrl.toString(), "UTF-8"); piazzaLogger.log(String.format("Proxying request to GET GeoServer at URI %s", decodedUrl), Severity.INFORMATIONAL); try { ResponseEntity<byte[]> response = restTemplate.exchange(decodedUrl, HttpMethod.GET, requestHeaders, byte[].class); return response; } catch (HttpClientErrorException | HttpServerErrorException exception) { piazzaLogger.log(String.format("Received GeoServer error response, code=%d, length=%d, for URI %s", exception.getStatusCode().value(), exception.getResponseBodyAsString().length(), decodedUrl), Severity.ERROR); if (exception.getStatusCode().equals(HttpStatus.UNAUTHORIZED) || exception.getStatusCode().equals(HttpStatus.FORBIDDEN)) { throw new UserException("Bad Authentication with GeoServer", exception, exception.getResponseBodyAsString(), HttpStatus.BAD_REQUEST); } throw new UserException("Upstream GeoServer error", exception, exception.getResponseBodyAsString(), exception.getStatusCode()); } } }