//
// ProxyHandler
// Copyright 2004 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany
// Copyright 2011 by Florian Richter
// First released 2011 at http://yacy.net
//
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program in the file lgpl21.txt
// If not, see .
//
package net.yacy.http;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.yacy.cora.protocol.HeaderFramework;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.cora.protocol.http.HTTPClient;
import net.yacy.kelondro.util.FileUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
public class ProxyHandler extends AbstractHandler implements Handler {
private List localVirtualHostNames;
protected void doStart() {
localVirtualHostNames = new LinkedList();
localVirtualHostNames.add("localpeer");
localVirtualHostNames.add("localhost");
}
private RequestHeader convertHeaderFromJetty(HttpServletRequest request) {
RequestHeader result = new RequestHeader();
@SuppressWarnings("unchecked")
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
@SuppressWarnings("unchecked")
Enumeration headers = request.getHeaders(headerName);
while(headers.hasMoreElements()) {
String header = headers.nextElement();
result.add(headerName, header);
}
}
return result;
}
private void convertHeaderToJetty(HttpResponse in, HttpServletResponse out) {
for(Header h: in.getAllHeaders()) {
out.addHeader(h.getName(), h.getValue());
}
}
private void cleanResponseHeader(HttpResponse headers) {
headers.removeHeaders("Content-Encoding");
headers.removeHeaders("Content-Length");
}
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
String host = request.getHeader("Host");
if(host == null) return; // no proxy request, continue processing by handlers
int hostSplitPos = host.indexOf(':');
String hostOnly = hostSplitPos<0 ? host : host.substring(0, hostSplitPos);
if(localVirtualHostNames.contains(hostOnly)) return; // no proxy request, continue processing by handlers
RequestHeader proxyHeaders = convertHeaderFromJetty(request);
proxyHeaders.add(RequestHeader.VIA, "YaCy");
proxyHeaders.remove(RequestHeader.KEEP_ALIVE);
proxyHeaders.remove(RequestHeader.CONTENT_LENGTH);
final HTTPClient client = new HTTPClient();
int timeout = 60000;
client.setTimout(timeout);
client.setHeader(proxyHeaders.entrySet());
client.setRedirecting(false);
// send request
try {
String queryString = request.getQueryString()!=null ? "?" + request.getQueryString() : "";
if (request.getMethod().equals("GET")) {
client.GET(request.getRequestURL().toString() + queryString);
} else if (request.getMethod().equals("POST")) {
client.POST(request.getRequestURL().toString() + queryString, request.getInputStream(), request.getContentLength());
} else if (request.getMethod().equals("HEAD")) {
client.HEADResponse(request.getRequestURL().toString() + queryString);
} else {
throw new ServletException("Unsupported Request Method");
}
HttpResponse responseHeader = client.getHttpResponse();
cleanResponseHeader(responseHeader);
convertHeaderToJetty(responseHeader, response);
//response.setContentType(responseHeader.getFirstHeader(HeaderFramework.CONTENT_TYPE).getValue());
response.setStatus(responseHeader.getStatusLine().getStatusCode());
client.writeTo(response.getOutputStream());
} catch(SocketException se) {
throw new ServletException("Socket Exception: " + se.getMessage());
} finally {
client.finish();
}
// we handled this request, break out of handler chain
Request base_request = (request instanceof Request) ? (Request)request:HttpConnection.getCurrentConnection().getRequest();
base_request.setHandled(true);
}
}