ProxyingHttpClientBuilder.java
/*
* 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.esigate.http;
import java.io.IOException;
import java.util.Properties;
import org.apache.http.HttpException;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpExecutionAware;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.client.cache.CachingHttpClientBuilder;
import org.apache.http.impl.execchain.ClientExecChain;
import org.esigate.HttpErrorPage;
import org.esigate.cache.CacheAdapter;
import org.esigate.events.EventManager;
import org.esigate.events.impl.FetchEvent;
public class ProxyingHttpClientBuilder extends CachingHttpClientBuilder {
private Properties properties;
private EventManager eventManager;
private boolean useCache = true;
@Override
protected ClientExecChain decorateMainExec(ClientExecChain mainExec) {
ClientExecChain result = mainExec;
result = addFetchEvent(result);
if (useCache) {
CacheAdapter cacheAdapter = new CacheAdapter();
cacheAdapter.init(properties);
result = cacheAdapter.wrapBackendHttpClient(result);
result = super.decorateMainExec(result);
result = cacheAdapter.wrapCachingHttpClient(result);
}
return result;
}
public void setUseCache(boolean useCache) {
this.useCache = useCache;
}
public void setEventManager(EventManager eventManager) {
this.eventManager = eventManager;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public EventManager getEventManager() {
return eventManager;
}
public boolean isUseCache() {
return useCache;
}
/**
* Decorate with fetch event managements
*
* @param wrapped
* @return the decorated ClientExecChain
*/
private ClientExecChain addFetchEvent(final ClientExecChain wrapped) {
return new ClientExecChain() {
@Override
public CloseableHttpResponse execute(HttpRoute route, HttpRequestWrapper request,
HttpClientContext httpClientContext, HttpExecutionAware execAware) {
OutgoingRequestContext context = OutgoingRequestContext.adapt(httpClientContext);
// Create request event
FetchEvent fetchEvent = new FetchEvent(context, request);
eventManager.fire(EventManager.EVENT_FETCH_PRE, fetchEvent);
if (fetchEvent.isExit()) {
if (fetchEvent.getHttpResponse() == null) {
// Provide an error page in order to avoid a NullPointerException
fetchEvent.setHttpResponse(HttpErrorPage.generateHttpResponse(
HttpStatus.SC_INTERNAL_SERVER_ERROR,
"An extension stopped the processing of the request without providing a response"));
}
} else {
try {
fetchEvent.setHttpResponse(wrapped.execute(route, request, context, execAware));
} catch (IOException | HttpException e) {
fetchEvent.setHttpResponse(HttpErrorPage.generateHttpResponse(e));
}
}
// Update the event and fire post event
eventManager.fire(EventManager.EVENT_FETCH_POST, fetchEvent);
return fetchEvent.getHttpResponse();
}
};
}
}