// Path: src/main/java/com/difference/historybook/proxy/Proxy.java
// public interface Proxy {
// 	
// 	/**
// 	 * Start the web proxy service
// 	 * 
// 	 * @throws Exception
// 	 */
// 	public void start() throws Exception;
// 	
// 	/**
// 	 * Stop the web proxy service
// 	 * 
// 	 * @throws Exception
// 	 */
// 	public void stop() throws Exception;
// 	
// 	/**
// 	 * Specify the port to run the proxy server on. May not take affect until next start.
// 	 * @param port port to run the proxy server on
// 	 * @return this for method chaining
// 	 */
// 	public Proxy setPort(int port);
// 	
// 	/**
// 	 * Specify a @ProxyFilterFactory to use in creating @ProxyFilter instances for each proxy request/response
// 	 * @param factory the @ProxyFilterFactory to use in creating @ProxyFilter instances for each proxy request/response
// 	 * @return        this for method call chaining
// 	 */
// 	public Proxy setFilterFactory(ProxyFilterFactory factory);
// 	
// 	/**
// 	 * Specify a @Predicate to use to determine whether a @ProxyResponse will be required.
// 	 * This is done early in the streaming of a response by peeking at the headers to determine
// 	 * whether the content will need to be buffered and decompressed for use.
// 	 * 
// 	 * @param selector a @Predicate that, given a @ProxyResponseInfo, determines whether a response should be buffered, decompressed, and passed to the filter for processing.
// 	 * @return	this for method call chaining
// 	 */
// 	public Proxy setResponseFilterSelector(Predicate<ProxyTransactionInfo> selector);
// }
// 
// Path: src/main/java/com/difference/historybook/proxy/ProxyFilter.java
// public interface ProxyFilter {
// 	/**
// 	 * Perform arbitrary processing based on a given @ProxyRequest
// 	 * @param request 
// 	 */
// 	public void processRequest(ProxyRequest request);
// 
// 	/**
// 	 * Perform arbitrary processing based on a given @ProxyResponse
// 	 * @param response 
// 	 */
// 	public void processResponse(ProxyResponse response);
// }
// 
// Path: src/main/java/com/difference/historybook/proxy/ProxyFilterFactory.java
// public interface ProxyFilterFactory {
// 	/**
// 	 * Return a new @ProxyFilter for use with a new request/response pair.
// 	 * @return @ProxyFilter Note that this should be a new object with each call unless the given proxy filter is stateless.
// 	 */
// 	public ProxyFilter getInstance();
// }
// 
// Path: src/main/java/com/difference/historybook/proxy/ProxyTransactionInfo.java
// public class ProxyTransactionInfo {
// 	private final String url;
// 	private final int status;
// 	private final Map<String,String> headers;
// 	
// 	public ProxyTransactionInfo(String url, int status, Map<String,String> headers) {
// 		this.url = url;
// 		this.status = status;
// 		this.headers = headers;
// 	}
// 	
// 	/**
// 	 * @return return the URL of the page being fetched
// 	 */
// 	public String getUrl() {
// 		return url;
// 	}
// 
// 	/**
// 	 * @return the numeric HTTP response code for the response
// 	 */
// 	public int getStatus() {
// 		return status;
// 	}
// 
// 	/**
// 	 * @return a @Map of the HTTP headers associated with the response
// 	 */
// 	public Map<String, String> getHeaders() {
// 		return headers;
// 	}
// 
// }


import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import org.littleshoot.proxy.HttpFilters;
import org.littleshoot.proxy.HttpFiltersAdapter;
import org.littleshoot.proxy.HttpFiltersSource;
import org.littleshoot.proxy.HttpFiltersSourceAdapter;
import org.littleshoot.proxy.HttpProxyServer;
import org.littleshoot.proxy.impl.DefaultHttpProxyServer;
import org.littleshoot.proxy.impl.ProxyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.difference.historybook.proxy.Proxy;
import com.difference.historybook.proxy.ProxyFilter;
import com.difference.historybook.proxy.ProxyFilterFactory;
import com.difference.historybook.proxy.ProxyTransactionInfo;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.http.DefaultHttpContent;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpContentDecompressor;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.codec.http.LastHttpContent;
/*
 * Copyright 2016 Andrew W. Buchanan (buchanan@difference.com)
 * 
 * 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 com.difference.historybook.proxy.littleproxy;





/**
 * An implementation of @Proxy using LittleProxy which is based on a Netty core 
 */
public class LittleProxy implements Proxy {
	private static final Logger LOG = LoggerFactory.getLogger(LittleProxy.class);

