317019 Date HTTP header not sent for HTTP/1.0 requests
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2010 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
b96953f305
commit
ac76f274cd
|
@ -3,6 +3,7 @@ jetty-7.1.5-SNAPSHOT
|
|||
+ 316449 Websocket disconnect fix
|
||||
+ 316584 Exception on startup if temp path has spaces and extractWAR=false
|
||||
+ 316597 Removed null check and fixed name in Resource#hrefEncodeURI
|
||||
+ 317019 Date HTTP header not sent for HTTP/1.0 requests
|
||||
+ JETTY-1237 Save local/remote address to be available after close
|
||||
|
||||
jetty-7.1.4.v20100610
|
||||
|
|
|
@ -33,7 +33,9 @@ public class ProxyServer
|
|||
server.setHandler(handler);
|
||||
|
||||
handler.addServletWithMapping(ProxyServlet.class,"/");
|
||||
|
||||
handler.getServlets()[0].setInitParameter("whiteList","www.google.com, galaxisweb.com/support/*");
|
||||
handler.getServlets()[0].setInitParameter("blackList","www.google.com/calendar/*");
|
||||
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
|
|
|
@ -1001,6 +1001,10 @@ public class HttpConnection implements Connection
|
|||
break;
|
||||
case HttpVersions.HTTP_1_0_ORDINAL:
|
||||
_generator.setHead(_head);
|
||||
|
||||
if (_server.getSendDateHeader())
|
||||
_generator.setDate(_request.getTimeStampBuffer());
|
||||
|
||||
break;
|
||||
case HttpVersions.HTTP_1_1_ORDINAL:
|
||||
_generator.setHead(_head);
|
||||
|
|
|
@ -5,16 +5,21 @@ import java.net.InetSocketAddress;
|
|||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.PathMap;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.ConnectedEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
|
@ -26,6 +31,8 @@ import org.eclipse.jetty.server.Handler;
|
|||
import org.eclipse.jetty.server.HttpConnection;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.HostMap;
|
||||
import org.eclipse.jetty.util.IPAddressMap;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -48,6 +55,8 @@ public class ProxyHandler extends HandlerWrapper
|
|||
private volatile int _writeTimeout = 30000;
|
||||
private volatile ThreadPool _threadPool;
|
||||
private volatile boolean _privateThreadPool;
|
||||
private HostMap<PathMap> _white = new HostMap<PathMap>();
|
||||
private HostMap<PathMap> _black = new HostMap<PathMap>();
|
||||
|
||||
public ProxyHandler()
|
||||
{
|
||||
|
@ -59,6 +68,13 @@ public class ProxyHandler extends HandlerWrapper
|
|||
setHandler(handler);
|
||||
}
|
||||
|
||||
public ProxyHandler(Handler handler, String[] white, String[] black)
|
||||
{
|
||||
setHandler(handler);
|
||||
set(white, _white);
|
||||
set(black, _black);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the timeout, in milliseconds, to connect to the remote server
|
||||
*/
|
||||
|
@ -208,6 +224,12 @@ public class ProxyHandler extends HandlerWrapper
|
|||
host = serverAddress.substring(0, colon);
|
||||
port = Integer.parseInt(serverAddress.substring(colon + 1));
|
||||
}
|
||||
|
||||
String uri = request.getRequestURI();
|
||||
if (validateDestination(host, uri))
|
||||
{
|
||||
throw new ServletException("Forbidden: "+host+uri);
|
||||
}
|
||||
|
||||
SocketChannel channel = connectToServer(request, host, port);
|
||||
|
||||
|
@ -705,4 +727,137 @@ public class ProxyHandler extends HandlerWrapper
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Add a whitelist entry to an existing handler configuration
|
||||
*
|
||||
* @param entry new whitelist entry
|
||||
*/
|
||||
public void addWhite(String entry)
|
||||
{
|
||||
add(entry, _white);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Add a blacklist entry to an existing handler configuration
|
||||
*
|
||||
* @param entry new blacklist entry
|
||||
*/
|
||||
public void addBlack(String entry)
|
||||
{
|
||||
add(entry, _black);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Re-initialize the whitelist of existing handler object
|
||||
*
|
||||
* @param entries array of whitelist entries
|
||||
*/
|
||||
public void setWhite(String[] entries)
|
||||
{
|
||||
set(entries, _white);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Re-initialize the blacklist of existing handler object
|
||||
*
|
||||
* @param entries array of blacklist entries
|
||||
*/
|
||||
public void setBlack(String[] entries)
|
||||
{
|
||||
set(entries, _black);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Helper method to process a list of new entries and replace
|
||||
* the content of the specified host map
|
||||
*
|
||||
* @param entries new entries
|
||||
* @param patternMap target host map
|
||||
*/
|
||||
protected void set(String[] entries, HostMap<PathMap> hostMap)
|
||||
{
|
||||
hostMap.clear();
|
||||
|
||||
for (String addrPath:entries)
|
||||
{
|
||||
add(addrPath, hostMap);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Helper method to parse the new entry and add it to
|
||||
* the specified host map.
|
||||
*
|
||||
* @param entry new entry
|
||||
* @param patternMap target host map
|
||||
*/
|
||||
private void add(String entry, HostMap<PathMap> hostMap)
|
||||
{
|
||||
if (entry != null && entry.length() > 0)
|
||||
{
|
||||
int idx = entry.indexOf('/');
|
||||
|
||||
String host = idx > 0 ? entry.substring(0,idx) : entry;
|
||||
String path = idx > 0 ? entry.substring(idx) : "/*";
|
||||
|
||||
host = host.trim();
|
||||
PathMap pathMap = hostMap.get(host);
|
||||
if (pathMap == null)
|
||||
{
|
||||
pathMap = new PathMap(true);
|
||||
hostMap.put(host,pathMap);
|
||||
}
|
||||
if (path != null)
|
||||
pathMap.put(path,path);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validateDestination(String host, String path)
|
||||
{
|
||||
if (_white.size()>0)
|
||||
{
|
||||
boolean match = false;
|
||||
|
||||
Object whiteObj = _white.getLazyMatches(host);
|
||||
if (whiteObj != null)
|
||||
{
|
||||
List whiteList = (whiteObj instanceof List) ? (List)whiteObj : Collections.singletonList(whiteObj);
|
||||
|
||||
for (Object entry: whiteList)
|
||||
{
|
||||
PathMap pathMap = ((Map.Entry<String, PathMap>)entry).getValue();
|
||||
if (match = (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_black.size() > 0)
|
||||
{
|
||||
Object blackObj = _black.getLazyMatches(host);
|
||||
if (blackObj != null)
|
||||
{
|
||||
List blackList = (blackObj instanceof List) ? (List)blackObj : Collections.singletonList(blackObj);
|
||||
|
||||
for (Object entry: blackList)
|
||||
{
|
||||
PathMap pathMap = ((Map.Entry<String, PathMap>)entry).getValue();
|
||||
if (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,14 @@ import java.net.MalformedURLException;
|
|||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -42,8 +48,10 @@ import org.eclipse.jetty.http.HttpHeaderValues;
|
|||
import org.eclipse.jetty.http.HttpHeaders;
|
||||
import org.eclipse.jetty.http.HttpSchemes;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.PathMap;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.util.HostMap;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -72,8 +80,8 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|||
public class ProxyServlet implements Servlet
|
||||
{
|
||||
protected Logger _log;
|
||||
HttpClient _client;
|
||||
String _hostHeader;
|
||||
protected HttpClient _client;
|
||||
protected String _hostHeader;
|
||||
|
||||
protected HashSet<String> _DontProxyHeaders = new HashSet<String>();
|
||||
{
|
||||
|
@ -90,6 +98,8 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
protected ServletConfig _config;
|
||||
protected ServletContext _context;
|
||||
protected HostMap<PathMap> _white = new HostMap<PathMap>();
|
||||
protected HostMap<PathMap> _black = new HostMap<PathMap>();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
|
@ -129,6 +139,17 @@ public class ProxyServlet implements Servlet
|
|||
_context.setAttribute(config.getServletName()+".ThreadPool",_client.getThreadPool());
|
||||
_context.setAttribute(config.getServletName()+".HttpClient",_client);
|
||||
}
|
||||
|
||||
String white = config.getInitParameter("whiteList");
|
||||
if (white != null)
|
||||
{
|
||||
parseList(white, _white);
|
||||
}
|
||||
String black = config.getInitParameter("blackList");
|
||||
if (black != null)
|
||||
{
|
||||
parseList(black, _black);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -136,6 +157,74 @@ public class ProxyServlet implements Servlet
|
|||
}
|
||||
}
|
||||
|
||||
private void parseList(String list, HostMap<PathMap> hostMap)
|
||||
{
|
||||
int idx;
|
||||
String entry;
|
||||
|
||||
StringTokenizer entries = new StringTokenizer(list, ",");
|
||||
while(entries.hasMoreTokens())
|
||||
{
|
||||
entry = entries.nextToken();
|
||||
idx = entry.indexOf('/');
|
||||
|
||||
String host = idx > 0 ? entry.substring(0,idx) : entry;
|
||||
String path = idx > 0 ? entry.substring(idx) : "/*";
|
||||
|
||||
host = host.trim();
|
||||
PathMap pathMap = hostMap.get(host);
|
||||
if (pathMap == null)
|
||||
{
|
||||
pathMap = new PathMap(true);
|
||||
hostMap.put(host,pathMap);
|
||||
}
|
||||
if (path != null)
|
||||
pathMap.put(path,path);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validateDestination(String host, String path)
|
||||
{
|
||||
if (_white.size()>0)
|
||||
{
|
||||
boolean match = false;
|
||||
|
||||
Object whiteObj = _white.getLazyMatches(host);
|
||||
if (whiteObj != null)
|
||||
{
|
||||
List whiteList = (whiteObj instanceof List) ? (List)whiteObj : Collections.singletonList(whiteObj);
|
||||
|
||||
for (Object entry: whiteList)
|
||||
{
|
||||
PathMap pathMap = ((Map.Entry<String, PathMap>)entry).getValue();
|
||||
if (match = (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_black.size() > 0)
|
||||
{
|
||||
Object blackObj = _black.getLazyMatches(host);
|
||||
if (blackObj != null)
|
||||
{
|
||||
List blackList = (blackObj instanceof List) ? (List)blackObj : Collections.singletonList(blackObj);
|
||||
|
||||
for (Object entry: blackList)
|
||||
{
|
||||
PathMap pathMap = ((Map.Entry<String, PathMap>)entry).getValue();
|
||||
if (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.Servlet#getServletConfig()
|
||||
|
@ -423,6 +512,9 @@ public class ProxyServlet implements Servlet
|
|||
protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri)
|
||||
throws MalformedURLException
|
||||
{
|
||||
if (!validateDestination(serverName, uri))
|
||||
return null;
|
||||
|
||||
return new HttpURI(scheme+"://"+serverName+":"+serverPort+uri);
|
||||
}
|
||||
|
||||
|
@ -517,8 +609,13 @@ public class ProxyServlet implements Servlet
|
|||
{
|
||||
if (!uri.startsWith(_prefix))
|
||||
return null;
|
||||
|
||||
URI dstUri = new URI(_proxyTo + uri.substring(_prefix.length())).normalize();
|
||||
|
||||
if (!validateDestination(dstUri.getHost(),dstUri.getPath()))
|
||||
return null;
|
||||
|
||||
return new HttpURI(new URI(_proxyTo + uri.substring(_prefix.length())).normalize().toString());
|
||||
return new HttpURI(dstUri.toString());
|
||||
}
|
||||
catch (URISyntaxException ex)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class HostMap<TYPE> extends HashMap<String, TYPE>
|
||||
{
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Construct empty HostMap.
|
||||
*/
|
||||
public HostMap()
|
||||
{
|
||||
super(11);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Construct empty HostMap.
|
||||
*
|
||||
* @param capacity initial capacity
|
||||
*/
|
||||
public HostMap(int capacity)
|
||||
{
|
||||
super (capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TYPE put(String host, TYPE object)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
return super.put(host, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TYPE get(Object key)
|
||||
{
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
public Object getLazyMatches(String host)
|
||||
{
|
||||
if (host == null)
|
||||
return LazyList.getList(super.entrySet());
|
||||
|
||||
int idx = 0;
|
||||
String domain = host.trim();
|
||||
HashSet<String> domains = new HashSet<String>();
|
||||
do {
|
||||
domains.add(domain);
|
||||
if ((idx = domain.indexOf('.')) > 0)
|
||||
{
|
||||
domain = domain.substring(idx+1);
|
||||
}
|
||||
} while (idx > 0);
|
||||
|
||||
Object entries = null;
|
||||
for(Map.Entry<String, TYPE> entry: super.entrySet())
|
||||
{
|
||||
if (domains.contains(entry.getKey()))
|
||||
{
|
||||
entries = LazyList.add(entries,entry);
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
}
|
|
@ -49,7 +49,7 @@ public class IPAddressMap<TYPE> extends HashMap<String, TYPE>
|
|||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Construct empty AddrPatternMap.
|
||||
/** Construct empty IPAddressMap.
|
||||
*
|
||||
* @param capacity initial capacity
|
||||
*/
|
||||
|
@ -84,10 +84,6 @@ public class IPAddressMap<TYPE> extends HashMap<String, TYPE>
|
|||
*
|
||||
* @see java.util.HashMap#get(java.lang.Object)
|
||||
*/
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.util.HashMap#get(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public TYPE get(Object key)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue