Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project
This commit is contained in:
commit
12b04e4e7f
|
@ -24,7 +24,7 @@
|
|||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includes>META-INF/**,org/eclipse/**</includes>
|
||||
<includes>META-INF/**,org/eclipse/**,org/apache/jasper/compiler/**</includes>
|
||||
<excludes>**/MANIFEST.MF,javax/**</excludes>
|
||||
<outputDirectory>${project.build.directory}/classes</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includes>META-INF/**,org/eclipse/**</includes>
|
||||
<includes>META-INF/**,org/eclipse/**,org/apache/jasper/compiler/*</includes>
|
||||
<excludes>**/MANIFEST.MF,javax/**</excludes>
|
||||
<outputDirectory>${project.build.directory}/classes</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includes>META-INF/**,org/eclipse/**</includes>
|
||||
<includes>META-INF/**,org/eclipse/**,org/apache/jasper/compiler/**</includes>
|
||||
<excludes>**/MANIFEST.MF,javax/**</excludes>
|
||||
<outputDirectory>${project.build.directory}/classes</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
|
|
|
@ -29,4 +29,12 @@ public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
|
|||
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
|
||||
_port = _server.getConnectors()[0].getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testPerf() throws Exception
|
||||
{
|
||||
super.testPerf();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// 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
|
||||
// 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.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.http;
|
||||
|
@ -34,7 +34,7 @@ import org.eclipse.jetty.util.URIUtil;
|
|||
* /foo/bar - an exact path specification.
|
||||
* /foo/* - a prefix path specification (must end '/*').
|
||||
* *.ext - a suffix path specification.
|
||||
* / - the default path specification.
|
||||
* / - the default path specification.
|
||||
* </PRE>
|
||||
* Matching is performed in the following order <NL>
|
||||
* <LI>Exact match.
|
||||
|
@ -43,24 +43,24 @@ import org.eclipse.jetty.util.URIUtil;
|
|||
* <LI>default.
|
||||
* </NL>
|
||||
* Multiple path specifications can be mapped by providing a list of
|
||||
* specifications. By default this class uses characters ":," as path
|
||||
* separators, unless configured differently by calling the static
|
||||
* method @see PathMap#setPathSpecSeparators(String)
|
||||
* specifications. By default this class uses characters ":," as path
|
||||
* separators, unless configured differently by calling the static
|
||||
* method @see PathMap#setPathSpecSeparators(String)
|
||||
* <P>
|
||||
* Special characters within paths such as '?<EFBFBD> and ';' are not treated specially
|
||||
* as it is assumed they would have been either encoded in the original URL or
|
||||
* as it is assumed they would have been either encoded in the original URL or
|
||||
* stripped from the path.
|
||||
* <P>
|
||||
* This class is not synchronized. If concurrent modifications are
|
||||
* possible then it should be synchronized at a higher level.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class PathMap extends HashMap implements Externalizable
|
||||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
private static String __pathSpecSeparators = ":,";
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the path spec separator.
|
||||
* Multiple path specification may be included in a single string
|
||||
|
@ -72,7 +72,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
{
|
||||
__pathSpecSeparators=s;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
final StringMap _prefixMap=new StringMap();
|
||||
final StringMap _suffixMap=new StringMap();
|
||||
|
@ -83,7 +83,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
Entry _default=null;
|
||||
final Set _entrySet;
|
||||
boolean _nodefault=false;
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Construct empty PathMap.
|
||||
*/
|
||||
|
@ -102,7 +102,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
_entrySet=entrySet();
|
||||
_nodefault=nodefault;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Construct empty PathMap.
|
||||
*/
|
||||
|
@ -111,7 +111,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
super (capacity);
|
||||
_entrySet=entrySet();
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Construct from dictionary PathMap.
|
||||
*/
|
||||
|
@ -120,7 +120,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
putAll(m);
|
||||
_entrySet=entrySet();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void writeExternal(java.io.ObjectOutput out)
|
||||
throws java.io.IOException
|
||||
|
@ -128,7 +128,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
HashMap map = new HashMap(this);
|
||||
out.writeObject(map);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void readExternal(java.io.ObjectInput in)
|
||||
throws java.io.IOException, ClassNotFoundException
|
||||
|
@ -136,7 +136,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
HashMap map = (HashMap)in.readObject();
|
||||
this.putAll(map);
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Add a single path match to the PathMap.
|
||||
* @param pathSpec The path specification, or comma separated list of
|
||||
|
@ -148,16 +148,16 @@ public class PathMap extends HashMap implements Externalizable
|
|||
{
|
||||
StringTokenizer tok = new StringTokenizer(pathSpec.toString(),__pathSpecSeparators);
|
||||
Object old =null;
|
||||
|
||||
|
||||
while (tok.hasMoreTokens())
|
||||
{
|
||||
String spec=tok.nextToken();
|
||||
|
||||
|
||||
if (!spec.startsWith("/") && !spec.startsWith("*."))
|
||||
throw new IllegalArgumentException("PathSpec "+spec+". must start with '/' or '*.'");
|
||||
|
||||
|
||||
old = super.put(spec,object);
|
||||
|
||||
|
||||
// Make entry that was just created.
|
||||
Entry entry = new Entry(spec,object);
|
||||
|
||||
|
@ -176,7 +176,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
else if (spec.startsWith("*."))
|
||||
_suffixMap.put(spec.substring(2),entry);
|
||||
else if (spec.equals(URIUtil.SLASH))
|
||||
{
|
||||
{
|
||||
if (_nodefault)
|
||||
_exactMap.put(spec,entry);
|
||||
else
|
||||
|
@ -193,7 +193,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
|
@ -209,8 +209,8 @@ public class PathMap extends HashMap implements Externalizable
|
|||
return entry.getValue();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Get the entry mapped by the best specification.
|
||||
* @param path the path.
|
||||
|
@ -222,14 +222,14 @@ public class PathMap extends HashMap implements Externalizable
|
|||
|
||||
if (path==null)
|
||||
return null;
|
||||
|
||||
int l=path.length();
|
||||
|
||||
int l=path.length();
|
||||
|
||||
// try exact match
|
||||
entry=_exactMap.getEntry(path,0,l);
|
||||
if (entry!=null)
|
||||
return (Entry) entry.getValue();
|
||||
|
||||
|
||||
// prefix search
|
||||
int i=l;
|
||||
while((i=path.lastIndexOf('/',i-1))>=0)
|
||||
|
@ -238,11 +238,11 @@ public class PathMap extends HashMap implements Externalizable
|
|||
if (entry!=null)
|
||||
return (Entry) entry.getValue();
|
||||
}
|
||||
|
||||
|
||||
// Prefix Default
|
||||
if (_prefixDefault!=null)
|
||||
return _prefixDefault;
|
||||
|
||||
|
||||
// Extension search
|
||||
i=0;
|
||||
while ((i=path.indexOf('.',i+1))>0)
|
||||
|
@ -250,12 +250,12 @@ public class PathMap extends HashMap implements Externalizable
|
|||
entry=_suffixMap.getEntry(path,i+1,l-i-1);
|
||||
if (entry!=null)
|
||||
return (Entry) entry.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Default
|
||||
return _default;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Get all entries matched by the path.
|
||||
* Best match first.
|
||||
|
@ -263,20 +263,20 @@ public class PathMap extends HashMap implements Externalizable
|
|||
* @return LazyList of Map.Entry instances key=pathSpec
|
||||
*/
|
||||
public Object getLazyMatches(String path)
|
||||
{
|
||||
{
|
||||
Map.Entry entry;
|
||||
Object entries=null;
|
||||
|
||||
if (path==null)
|
||||
return LazyList.getList(entries);
|
||||
|
||||
|
||||
int l=path.length();
|
||||
|
||||
// try exact match
|
||||
entry=_exactMap.getEntry(path,0,l);
|
||||
if (entry!=null)
|
||||
entries=LazyList.add(entries,entry.getValue());
|
||||
|
||||
|
||||
// prefix search
|
||||
int i=l-1;
|
||||
while((i=path.lastIndexOf('/',i-1))>=0)
|
||||
|
@ -285,11 +285,11 @@ public class PathMap extends HashMap implements Externalizable
|
|||
if (entry!=null)
|
||||
entries=LazyList.add(entries,entry.getValue());
|
||||
}
|
||||
|
||||
|
||||
// Prefix Default
|
||||
if (_prefixDefault!=null)
|
||||
entries=LazyList.add(entries,_prefixDefault);
|
||||
|
||||
|
||||
// Extension search
|
||||
i=0;
|
||||
while ((i=path.indexOf('.',i+1))>0)
|
||||
|
@ -305,13 +305,13 @@ public class PathMap extends HashMap implements Externalizable
|
|||
// Optimization for just the default
|
||||
if (entries==null)
|
||||
return _defaultSingletonList;
|
||||
|
||||
|
||||
entries=LazyList.add(entries,_default);
|
||||
}
|
||||
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Get all entries matched by the path.
|
||||
* Best match first.
|
||||
|
@ -319,7 +319,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
* @return List of Map.Entry instances key=pathSpec
|
||||
*/
|
||||
public List getMatches(String path)
|
||||
{
|
||||
{
|
||||
return LazyList.getList(getLazyMatches(path));
|
||||
}
|
||||
|
||||
|
@ -330,12 +330,12 @@ public class PathMap extends HashMap implements Externalizable
|
|||
* @return Whether the PathMap contains any entries that match this
|
||||
*/
|
||||
public boolean containsMatch(String path)
|
||||
{
|
||||
{
|
||||
Entry match = getMatch(path);
|
||||
return match!=null && !match.equals(_default);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/* --------------------------------------------------------------- */
|
||||
@Override
|
||||
public Object remove(Object pathSpec)
|
||||
{
|
||||
|
@ -362,7 +362,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
}
|
||||
return super.remove(pathSpec);
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
@Override
|
||||
public void clear()
|
||||
|
@ -374,7 +374,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
_defaultSingletonList=null;
|
||||
super.clear();
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/**
|
||||
* @return true if match.
|
||||
|
@ -397,7 +397,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
{
|
||||
if (!noDefault && pathSpec.length()==1 || pathSpec.equals(path))
|
||||
return true;
|
||||
|
||||
|
||||
if(isPathWildcardMatch(pathSpec, path))
|
||||
return true;
|
||||
}
|
||||
|
@ -419,24 +419,24 @@ public class PathMap extends HashMap implements Externalizable
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Return the portion of a path that matches a path spec.
|
||||
* @return null if no match at all.
|
||||
*/
|
||||
public static String pathMatch(String pathSpec, String path)
|
||||
{
|
||||
{
|
||||
char c = pathSpec.charAt(0);
|
||||
|
||||
|
||||
if (c=='/')
|
||||
{
|
||||
if (pathSpec.length()==1)
|
||||
return path;
|
||||
|
||||
|
||||
if (pathSpec.equals(path))
|
||||
return path;
|
||||
|
||||
|
||||
if (isPathWildcardMatch(pathSpec, path))
|
||||
return path.substring(0,pathSpec.length()-2);
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
/** Return the portion of a path that is after a path spec.
|
||||
* @return The path info string
|
||||
|
@ -456,12 +456,12 @@ public class PathMap extends HashMap implements Externalizable
|
|||
public static String pathInfo(String pathSpec, String path)
|
||||
{
|
||||
char c = pathSpec.charAt(0);
|
||||
|
||||
|
||||
if (c=='/')
|
||||
{
|
||||
if (pathSpec.length()==1)
|
||||
return null;
|
||||
|
||||
|
||||
boolean wildcard = isPathWildcardMatch(pathSpec, path);
|
||||
|
||||
// handle the case where pathSpec uses a wildcard and path info is "/*"
|
||||
|
@ -474,7 +474,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
return null;
|
||||
return path.substring(pathSpec.length()-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -484,7 +484,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
* @param base The base the path is relative to.
|
||||
* @param pathSpec The spec of the path segment to ignore.
|
||||
* @param path the additional path
|
||||
* @return base plus path with pathspec removed
|
||||
* @return base plus path with pathspec removed
|
||||
*/
|
||||
public static String relativePath(String base,
|
||||
String pathSpec,
|
||||
|
@ -508,7 +508,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
path = base + URIUtil.SLASH + info;
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -516,7 +516,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
{
|
||||
private final Object key;
|
||||
private final Object value;
|
||||
private String mapped;
|
||||
private String mapped;
|
||||
private transient String string;
|
||||
|
||||
Entry(Object key, Object value)
|
||||
|
@ -529,7 +529,7 @@ public class PathMap extends HashMap implements Externalizable
|
|||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
public Object getValue()
|
||||
{
|
||||
return value;
|
||||
|
|
|
@ -206,6 +206,141 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
}
|
||||
}
|
||||
|
||||
private int process() throws IOException
|
||||
{
|
||||
ByteBuffer bbuf = null; // TODO ???
|
||||
|
||||
int wraps=0;
|
||||
|
||||
HandshakeStatus initialStatus = _engine.getHandshakeStatus();
|
||||
loop: while (true)
|
||||
{
|
||||
// If we have encrypted data in output buffer
|
||||
if (isBufferingOutput())
|
||||
{
|
||||
// we must flush it, as the other end might be
|
||||
// waiting for that outgoing data before sending
|
||||
// more incoming data
|
||||
flush();
|
||||
|
||||
// If we were unable to flush all the data, then
|
||||
// we should break the loop and wait for the call
|
||||
// back to handle when the SelectSet detects that
|
||||
// the channel is writable again.
|
||||
if (isBufferingOutput())
|
||||
{
|
||||
scheduleWrite();
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
|
||||
// handle the current hand share status
|
||||
switch(_engine.getHandshakeStatus())
|
||||
{
|
||||
case FINISHED:
|
||||
case NOT_HANDSHAKING:
|
||||
// If we are closing, then unwrap must have CLOSED result,
|
||||
// so return -1 to signal upwards
|
||||
if (_closing)
|
||||
return -1;
|
||||
|
||||
// otherwise we break loop with the data we have unwrapped.
|
||||
break loop;
|
||||
|
||||
case NEED_UNWRAP:
|
||||
checkRenegotiate();
|
||||
// Need more data to be unwrapped so try another call to unwrap
|
||||
if (!unwrap(bbuf) && _engine.getHandshakeStatus()==HandshakeStatus.NEED_UNWRAP)
|
||||
{
|
||||
// If the unwrap call did not make any progress and we are still in
|
||||
// NEED_UNWRAP, then we should break the loop and wait for more data to
|
||||
// arrive.
|
||||
break loop;
|
||||
}
|
||||
// progress was made so continue the loop.
|
||||
break;
|
||||
|
||||
case NEED_TASK:
|
||||
{
|
||||
// A task needs to be run, so run it!
|
||||
|
||||
Runnable task;
|
||||
while ((task=_engine.getDelegatedTask())!=null)
|
||||
{
|
||||
task.run();
|
||||
}
|
||||
|
||||
// Detect SUN JVM Bug!!!
|
||||
if(initialStatus==HandshakeStatus.NOT_HANDSHAKING &&
|
||||
_engine.getHandshakeStatus()==HandshakeStatus.NEED_UNWRAP && wraps==0)
|
||||
{
|
||||
// This should be NEED_WRAP
|
||||
// The fix simply detects the signature of the bug and then close the connection (fail-fast) so that ff3 will delegate to using SSL instead of TLS.
|
||||
// This is a jvm bug on java1.6 where the SSLEngine expects more data from the initial handshake when the client(ff3-tls) already had given it.
|
||||
// See http://jira.codehaus.org/browse/JETTY-567 for more details
|
||||
if (_debug) __log.warn(_session+" JETTY-567");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case NEED_WRAP:
|
||||
{
|
||||
checkRenegotiate();
|
||||
// The SSL needs to send some handshake data to the other side,
|
||||
// so let fill become a flush for a little bit.
|
||||
wraps++;
|
||||
needOutBuffer();
|
||||
ByteBuffer out_buffer=_outNIOBuffer.getByteBuffer();
|
||||
synchronized(out_buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
// call wrap with empty application buffers, so it can
|
||||
// generate required handshake messages into _outNIOBuffer
|
||||
_outNIOBuffer.compact();
|
||||
int put=_outNIOBuffer.putIndex();
|
||||
out_buffer.position();
|
||||
_result=null;
|
||||
_result=_engine.wrap(__NO_BUFFERS,out_buffer);
|
||||
if (_debug) __log.debug(_session+" fill wrap "+_result);
|
||||
switch(_result.getStatus())
|
||||
{
|
||||
case BUFFER_OVERFLOW:
|
||||
case BUFFER_UNDERFLOW:
|
||||
LOG.warn("wrap {}",_result);
|
||||
_closing=true;
|
||||
break;
|
||||
case CLOSED:
|
||||
_closing=true;
|
||||
break;
|
||||
}
|
||||
_outNIOBuffer.setPutIndex(put+_result.bytesProduced());
|
||||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
super.close();
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
out_buffer.position(0);
|
||||
}
|
||||
}
|
||||
|
||||
// flush the encrypted outNIOBuffer
|
||||
flush();
|
||||
freeOutBuffer();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // TODO
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void sslClose() throws IOException
|
||||
{
|
||||
|
@ -650,24 +785,25 @@ public class SslSelectChannelEndPoint extends SelectChannelEndPoint
|
|||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
if (_outNIOBuffer==null)
|
||||
return;
|
||||
|
||||
int len=_outNIOBuffer.length();
|
||||
{
|
||||
if (isBufferingOutput())
|
||||
{
|
||||
int flushed=super.flush(_outNIOBuffer);
|
||||
if (_debug) __log.debug(_session+" Flushed "+flushed+"/"+len);
|
||||
if (isBufferingOutput())
|
||||
if (_debug)
|
||||
__log.debug(_session+" Flushed "+flushed+" left="+_outNIOBuffer.length());
|
||||
}
|
||||
else if (_closing)
|
||||
{
|
||||
if (_engine.isOutboundDone())
|
||||
{
|
||||
// Try again after yield.... cheaper than a reschedule.
|
||||
Thread.yield();
|
||||
flushed=super.flush(_outNIOBuffer);
|
||||
if (_debug) __log.debug(_session+" flushed "+flushed+"/"+len);
|
||||
if (_debug)
|
||||
__log.debug(_session+" close");
|
||||
super.close();
|
||||
}
|
||||
else if (_closing && !_engine.isOutboundDone())
|
||||
else
|
||||
{
|
||||
if (_debug)
|
||||
__log.debug(_session+" closeOutbound");
|
||||
_engine.closeOutbound();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,54 @@
|
|||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.glassfish.web</groupId>
|
||||
<artifactId>jsp-impl</artifactId>
|
||||
<version>2.1.3-b10</version>
|
||||
<type>jar</type>
|
||||
<classifier>sources</classifier>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>target/generated-sources</outputDirectory>
|
||||
<includes>**/JDTJavaCompiler.java</includes>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-source</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>target/generated-sources</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
|
@ -26,14 +74,12 @@
|
|||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Import-Package>
|
||||
com.sun.org.apache.commons.logging;version="[2.1,3)";glassfish="split",
|
||||
<Import-Package>
|
||||
org.apache.jasper;version="[2.1,3)";glassfish="split",
|
||||
*
|
||||
</Import-Package>
|
||||
<Export-Package>org.eclipse.jetty*;version="${parsedVersion.osgiVersion}"</Export-Package>
|
||||
<Fragment-Host>org.apache.jasper.glassfish</Fragment-Host>
|
||||
<!-- disable the uses directive: we don't want to fore eeryone that uses us to
|
||||
have to depend on com.sun.org.apache.commons.logging provided by jasper-glassfish. -->
|
||||
</Import-Package>
|
||||
<Export-Package>org.apache.jasper*;version="${parsedVersion.osgiVersion}"</Export-Package>
|
||||
<Fragment-Host>org.apache.jasper.glassfish</Fragment-Host>
|
||||
<_nouses>true</_nouses>
|
||||
</instructions>
|
||||
</configuration>
|
||||
|
@ -61,20 +107,10 @@
|
|||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jsp-2.1-glassfish</artifactId>
|
||||
<version>${javax-servlet-jsp-version}</version>
|
||||
<groupId>org.glassfish.web</groupId>
|
||||
<artifactId>jsp-impl</artifactId>
|
||||
<version>2.1.3-b10</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
@ -83,5 +119,11 @@
|
|||
<artifactId>servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jdt.core.compiler</groupId>
|
||||
<artifactId>ecj</artifactId>
|
||||
<version>3.7</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
package org.eclipse.jetty.jsp;
|
||||
|
||||
import com.sun.org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
public class JettyLog implements com.sun.org.apache.commons.logging.Log
|
||||
{
|
||||
private static volatile boolean __initialized;
|
||||
|
||||
/**
|
||||
* Called via reflection from WebXmlProcessor
|
||||
*/
|
||||
public static synchronized void init()
|
||||
{
|
||||
if (!__initialized)
|
||||
{
|
||||
__initialized = true;
|
||||
LogFactory.setLogImplClassName(JettyLog.class.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private final Logger _logger;
|
||||
|
||||
public JettyLog(String name)
|
||||
{
|
||||
_logger = Log.getLogger(name);
|
||||
}
|
||||
|
||||
public void fatal(Object o)
|
||||
{
|
||||
error(o);
|
||||
}
|
||||
|
||||
public void fatal(Object o, Throwable throwable)
|
||||
{
|
||||
error(o, throwable);
|
||||
}
|
||||
|
||||
public boolean isErrorEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void error(Object o)
|
||||
{
|
||||
warn(o);
|
||||
}
|
||||
|
||||
public void error(Object o, Throwable throwable)
|
||||
{
|
||||
_logger.warn(String.valueOf(o), throwable);
|
||||
}
|
||||
|
||||
public boolean isWarnEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void warn(Object o)
|
||||
{
|
||||
_logger.warn(String.valueOf(o));
|
||||
}
|
||||
|
||||
public boolean isInfoEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void info(Object o)
|
||||
{
|
||||
_logger.info(String.valueOf(o));
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled()
|
||||
{
|
||||
return _logger.isDebugEnabled();
|
||||
}
|
||||
|
||||
public void debug(Object o)
|
||||
{
|
||||
_logger.debug(String.valueOf(o));
|
||||
}
|
||||
|
||||
public void debug(Object o, Throwable throwable)
|
||||
{
|
||||
_logger.debug(String.valueOf(o), throwable);
|
||||
}
|
||||
|
||||
public boolean isTraceEnabled()
|
||||
{
|
||||
return isDebugEnabled();
|
||||
}
|
||||
|
||||
public void trace(Object o)
|
||||
{
|
||||
debug(o);
|
||||
}
|
||||
}
|
|
@ -74,6 +74,11 @@
|
|||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
|
|
|
@ -0,0 +1,487 @@
|
|||
package org.eclipse.jetty.rewrite.handler;
|
||||
|
||||
//========================================================================
|
||||
//Copyright (c) 2006-2009 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.
|
||||
//========================================================================
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpExchange;
|
||||
import org.eclipse.jetty.http.HttpHeaderValues;
|
||||
import org.eclipse.jetty.http.HttpHeaders;
|
||||
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.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
|
||||
/**
|
||||
* This rule allows the user to configure a particular rewrite rule that will proxy out
|
||||
* to a configured location. This rule uses the jetty http client.
|
||||
*
|
||||
* Rule rule = new ProxyRule();
|
||||
* rule.setPattern("/foo/*");
|
||||
* rule.setProxyTo("http://url.com");
|
||||
*
|
||||
* see api for other configuration options which influence the configuration of the jetty
|
||||
* client instance
|
||||
*
|
||||
*/
|
||||
public class ProxyRule extends PatternRule
|
||||
{
|
||||
private static final Logger _log = Log.getLogger(ProxyRule.class);
|
||||
|
||||
private HttpClient _client;
|
||||
private String _hostHeader;
|
||||
private String _proxyTo;
|
||||
|
||||
private int _connectorType = 2;
|
||||
private String _maxThreads;
|
||||
private String _maxConnections;
|
||||
private String _timeout;
|
||||
private String _idleTimeout;
|
||||
private String _requestHeaderSize;
|
||||
private String _requestBufferSize;
|
||||
private String _responseHeaderSize;
|
||||
private String _responseBufferSize;
|
||||
|
||||
private HashSet<String> _DontProxyHeaders = new HashSet<String>();
|
||||
{
|
||||
_DontProxyHeaders.add("proxy-connection");
|
||||
_DontProxyHeaders.add("connection");
|
||||
_DontProxyHeaders.add("keep-alive");
|
||||
_DontProxyHeaders.add("transfer-encoding");
|
||||
_DontProxyHeaders.add("te");
|
||||
_DontProxyHeaders.add("trailer");
|
||||
_DontProxyHeaders.add("proxy-authorization");
|
||||
_DontProxyHeaders.add("proxy-authenticate");
|
||||
_DontProxyHeaders.add("upgrade");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ProxyRule()
|
||||
{
|
||||
_handling = true;
|
||||
_terminating = true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void initializeClient() throws Exception
|
||||
{
|
||||
_client = new HttpClient();
|
||||
_client.setConnectorType(_connectorType);
|
||||
|
||||
if ( _maxThreads != null )
|
||||
{
|
||||
_client.setThreadPool(new QueuedThreadPool(Integer.parseInt(_maxThreads)));
|
||||
}
|
||||
else
|
||||
{
|
||||
_client.setThreadPool(new QueuedThreadPool());
|
||||
}
|
||||
|
||||
if ( _maxConnections != null )
|
||||
{
|
||||
_client.setMaxConnectionsPerAddress(Integer.parseInt(_maxConnections));
|
||||
}
|
||||
|
||||
if ( _timeout != null )
|
||||
{
|
||||
_client.setTimeout(Long.parseLong(_timeout));
|
||||
}
|
||||
|
||||
if ( _idleTimeout != null )
|
||||
{
|
||||
_client.setIdleTimeout(Long.parseLong(_idleTimeout));
|
||||
}
|
||||
|
||||
if ( _requestBufferSize != null )
|
||||
{
|
||||
_client.setRequestBufferSize(Integer.parseInt(_requestBufferSize));
|
||||
}
|
||||
|
||||
if ( _requestHeaderSize != null )
|
||||
{
|
||||
_client.setRequestHeaderSize(Integer.parseInt(_requestHeaderSize));
|
||||
}
|
||||
|
||||
if ( _responseBufferSize != null )
|
||||
{
|
||||
_client.setResponseBufferSize(Integer.parseInt(_responseBufferSize));
|
||||
}
|
||||
|
||||
if ( _responseHeaderSize != null )
|
||||
{
|
||||
_client.setResponseHeaderSize(Integer.parseInt(_responseHeaderSize));
|
||||
}
|
||||
|
||||
_client.start();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private HttpURI proxyHttpURI(String uri) throws MalformedURLException
|
||||
{
|
||||
return new HttpURI(_proxyTo + uri);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected String apply(String target, HttpServletRequest request, final HttpServletResponse response) throws IOException
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (_client == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
initializeClient();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IOException("Unable to proxy: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int debug = _log.isDebugEnabled()?request.hashCode():0;
|
||||
|
||||
final InputStream in = request.getInputStream();
|
||||
final OutputStream out = response.getOutputStream();
|
||||
|
||||
HttpURI url = createUrl(request,debug);
|
||||
|
||||
if (url == null)
|
||||
{
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
return target;
|
||||
}
|
||||
|
||||
HttpExchange exchange = new HttpExchange()
|
||||
{
|
||||
@Override
|
||||
protected void onRequestCommitted() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRequestComplete() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseComplete() throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
_log.debug(debug + " complete");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseContent(Buffer content) throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
_log.debug(debug + " content" + content.length());
|
||||
content.writeTo(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseHeaderComplete() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
_log.debug(debug + " " + version + " " + status + " " + reason);
|
||||
|
||||
if (reason != null && reason.length() > 0)
|
||||
response.setStatus(status,reason.toString());
|
||||
else
|
||||
response.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
String s = name.toString().toLowerCase();
|
||||
if (!_DontProxyHeaders.contains(s) || (HttpHeaders.CONNECTION_BUFFER.equals(name) && HttpHeaderValues.CLOSE_BUFFER.equals(value)))
|
||||
{
|
||||
if (debug != 0)
|
||||
_log.debug(debug + " " + name + ": " + value);
|
||||
|
||||
response.addHeader(name.toString(),value.toString());
|
||||
}
|
||||
else if (debug != 0)
|
||||
_log.debug(debug + " " + name + "! " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConnectionFailed(Throwable ex)
|
||||
{
|
||||
_log.warn(ex.toString());
|
||||
_log.debug(ex);
|
||||
if (!response.isCommitted())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Throwable ex)
|
||||
{
|
||||
if (ex instanceof EofException)
|
||||
{
|
||||
_log.ignore(ex);
|
||||
return;
|
||||
}
|
||||
_log.warn(ex.toString());
|
||||
_log.debug(ex);
|
||||
if (!response.isCommitted())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExpire()
|
||||
{
|
||||
if (!response.isCommitted())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
exchange.setMethod(request.getMethod());
|
||||
exchange.setURL(url.toString());
|
||||
exchange.setVersion(request.getProtocol());
|
||||
|
||||
if (debug != 0)
|
||||
{
|
||||
_log.debug(debug + " " + request.getMethod() + " " + url + " " + request.getProtocol());
|
||||
}
|
||||
|
||||
boolean hasContent = createHeaders(request,debug,exchange);
|
||||
|
||||
if (hasContent)
|
||||
{
|
||||
exchange.setRequestContentSource(in);
|
||||
}
|
||||
|
||||
/*
|
||||
* we need to set the timeout on the exchange to take into account the timeout of the HttpClient and the HttpExchange
|
||||
*/
|
||||
long ctimeout = (_client.getTimeout() > exchange.getTimeout())?_client.getTimeout():exchange.getTimeout();
|
||||
exchange.setTimeout(ctimeout);
|
||||
|
||||
_client.send(exchange);
|
||||
|
||||
try
|
||||
{
|
||||
exchange.waitForDone();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
_log.info("Exception while waiting for response on proxied request", e);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private HttpURI createUrl(HttpServletRequest request, final int debug) throws MalformedURLException
|
||||
{
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
if (request.getQueryString() != null)
|
||||
{
|
||||
uri += "?" + request.getQueryString();
|
||||
}
|
||||
|
||||
uri = PathMap.pathInfo(_pattern,uri);
|
||||
|
||||
if(uri==null)
|
||||
{
|
||||
uri = "/";
|
||||
}
|
||||
|
||||
HttpURI url = proxyHttpURI(uri);
|
||||
|
||||
if (debug != 0)
|
||||
{
|
||||
_log.debug(debug + " proxy " + uri + "-->" + url);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private boolean createHeaders(final HttpServletRequest request, final int debug, HttpExchange exchange)
|
||||
{
|
||||
// check connection header
|
||||
String connectionHdr = request.getHeader("Connection");
|
||||
if (connectionHdr != null)
|
||||
{
|
||||
connectionHdr = connectionHdr.toLowerCase();
|
||||
if (connectionHdr.indexOf("keep-alive") < 0 && connectionHdr.indexOf("close") < 0)
|
||||
{
|
||||
connectionHdr = null;
|
||||
}
|
||||
}
|
||||
|
||||
// force host
|
||||
if (_hostHeader != null)
|
||||
{
|
||||
exchange.setRequestHeader("Host",_hostHeader);
|
||||
}
|
||||
|
||||
// copy headers
|
||||
boolean xForwardedFor = false;
|
||||
boolean hasContent = false;
|
||||
long contentLength = -1;
|
||||
Enumeration<?> enm = request.getHeaderNames();
|
||||
while (enm.hasMoreElements())
|
||||
{
|
||||
// TODO could be better than this!
|
||||
String hdr = (String)enm.nextElement();
|
||||
String lhdr = hdr.toLowerCase();
|
||||
|
||||
if (_DontProxyHeaders.contains(lhdr))
|
||||
continue;
|
||||
if (connectionHdr != null && connectionHdr.indexOf(lhdr) >= 0)
|
||||
continue;
|
||||
if (_hostHeader != null && "host".equals(lhdr))
|
||||
continue;
|
||||
|
||||
if ("content-type".equals(lhdr))
|
||||
hasContent = true;
|
||||
else if ("content-length".equals(lhdr))
|
||||
{
|
||||
contentLength = request.getContentLength();
|
||||
exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH,Long.toString(contentLength));
|
||||
if (contentLength > 0)
|
||||
hasContent = true;
|
||||
}
|
||||
else if ("x-forwarded-for".equals(lhdr))
|
||||
xForwardedFor = true;
|
||||
|
||||
Enumeration<?> vals = request.getHeaders(hdr);
|
||||
while (vals.hasMoreElements())
|
||||
{
|
||||
String val = (String)vals.nextElement();
|
||||
if (val != null)
|
||||
{
|
||||
if (debug != 0)
|
||||
_log.debug(debug + " " + hdr + ": " + val);
|
||||
|
||||
exchange.setRequestHeader(hdr,val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Proxy headers
|
||||
exchange.setRequestHeader("Via","1.1 (jetty)");
|
||||
if (!xForwardedFor)
|
||||
{
|
||||
exchange.addRequestHeader("X-Forwarded-For",request.getRemoteAddr());
|
||||
exchange.addRequestHeader("X-Forwarded-Proto",request.getScheme());
|
||||
exchange.addRequestHeader("X-Forwarded-Host",request.getServerName());
|
||||
exchange.addRequestHeader("X-Forwarded-Server",request.getLocalName());
|
||||
}
|
||||
return hasContent;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setProxyTo(String proxyTo)
|
||||
{
|
||||
this._proxyTo = proxyTo;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setMaxThreads(String maxThreads)
|
||||
{
|
||||
this._maxThreads = maxThreads;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setMaxConnections(String maxConnections)
|
||||
{
|
||||
_maxConnections = maxConnections;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setTimeout(String timeout)
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setIdleTimeout(String idleTimeout)
|
||||
{
|
||||
_idleTimeout = idleTimeout;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setRequestHeaderSize(String requestHeaderSize)
|
||||
{
|
||||
_requestHeaderSize = requestHeaderSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setRequestBufferSize(String requestBufferSize)
|
||||
{
|
||||
_requestBufferSize = requestBufferSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setResponseHeaderSize(String responseHeaderSize)
|
||||
{
|
||||
_responseHeaderSize = responseHeaderSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setResponseBufferSize(String responseBufferSize)
|
||||
{
|
||||
_responseBufferSize = responseBufferSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void addDontProxyHeaders(String dontProxyHeader)
|
||||
{
|
||||
_DontProxyHeaders.add(dontProxyHeader);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* CONNECTOR_SOCKET = 0;
|
||||
* CONNECTOR_SELECT_CHANNEL = 2; (default)
|
||||
*
|
||||
* @param connectorType
|
||||
*/
|
||||
public void setConnectorType( int connectorType )
|
||||
{
|
||||
_connectorType = connectorType;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,11 +5,11 @@
|
|||
// 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
|
||||
// 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.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
package org.eclipse.jetty.rewrite.handler;
|
||||
|
||||
|
@ -19,25 +19,24 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.PathMap;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*<p> Rewrite handler is responsible for managing the rules. Its capabilities
|
||||
* is not only limited for URL rewrites such as RewritePatternRule or RewriteRegexRule.
|
||||
* There is also handling for cookies, headers, redirection, setting status or error codes
|
||||
* whenever the rule finds a match.
|
||||
*
|
||||
* <p> The rules can be matched by the either: pattern matching of PathMap
|
||||
* (eg {@link PatternRule}), regular expressions (eg {@link RegexRule}) or certain conditions set
|
||||
* is not only limited for URL rewrites such as RewritePatternRule or RewriteRegexRule.
|
||||
* There is also handling for cookies, headers, redirection, setting status or error codes
|
||||
* whenever the rule finds a match.
|
||||
*
|
||||
* <p> The rules can be matched by the either: pattern matching of PathMap
|
||||
* (eg {@link PatternRule}), regular expressions (eg {@link RegexRule}) or certain conditions set
|
||||
* (eg {@link MsieSslRule} - the requests must be in SSL mode).
|
||||
*
|
||||
* <p> The rules can be grouped into rule containers (class {@link RuleContainer}), and will only
|
||||
*
|
||||
* <p> The rules can be grouped into rule containers (class {@link RuleContainer}), and will only
|
||||
* be applied if the request matches the conditions for their container
|
||||
* (e.g., by virtual host name)
|
||||
*
|
||||
*
|
||||
* <p>The list of predefined rules is:
|
||||
* <ul>
|
||||
* <li> {@link CookiePatternRule} - adds a new cookie in response. </li>
|
||||
|
@ -46,28 +45,36 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||
* <li> {@link ResponsePatternRule} - sets the status/error codes. </li>
|
||||
* <li> {@link RewritePatternRule} - rewrites the requested URI. </li>
|
||||
* <li> {@link RewriteRegexRule} - rewrites the requested URI using regular expression for pattern matching. </li>
|
||||
* <li> {@link ProxyRule} - proxies the requested URI to the host defined in proxyTo. </li>
|
||||
* <li> {@link MsieSslRule} - disables the keep alive on SSL for IE5 and IE6. </li>
|
||||
* <li> {@link LegacyRule} - the old version of rewrite. </li>
|
||||
* <li> {@link ForwardedSchemeHeaderRule} - set the scheme according to the headers present. </li>
|
||||
* <li> {@link VirtualHostRuleContainer} - checks whether the request matches one of a set of virtual host names.</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
*
|
||||
* Here is a typical jetty.xml configuration would be: <pre>
|
||||
*
|
||||
*
|
||||
* <Set name="handler">
|
||||
* <New id="Handlers" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
|
||||
* <Set name="rules">
|
||||
* <Array type="org.eclipse.jetty.rewrite.handler.Rule">
|
||||
*
|
||||
* <Item>
|
||||
* <Item>
|
||||
* <New id="rewrite" class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
|
||||
* <Set name="pattern">/*</Set>
|
||||
* <Set name="replacement">/test</Set>
|
||||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
* <Item>
|
||||
* <Item>
|
||||
* <New id="rewrite" class="org.eclipse.jetty.rewrite.handler.ProxyRule">
|
||||
* <Set name="pattern">/*</Set>
|
||||
* <Set name="proxyTo">http://webtide.com:8080</Set>
|
||||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
* <Item>
|
||||
* <New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule">
|
||||
* <Set name="pattern">/session/</Set>
|
||||
* <Set name="code">400</Set>
|
||||
|
@ -75,7 +82,7 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
* <Item>
|
||||
* <Item>
|
||||
* <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
|
||||
* <Set name="pattern">*.jsp</Set>
|
||||
* <Set name="name">server</Set>
|
||||
|
@ -83,7 +90,7 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
* <Item>
|
||||
* <Item>
|
||||
* <New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
|
||||
* <Set name="pattern">*.jsp</Set>
|
||||
* <Set name="name">title</Set>
|
||||
|
@ -91,28 +98,28 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
* <Item>
|
||||
* <Item>
|
||||
* <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule">
|
||||
* <Set name="pattern">/test/dispatch</Set>
|
||||
* <Set name="location">http://jetty.eclipse.org</Set>
|
||||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
* <Item>
|
||||
* <Item>
|
||||
* <New id="regexRewrite" class="org.eclipse.jetty.rewrite.handler.RewriteRegexRule">
|
||||
* <Set name="regex">/test-jaas/$</Set>
|
||||
* <Set name="replacement">/demo</Set>
|
||||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
* <Item>
|
||||
*
|
||||
* <Item>
|
||||
* <New id="forwardedHttps" class="org.eclipse.jetty.rewrite.handler.ForwardedSchemeHeaderRule">
|
||||
* <Set name="header">X-Forwarded-Scheme</Set>
|
||||
* <Set name="headerValue">https</Set>
|
||||
* <Set name="scheme">https</Set>
|
||||
* </New>
|
||||
* </Item>
|
||||
*
|
||||
*
|
||||
* <Item>
|
||||
* <New id="virtualHost" class="org.eclipse.jetty.rewrite.handler.VirtualHostRuleContainer">
|
||||
*
|
||||
|
@ -134,10 +141,10 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||
* </New>
|
||||
* </Arg>
|
||||
* </Call>
|
||||
*
|
||||
*
|
||||
* </New>
|
||||
* </ Item>
|
||||
*
|
||||
*
|
||||
* </Array>
|
||||
* </Set>
|
||||
*
|
||||
|
@ -162,13 +169,13 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||
* </New>
|
||||
* </Set>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class RewriteHandler extends HandlerWrapper
|
||||
{
|
||||
|
||||
|
||||
private RuleContainer _rules;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public RewriteHandler()
|
||||
{
|
||||
|
@ -179,7 +186,7 @@ public class RewriteHandler extends HandlerWrapper
|
|||
/**
|
||||
* To enable configuration from jetty.xml on rewriteRequestURI, rewritePathInfo and
|
||||
* originalPathAttribute
|
||||
*
|
||||
*
|
||||
* @param legacyRule old style rewrite rule
|
||||
*/
|
||||
@Deprecated
|
||||
|
@ -201,7 +208,7 @@ public class RewriteHandler extends HandlerWrapper
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Assigns the rules to process.
|
||||
* @param rules an array of {@link Rule}.
|
||||
* @param rules an array of {@link Rule}.
|
||||
*/
|
||||
public void setRules(Rule[] rules)
|
||||
{
|
||||
|
@ -297,13 +304,13 @@ public class RewriteHandler extends HandlerWrapper
|
|||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
if (isStarted())
|
||||
{
|
||||
{
|
||||
String returned = _rules.matchAndApply(target, request, response);
|
||||
target = (returned == null) ? target : returned;
|
||||
|
||||
|
||||
if (!baseRequest.isHandled())
|
||||
super.handle(target, baseRequest, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
package org.eclipse.jetty.rewrite.handler;
|
||||
|
||||
//========================================================================
|
||||
//Copyright (c) 2006-2009 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.
|
||||
//========================================================================
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.client.ContentExchange;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpExchange;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ProxyRuleTest
|
||||
{
|
||||
private static ProxyRule _rule;
|
||||
private static RewriteHandler _handler;
|
||||
private static Server _proxyServer = new Server();
|
||||
private static Connector _proxyServerConnector = new SelectChannelConnector();
|
||||
private static Server _targetServer = new Server();
|
||||
private static Connector _targetServerConnector = new SelectChannelConnector();
|
||||
private static HttpClient _httpClient = new HttpClient();
|
||||
|
||||
@BeforeClass
|
||||
public static void setupOnce() throws Exception
|
||||
{
|
||||
_targetServer.addConnector(_targetServerConnector);
|
||||
_targetServer.setHandler(new AbstractHandler()
|
||||
{
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
String responseString = "uri: " + request.getRequestURI() + " some content";
|
||||
response.getOutputStream().write(responseString.getBytes());
|
||||
response.setStatus(201);
|
||||
}
|
||||
});
|
||||
_targetServer.start();
|
||||
|
||||
_rule = new ProxyRule();
|
||||
_rule.setPattern("/foo/*");
|
||||
_rule.setProxyTo("http://localhost:" + _targetServerConnector.getLocalPort());
|
||||
_handler = new RewriteHandler();
|
||||
_handler.setRewriteRequestURI(true);
|
||||
_handler.setRules(new Rule[] { _rule });
|
||||
|
||||
_proxyServer.addConnector(_proxyServerConnector);
|
||||
_proxyServer.setHandler(_handler);
|
||||
_proxyServer.start();
|
||||
|
||||
_httpClient.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void destroy() throws Exception
|
||||
{
|
||||
_httpClient.stop();
|
||||
_proxyServer.stop();
|
||||
_targetServer.stop();
|
||||
_rule = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxy() throws Exception
|
||||
{
|
||||
|
||||
ContentExchange exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
String body = "BODY";
|
||||
String url = "http://localhost:" + _proxyServerConnector.getLocalPort() + "/foo?body=" + URLEncoder.encode(body,"UTF-8");
|
||||
exchange.setURL(url);
|
||||
|
||||
_httpClient.send(exchange);
|
||||
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
|
||||
assertEquals("uri: / some content",exchange.getResponseContent());
|
||||
assertEquals(201,exchange.getResponseStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyWithDeeperPath() throws Exception
|
||||
{
|
||||
|
||||
ContentExchange exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
String body = "BODY";
|
||||
String url = "http://localhost:" + _proxyServerConnector.getLocalPort() + "/foo/bar/foobar?body=" + URLEncoder.encode(body,"UTF-8");
|
||||
exchange.setURL(url);
|
||||
|
||||
_httpClient.send(exchange);
|
||||
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
|
||||
assertEquals("uri: /bar/foobar some content",exchange.getResponseContent());
|
||||
assertEquals(201,exchange.getResponseStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyNoMatch() throws Exception
|
||||
{
|
||||
ContentExchange exchange = new ContentExchange(true);
|
||||
exchange.setMethod(HttpMethods.GET);
|
||||
String body = "BODY";
|
||||
String url = "http://localhost:" + _proxyServerConnector.getLocalPort() + "/foobar?body=" + URLEncoder.encode(body,"UTF-8");
|
||||
exchange.setURL(url);
|
||||
|
||||
_httpClient.send(exchange);
|
||||
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
|
||||
assertEquals(404,exchange.getResponseStatus());
|
||||
}
|
||||
}
|
|
@ -98,9 +98,7 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
|
|||
SslSelectChannelEndPoint sslHttpChannelEndpoint=(SslSelectChannelEndPoint)endpoint;
|
||||
SSLEngine sslEngine=sslHttpChannelEndpoint.getSSLEngine();
|
||||
SSLSession sslSession=sslEngine.getSession();
|
||||
|
||||
System.err.println(sslSession.getProtocol());
|
||||
|
||||
|
||||
SslCertificates.customize(sslSession,endpoint,request);
|
||||
}
|
||||
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -185,7 +185,7 @@
|
|||
<plugin>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-version-maven-plugin</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.0.6</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<li><a href="tag2.jsp">JSP 2.0 SimpleTag demo</a><br/>
|
||||
<li><a href="tagfile.jsp">JSP 2.0 Tag File demo</a><br/>
|
||||
<li><a href="expr.jsp?A=1">JSP 2.0 Tag Expression</a><br/>
|
||||
<li><a href="jstl.jsp">JSTL Expression</a><br/>
|
||||
</ul>
|
||||
<a href="/">Main Menu</a>
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<h1>JSTL Example</h1>
|
||||
<hr>
|
||||
<p>A trivial jstl example
|
||||
<hr>
|
||||
<c:forEach var="i" begin="1" end="10" step="1">
|
||||
<c:out value="${i}" />
|
||||
<br />
|
||||
</c:forEach>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue