package com.adobe.cq.contentinsight.impl.servlets;
import org.slf4j.LoggerFactory;
import org.apache.felix.scr.annotations.Activate;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.service.component.ComponentContext;
import java.util.regex.Pattern;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.HttpClient;
import java.net.URISyntaxException;
import org.apache.http.client.utils.HttpClientUtils;
import java.io.OutputStream;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.SlingHttpServletRequest;
import org.slf4j.Logger;
import org.apache.felix.scr.annotations.Reference;
import org.apache.http.osgi.services.HttpClientBuilderFactory;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
@SlingServlet(generateComponent = true, metatype = true, resourceTypes = { "cq/contentinsight/proxy" }, extensions = { "json" }, selectors = { "reportingservices" }, methods = { "GET" }, label = "Reporting Services API proxy servlet", description = "Proxy servlet for Reporting Services API")
public class ReportingServicesProxyServlet extends SlingSafeMethodsServlet
{
private static final String DEFAULT_API_OMNITURE_URL = ".*/api[0-9]*.omniture.com/.*";
@Property(name = "reportingservices.proxy.whitelist", label = "Whitelist", description = "Allowed destinations for the reporting services proxy servlet", cardinality = Integer.MAX_VALUE, value = { ".*/api[0-9]*.omniture.com/.*" })
private String[] whiteList;
@Reference
private HttpClientBuilderFactory clientBuilderFactory;
private static final long serialVersionUID = 7044811756109092040L;
private static final Logger LOG;
public ReportingServicesProxyServlet() {
this.whiteList = new String[] { ".*/api[0-9]*.omniture.com/.*" };
}
protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response) throws ServletException, IOException {
final String url = request.getParameter("url");
final String query = request.getParameter("q");
if (url == null || query == null) {
response.setStatus(400);
return;
}
if (!this.isUrlAllowed(url)) {
ReportingServicesProxyServlet.LOG.warn("Received url " + url + " not whitelisted!");
return;
}
final CloseableHttpClient httpClient = this.clientBuilderFactory.newBuilder().build();
try {
final URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.addParameter("q", query);
final HttpGet get = new HttpGet(uriBuilder.build());
get.setHeader("x-adobe-rs-auth", request.getHeader("x-adobe-rs-auth"));
HttpResponse getResponse = null;
try {
getResponse = (HttpResponse)httpClient.execute((HttpUriRequest)get);
final int status = getResponse.getStatusLine().getStatusCode();
IOUtils.copy(getResponse.getEntity().getContent(), (OutputStream)response.getOutputStream());
response.setStatus(status);
}
finally {
HttpClientUtils.closeQuietly(getResponse);
}
}
catch (URISyntaxException e) {
ReportingServicesProxyServlet.LOG.error("Invalid URL: " + url, (Throwable)e);
}
finally {
HttpClientUtils.closeQuietly((HttpClient)httpClient);
}
}
private boolean isUrlAllowed(final String url) {
boolean isAllowed = false;
for (final String whitelistedRegex : this.whiteList) {
final Pattern pattern = Pattern.compile(whitelistedRegex);
isAllowed = pattern.matcher((CharSequence)url).matches();
if (isAllowed) {
break;
}
}
return isAllowed;
}
@Activate
protected void activate(final ComponentContext ctx) {
this.whiteList = PropertiesUtil.toStringArray(ctx.getProperties().get("reportingservices.proxy.whitelist"), new String[] { ".*/api[0-9]*.omniture.com/.*" });
}
static {
LOG = LoggerFactory.getLogger((Class)ReportingServicesProxyServlet.class);
}
protected void bindClientBuilderFactory(final HttpClientBuilderFactory clientBuilderFactory) {
this.clientBuilderFactory = clientBuilderFactory;
}
protected void unbindClientBuilderFactory(final HttpClientBuilderFactory httpClientBuilderFactory) {
if (this.clientBuilderFactory == httpClientBuilderFactory) {
this.clientBuilderFactory = null;
}
}
}