Java tutorial
/** * Copyright (C) 2013 Inera AB (http://www.inera.se) * * This file is part of Inera Certificate Proxy (http://code.google.com/p/inera-certificate-proxy). * * Inera Certificate Proxy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Inera Certificate Proxy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package se.inera.certificate.proxy.mappings.remote; import com.google.common.base.Throwables; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpOptions; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.InputStreamEntity; import org.apache.http.message.BasicHttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.inera.certificate.proxy.filter.RequestContext; import se.inera.certificate.proxy.mappings.AbstractDispatcher; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Arrays; import java.util.List; import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; import static java.util.Collections.list; import static org.apache.commons.io.IOUtils.copyLarge; import static org.apache.commons.lang.StringUtils.lowerCase; import static org.apache.commons.lang.StringUtils.substringAfter; import static se.inera.certificate.proxy.utils.PathUtil.getPath; import static se.inera.certificate.proxy.utils.PathUtil.joinFragments; public class RemoteDispatcher extends AbstractDispatcher { private static final List<String> BLOCKED_HEADERS = Arrays.asList(new String[] { "host" }); private Logger log = LoggerFactory.getLogger(RemoteDispatcher.class); private final HttpClient httpClient; private final RemoteMapping remoteMapping; public RemoteDispatcher(RemoteMapping remoteMapping, RequestContext requestContext) { super(requestContext); this.httpClient = requestContext.getHttpClient(); this.remoteMapping = remoteMapping; } @Override public void dispatch(HttpServletRequest httpRequest, HttpServletResponse httpResponse) { try { doDispatch(httpRequest, httpResponse); } catch (IOException e) { Throwables.propagate(e); } } private void doDispatch(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException { URI newUrl = buildNewURL(httpRequest, remoteMapping); HttpResponse resp = makeRequest(httpRequest, newUrl); httpResponse.setStatus(resp.getStatusLine().getStatusCode()); for (Header h : resp.getAllHeaders()) { httpResponse.addHeader(h.getName(), h.getValue()); } sendResponseEntity(httpResponse, resp.getEntity()); } private void sendResponseEntity(ServletResponse response, HttpEntity entity) throws IOException { // Entity can be null in case of 304 answer. if (entity != null) { Header contentType = entity.getContentType(); if (contentType != null) { response.setContentType(contentType.getValue()); } copyLarge(entity.getContent(), response.getOutputStream()); } response.getOutputStream().flush(); } private URI buildNewURL(HttpServletRequest httpRequest, RemoteMapping mapping) { checkNotNull(httpRequest, "Argument httpRequest is null!"); checkNotNull(mapping, "Argument mapping is null!"); String requestUrl = getPath(httpRequest); String newUri = joinFragments(mapping.getMappedPath(), substringAfter(requestUrl, mapping.getContext())); URI result = null; try { result = new URIBuilder().setScheme(mapping.getMappedProtocol()).setHost(mapping.getMappedHost()) .setPort(mapping.getMappedPort()).setPath(newUri).setQuery(httpRequest.getQueryString()) .build(); } catch (URISyntaxException e) { Throwables.propagate(e); } return result; } private HttpResponse makeRequest(HttpServletRequest request, URI newUrl) throws IOException { log.debug("CALLING: {}", newUrl); String method = request.getMethod(); if (method.equalsIgnoreCase("GET")) { return makeGetRequest(request, new HttpGet(newUrl)); } else if (method.contentEquals("POST")) { return makePostRequest(request, new HttpPost(newUrl)); } else if (method.contentEquals("PUT")) { return makePutRequest(request, new HttpPut(newUrl)); } else if (method.contentEquals("OPTIONS")) { return makeOptionsRequest(request, new HttpOptions(newUrl)); } return new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_FORBIDDEN, "Unknown method:" + method); } private HttpResponse makeGetRequest(HttpServletRequest request, HttpGet get) throws IOException { addHeaders(request, get); return makeRequest(get); } private HttpResponse makePostRequest(HttpServletRequest request, HttpPost post) throws IOException { addHeaders(request, post); post.setEntity(new InputStreamEntity(request.getInputStream(), -1)); return makeRequest(post); } private HttpResponse makePutRequest(HttpServletRequest request, HttpPut put) throws IOException { addHeaders(request, put); put.setEntity(new InputStreamEntity(request.getInputStream(), -1)); return makeRequest(put); } private HttpResponse makeOptionsRequest(HttpServletRequest request, HttpOptions options) throws IOException { addHeaders(request, options); return makeRequest(options); } private void addHeaders(HttpServletRequest request, HttpUriRequest req) { for (String headerName : list(request.getHeaderNames())) { if (!BLOCKED_HEADERS.contains(lowerCase(headerName))) { req.addHeader(headerName, request.getHeader(headerName)); } } for (Map.Entry<String, String> headers : getRequestContext().getHeaders(request).entrySet()) { req.setHeader(headers.getKey(), headers.getValue()); } } private HttpResponse makeRequest(HttpUriRequest msg) throws IOException { return httpClient.execute(msg); } }