	private ProxyFilterFactory filterFactory;
// Path: src/main/java/com/difference/historybook/proxy/Proxy.java
// public interface Proxy {
// 	
// 	/**
// 	 * Start the web proxy service
// 	 * 
// 	 * @throws Exception
// 	 */
// 	public void start() throws Exception;
// 	
// 	/**
// 	 * Stop the web proxy service
// 	 * 
// 	 * @throws Exception
// 	 */
// 	public void stop() throws Exception;
// 	
// 	/**
// 	 * Specify the port to run the proxy server on. May not take affect until next start.
// 	 * @param port port to run the proxy server on
// 	 * @return this for method chaining
// 	 */
// 	public Proxy setPort(int port);
// 	
// 	/**
// 	 * Specify a @ProxyFilterFactory to use in creating @ProxyFilter instances for each proxy request/response
// 	 * @param factory the @ProxyFilterFactory to use in creating @ProxyFilter instances for each proxy request/response
// 	 * @return        this for method call chaining
// 	 */
// 	public Proxy setFilterFactory(ProxyFilterFactory factory);
// 	
// 	/**
// 	 * Specify a @Predicate to use to determine whether a @ProxyResponse will be required.
// 	 * This is done early in the streaming of a response by peeking at the headers to determine
// 	 * whether the content will need to be buffered and decompressed for use.
// 	 * 
// 	 * @param selector a @Predicate that, given a @ProxyResponseInfo, determines whether a response should be buffered, decompressed, and passed to the filter for processing.
// 	 * @return	this for method call chaining
// 	 */
// 	public Proxy setResponseFilterSelector(Predicate<ProxyTransactionInfo> selector);
// }
// 
// Path: src/main/java/com/difference/historybook/proxy/ProxyFilter.java
// public interface ProxyFilter {
// 	/**
// 	 * Perform arbitrary processing based on a given @ProxyRequest
// 	 * @param request 
// 	 */
// 	public void processRequest(ProxyRequest request);
// 
// 	/**
// 	 * Perform arbitrary processing based on a given @ProxyResponse
// 	 * @param response 
// 	 */
// 	public void processResponse(ProxyResponse response);
// }
// 
// Path: src/main/java/com/difference/historybook/proxy/ProxyFilterFactory.java
// public interface ProxyFilterFactory {
// 	/**
// 	 * Return a new @ProxyFilter for use with a new request/response pair.
// 	 * @return @ProxyFilter Note that this should be a new object with each call unless the given proxy filter is stateless.
// 	 */
// 	public ProxyFilter getInstance();
// }
// 
// Path: src/main/java/com/difference/historybook/proxy/ProxyTransactionInfo.java
// public class ProxyTransactionInfo {
// 	private final String url;
// 	private final int status;
// 	private final Map<String,String> headers;
// 	
// 	public ProxyTransactionInfo(String url, int status, Map<String,String> headers) {
// 		this.url = url;
// 		this.status = status;
// 		this.headers = headers;
// 	}
// 	
// 	/**
// 	 * @return return the URL of the page being fetched
// 	 */
// 	public String getUrl() {
// 		return url;
// 	}
// 
// 	/**
// 	 * @return the numeric HTTP response code for the response
// 	 */
// 	public int getStatus() {
// 		return status;
// 	}
// 
// 	/**
// 	 * @return a @Map of the HTTP headers associated with the response
// 	 */
// 	public Map<String, String> getHeaders() {
// 		return headers;
// 	}
// 
// }


// Path: src/main/java/com/difference/historybook/proxy/littleproxy/LittleProxy.java
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import org.littleshoot.proxy.HttpFilters;
import org.littleshoot.proxy.HttpFiltersAdapter;
import org.littleshoot.proxy.HttpFiltersSource;
import org.littleshoot.proxy.HttpFiltersSourceAdapter;
import org.littleshoot.proxy.HttpProxyServer;
import org.littleshoot.proxy.impl.DefaultHttpProxyServer;
import org.littleshoot.proxy.impl.ProxyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.difference.historybook.proxy.Proxy;
import com.difference.historybook.proxy.ProxyFilter;
import com.difference.historybook.proxy.ProxyFilterFactory;
import com.difference.historybook.proxy.ProxyTransactionInfo;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.http.DefaultHttpContent;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpContentDecompressor;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.codec.http.LastHttpContent;

/*
 * Copyright 2016 Andrew W. Buchanan (buchanan@difference.com)
 * 
 * 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 com.difference.historybook.proxy.littleproxy;





/**
 * An implementation of @Proxy using LittleProxy which is based on a Netty core 
 */
public class LittleProxy implements Proxy {
	private static final Logger LOG = LoggerFactory.getLogger(LittleProxy.class);

	private ProxyFilterFactory filterFactory;
	private Predicate<ProxyTransactionInfo> selector;