package de.digitalstep.ntlmproxy;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
import com.google.common.io.ByteStreams;
import de.compeople.commons.net.proxy.CompoundProxySelectorFactory;
class Handler implements Runnable {
private static final Logger log = LoggerFactory.getLogger(Handler.class);
private static final List<String> stripHeadersIn = Arrays.asList("Content-Type", "Content-Length", "Proxy-Connection");
private static final List<String> stripHeadersOut = Arrays.asList("Proxy-Authentication", "Proxy-Authorization");
private final Socket socket;
private HandlerListener listener;
public Handler(Socket socket, Optional<HandlerListener> listener) {
this.socket = socket;
this.listener = listener.isPresent() ? listener.get() : new HandlerListener();
}
public void run() {
HttpParser parser = null;
try {
parser = new HttpParser(socket.getInputStream());
try {
while (!parser.parse())
;
} catch (IOException e) {
log.warn(e.getMessage(), e);
return;
}
URI uri = enableSystemProxy(parser.getUri());
HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
connection.setRequestMethod(parser.getMethod());
connection.setInstanceFollowRedirects(false);
for (Header header : parser.getHeaders()) {
if (!stripHeadersIn.contains(header.name())) {
connection.addRequestProperty(header.name(), header.value());
}
}
socket.shutdownInput();
final OutputStream out = socket.getOutputStream();
switch (connection.getResponseCode()) {
case 404:
out.write("HTTP/1.0 404 Not Found\r\n".getBytes());
out.close();
return;
}
for (int index = 0; index < 1; index++) {
Header header = new Header(connection.getHeaderFieldKey(index), connection.getHeaderField(index));
if (!stripHeadersOut.contains(header.name())) {
out.write((header.toString() + "\r\n").getBytes());
log.debug("Wrote header {}", header);
}
}
out.write("Gunnar: Test\r\n".getBytes());
final InputStream in = connection.getInputStream();
out.write("\r\n".getBytes());
byte[] bytes = ByteStreams.toByteArray(in);
ByteStreams.copy(new ByteArrayInputStream(bytes), out);
// out.write("\r\n".getBytes());
parser.close();
in.close();
out.close();
log.debug("Output closed");
connection.disconnect();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private URI enableSystemProxy(final String location) throws URISyntaxException {
URI uri = new URI(location);
Proxy proxy = CompoundProxySelectorFactory.getProxySelector().select(uri).get(0);
listener.onGet(uri, proxy);
InetSocketAddress addr = (InetSocketAddress) proxy.address();
if (addr == null) {
System.setProperty("http.proxyHost", "");
System.setProperty("http.proxyPort", "");
} else {
System.setProperty("http.proxyHost", addr.getHostName());
System.setProperty("http.proxyPort", Integer.toString(addr.getPort()));
}
return uri;
}
}