jetty-9 removed old http client

This commit is contained in:
Greg Wilkins 2012-10-29 10:33:58 +11:00
parent 262ef1386d
commit b87dc6ce83
88 changed files with 0 additions and 18232 deletions

View File

@ -1,122 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>
<name>Jetty :: Asynchronous HTTP Client</name>
<url>{$jetty.url}</url>
<properties>
<bundle-symbolic-name>${project.groupId}.client</bundle-symbolic-name>
<jetty.test.policy.loc>target/test-policy</jetty.test.policy.loc>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<instructions>
<Import-Package>javax.net.*,*</Import-Package>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!--
Required for OSGI
-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.client.*</onlyAnalyze>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>generate-test-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-policy</artifactId>
<version>${jetty-test-policy-version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**/*.keystore,**/*.pem</includes>
<outputDirectory>${jetty.test.policy.loc}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>-->
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,570 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.View;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Timeout;
/**
*
* @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $
*/
public abstract class AbstractHttpConnection extends AbstractConnection implements Dumpable
{
private static final Logger LOG = Log.getLogger(AbstractHttpConnection.class);
protected HttpDestination _destination;
protected HttpGenerator _generator;
protected HttpParser _parser;
protected boolean _http11 = true;
protected int _status;
protected ByteBuffer _connectionHeader;
protected boolean _reserved;
// The current exchange waiting for a response
protected volatile HttpExchange _exchange;
protected HttpExchange _pipeline;
private final Timeout.Task _idleTimeout = new ConnectionIdleTask();
private AtomicBoolean _idle = new AtomicBoolean(false);
AbstractHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp)
{
super(endp);
_generator = new HttpGenerator(requestBuffers,endp);
_parser = new HttpParser(responseBuffers,endp,new Handler());
}
public void setReserved (boolean reserved)
{
_reserved = reserved;
}
public boolean isReserved()
{
return _reserved;
}
public HttpDestination getDestination()
{
return _destination;
}
public void setDestination(HttpDestination destination)
{
_destination = destination;
}
public boolean send(HttpExchange ex) throws IOException
{
LOG.debug("Send {} on {}",ex,this);
synchronized (this)
{
if (_exchange != null)
{
if (_pipeline != null)
throw new IllegalStateException(this + " PIPELINED!!! _exchange=" + _exchange);
_pipeline = ex;
return true;
}
_exchange = ex;
_exchange.associate(this);
// The call to associate() may have closed the connection, check if it's the case
if (!_endp.isOpen())
{
_exchange.disassociate();
_exchange = null;
return false;
}
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT);
adjustIdleTimeout();
return true;
}
}
private void adjustIdleTimeout() throws IOException
{
// Adjusts the idle timeout in case the default or exchange timeout
// are greater. This is needed for long polls, where one wants an
// aggressive releasing of idle connections (so idle timeout is small)
// but still allow long polls to complete normally
long timeout = _exchange.getTimeout();
if (timeout <= 0)
timeout = _destination.getHttpClient().getTimeout();
long endPointTimeout = _endp.getMaxIdleTime();
if (timeout > 0 && timeout > endPointTimeout)
{
// Make it larger than the exchange timeout so that there are
// no races between the idle timeout and the exchange timeout
// when trying to close the endpoint
_endp.setMaxIdleTime(2 * (int)timeout);
}
}
public abstract Connection handle() throws IOException;
public boolean isIdle()
{
synchronized (this)
{
return _exchange == null;
}
}
public boolean isSuspended()
{
return false;
}
public void onClose()
{
}
/**
* @throws IOException
*/
protected void commitRequest() throws IOException
{
synchronized (this)
{
_status=0;
if (_exchange.getStatus() != HttpExchange.STATUS_WAITING_FOR_COMMIT)
throw new IllegalStateException();
_exchange.setStatus(HttpExchange.STATUS_SENDING_REQUEST);
_generator.setVersion(_exchange.getVersion());
String method=_exchange.getMethod();
String uri = _exchange.getRequestURI();
if (_destination.isProxied())
{
if (!HttpMethod.CONNECT.equals(method) && uri.startsWith("/"))
{
boolean secure = _destination.isSecure();
String host = _destination.getAddress().getHost();
int port = _destination.getAddress().getPort();
StringBuilder absoluteURI = new StringBuilder();
absoluteURI.append(secure ? HttpScheme.HTTPS : HttpScheme.HTTP);
absoluteURI.append("://");
absoluteURI.append(host);
// Avoid adding default ports
if (!(secure && port == 443 || !secure && port == 80))
absoluteURI.append(":").append(port);
absoluteURI.append(uri);
uri = absoluteURI.toString();
}
Authentication auth = _destination.getProxyAuthentication();
if (auth != null)
auth.setCredentials(_exchange);
}
_generator.setRequest(method, uri);
_parser.setHeadResponse(HttpMethod.HEAD.equalsIgnoreCase(method));
HttpFields requestHeaders = _exchange.getRequestFields();
if (_exchange.getVersion() >= HttpVersion.HTTP_1_1_ORDINAL)
{
if (!requestHeaders.containsKey(HttpHeader.HOST_BUFFER))
requestHeaders.add(HttpHeader.HOST_BUFFER,_destination.getHostHeader());
}
ByteBuffer requestContent = _exchange.getRequestContent();
if (requestContent != null)
{
requestHeaders.putLongField(HttpHeader.CONTENT_LENGTH, requestContent.length());
_generator.completeHeader(requestHeaders,false);
_generator.addContent(new View(requestContent),true);
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
else
{
InputStream requestContentStream = _exchange.getRequestContentSource();
if (requestContentStream != null)
{
_generator.completeHeader(requestHeaders, false);
}
else
{
requestHeaders.remove(HttpHeader.CONTENT_LENGTH);
_generator.completeHeader(requestHeaders, true);
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
}
}
}
protected void reset() throws IOException
{
_connectionHeader = null;
_parser.reset();
_generator.reset();
_http11 = true;
}
private class Handler extends HttpParser.EventHandler
{
@Override
public void startRequest(ByteBuffer method, ByteBuffer url, ByteBuffer version) throws IOException
{
// System.out.println( method.toString() + "///" + url.toString() +
// "///" + version.toString() );
// TODO validate this is acceptable, the <!DOCTYPE goop was coming
// out here
// throw new IllegalStateException();
}
@Override
public void startResponse(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange==null)
{
LOG.warn("No exchange for response");
_endp.close();
return;
}
switch(status)
{
case HttpStatus.CONTINUE_100:
case HttpStatus.PROCESSING_102:
// TODO check if appropriate expect was sent in the request.
exchange.setEventListener(new NonFinalResponseListener(exchange));
break;
case HttpStatus.OK_200:
// handle special case for CONNECT 200 responses
if (HttpMethod.CONNECT.equalsIgnoreCase(exchange.getMethod()))
_parser.setHeadResponse(true);
break;
}
_http11 = HttpVersion.HTTP_1_1_BUFFER.equals(version);
_status=status;
exchange.getEventListener().onResponseStatus(version,status,reason);
exchange.setStatus(HttpExchange.STATUS_PARSING_HEADERS);
}
@Override
public void parsedHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
{
if (HttpHeader.CACHE.getOrdinal(name) == HttpHeader.CONNECTION_ORDINAL)
{
_connectionHeader = HttpHeaderValue.CACHE.lookup(value);
}
exchange.getEventListener().onResponseHeader(name,value);
}
}
@Override
public void headerComplete() throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
exchange.setStatus(HttpExchange.STATUS_PARSING_CONTENT);
}
@Override
public void content(ByteBuffer ref) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
exchange.getEventListener().onResponseContent(ref);
}
@Override
public void messageComplete(long contextLength) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
exchange.setStatus(HttpExchange.STATUS_COMPLETED);
}
@Override
public void earlyEOF()
{
HttpExchange exchange = _exchange;
if (exchange!=null)
{
if (!exchange.isDone())
{
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(new EofException("early EOF"));
}
}
}
}
@Override
public String toString()
{
return String.format("%s %s g=%s p=%s",
super.toString(),
_destination == null ? "?.?.?.?:??" : _destination.getAddress(),
_generator,
_parser);
}
public String toDetailString()
{
return toString() + " ex=" + _exchange + " idle for " + _idleTimeout.getAge();
}
public void close() throws IOException
{
//if there is a live, unfinished exchange, set its status to be
//excepted and wake up anyone waiting on waitForDone()
HttpExchange exchange = _exchange;
if (exchange != null && !exchange.isDone())
{
switch (exchange.getStatus())
{
case HttpExchange.STATUS_CANCELLED:
case HttpExchange.STATUS_CANCELLING:
case HttpExchange.STATUS_COMPLETED:
case HttpExchange.STATUS_EXCEPTED:
case HttpExchange.STATUS_EXPIRED:
break;
case HttpExchange.STATUS_PARSING_CONTENT:
if (_endp.isInputShutdown() && _parser.isState(HttpParser.STATE_EOF_CONTENT))
break;
default:
String exch= exchange.toString();
String reason = _endp.isOpen()?(_endp.isInputShutdown()?"half closed: ":"local close: "):"closed: ";
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(new EofException(reason+exch));
}
}
if (_endp.isOpen())
{
_endp.close();
_destination.returnConnection(this, true);
}
}
public void setIdleTimeout()
{
synchronized (this)
{
if (_idle.compareAndSet(false, true))
_destination.getHttpClient().scheduleIdle(_idleTimeout);
else
throw new IllegalStateException();
}
}
public boolean cancelIdleTimeout()
{
synchronized (this)
{
if (_idle.compareAndSet(true, false))
{
_destination.getHttpClient().cancel(_idleTimeout);
return true;
}
}
return false;
}
protected void exchangeExpired(HttpExchange exchange)
{
synchronized (this)
{
// We are expiring an exchange, but the exchange is pending
// Cannot reuse the connection because the reply may arrive, so close it
if (_exchange == exchange)
{
try
{
_destination.returnConnection(this, true);
}
catch (IOException x)
{
LOG.ignore(x);
}
}
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump()
*/
public String dump()
{
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump(java.lang.Appendable, java.lang.String)
*/
public void dump(Appendable out, String indent) throws IOException
{
synchronized (this)
{
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,Collections.singletonList(_endp));
}
}
/* ------------------------------------------------------------ */
private class ConnectionIdleTask extends Timeout.Task
{
/* ------------------------------------------------------------ */
@Override
public void expired()
{
// Connection idle, close it
if (_idle.compareAndSet(true, false))
{
_destination.returnIdleConnection(AbstractHttpConnection.this);
}
}
}
/* ------------------------------------------------------------ */
private class NonFinalResponseListener implements HttpEventListener
{
final HttpExchange _exchange;
final HttpEventListener _next;
/* ------------------------------------------------------------ */
public NonFinalResponseListener(HttpExchange exchange)
{
_exchange=exchange;
_next=exchange.getEventListener();
}
/* ------------------------------------------------------------ */
public void onRequestCommitted() throws IOException
{
}
/* ------------------------------------------------------------ */
public void onRequestComplete() throws IOException
{
}
/* ------------------------------------------------------------ */
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
}
/* ------------------------------------------------------------ */
public void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
_next.onResponseHeader(name,value);
}
/* ------------------------------------------------------------ */
public void onResponseHeaderComplete() throws IOException
{
_next.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
public void onResponseContent(ByteBuffer content) throws IOException
{
}
/* ------------------------------------------------------------ */
public void onResponseComplete() throws IOException
{
_exchange.setEventListener(_next);
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
_parser.reset();
}
/* ------------------------------------------------------------ */
public void onConnectionFailed(Throwable ex)
{
_exchange.setEventListener(_next);
_next.onConnectionFailed(ex);
}
/* ------------------------------------------------------------ */
public void onException(Throwable ex)
{
_exchange.setEventListener(_next);
_next.onException(ex);
}
/* ------------------------------------------------------------ */
public void onExpire()
{
_exchange.setEventListener(_next);
_next.onExpire();
}
/* ------------------------------------------------------------ */
public void onRetry()
{
_exchange.setEventListener(_next);
_next.onRetry();
}
}
}

View File

@ -1,96 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.net.InetSocketAddress;
/**
* @version $Revision: 4135 $ $Date: 2008-12-02 11:57:07 +0100 (Tue, 02 Dec 2008) $
*/
public class Address
{
private final String host;
private final int port;
public static Address from(String hostAndPort)
{
String host;
int port;
int colon = hostAndPort.indexOf(':');
if (colon >= 0)
{
host = hostAndPort.substring(0, colon);
port = Integer.parseInt(hostAndPort.substring(colon + 1));
}
else
{
host = hostAndPort;
port = 0;
}
return new Address(host, port);
}
public Address(String host, int port)
{
if (host == null)
throw new IllegalArgumentException("Host is null");
this.host = host.trim();
this.port = port;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Address that = (Address)obj;
if (!host.equals(that.host)) return false;
return port == that.port;
}
@Override
public int hashCode()
{
int result = host.hashCode();
result = 31 * result + port;
return result;
}
public String getHost()
{
return host;
}
public int getPort()
{
return port;
}
public InetSocketAddress toSocketAddress()
{
return new InetSocketAddress(getHost(), getPort());
}
@Override
public String toString()
{
return host + ":" + port;
}
}

View File

@ -1,267 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Asynchronous Client HTTP Connection
*/
public class AsyncHttpConnection extends AbstractHttpConnection implements AsyncConnection
{
private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
private boolean _requestComplete;
private ByteBuffer _requestContentChunk;
private final AsyncEndPoint _asyncEndp;
AsyncHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp)
{
super(requestBuffers,responseBuffers,endp);
_asyncEndp=(AsyncEndPoint)endp;
}
protected void reset() throws IOException
{
_requestComplete = false;
super.reset();
}
public Connection handle() throws IOException
{
Connection connection = this;
boolean progress=true;
try
{
boolean failed = false;
// While we are making progress and have not changed connection
while (progress && connection==this)
{
LOG.debug("while open={} more={} progress={}",_endp.isOpen(),_parser.isMoreInBuffer(),progress);
progress=false;
HttpExchange exchange=_exchange;
LOG.debug("exchange {} on {}",exchange,this);
try
{
// Should we commit the request?
if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
LOG.debug("commit {}",exchange);
progress=true;
commitRequest();
}
// Generate output
if (_generator.isCommitted() && !_generator.isComplete())
{
if (_generator.flushBuffer()>0)
{
LOG.debug("flushed");
progress=true;
}
// Is there more content to send or should we complete the generator
if (_generator.isState(AbstractGenerator.STATE_CONTENT))
{
// Look for more content to send.
if (_requestContentChunk==null)
_requestContentChunk = exchange.getRequestContentChunk(null);
if (_requestContentChunk==null)
{
LOG.debug("complete {}",exchange);
progress=true;
_generator.complete();
}
else if (_generator.isEmpty())
{
LOG.debug("addChunk");
progress=true;
ByteBuffer chunk=_requestContentChunk;
_requestContentChunk=exchange.getRequestContentChunk(null);
_generator.addContent(chunk,_requestContentChunk==null);
if (_requestContentChunk==null)
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
}
}
// Signal request completion
if (_generator.isComplete() && !_requestComplete)
{
LOG.debug("requestComplete {}",exchange);
progress=true;
_requestComplete = true;
exchange.getEventListener().onRequestComplete();
}
// Read any input that is available
if (!_parser.isComplete() && _parser.parseAvailable())
{
LOG.debug("parsed {}",exchange);
progress=true;
}
// Flush output
_endp.flush();
// Has any IO been done by the endpoint itself since last loop
if (_asyncEndp.hasProgressed())
{
LOG.debug("hasProgressed {}",exchange);
progress=true;
}
}
catch (Throwable e)
{
LOG.debug("Failure on " + _exchange, e);
failed = true;
synchronized (this)
{
if (exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
exchange.getStatus() != HttpExchange.STATUS_CANCELLED &&
!exchange.isDone())
{
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
if (e instanceof Error)
throw (Error)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
finally
{
LOG.debug("finally {} on {} progress={} {}",exchange,this,progress,_endp);
boolean complete = failed || _generator.isComplete() && _parser.isComplete();
if (complete)
{
boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent();
_generator.setPersistent(persistent);
reset();
if (persistent)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
synchronized (this)
{
exchange=_exchange;
_exchange = null;
// Cancel the exchange
if (exchange!=null)
{
exchange.cancelTimeout(_destination.getHttpClient());
// TODO should we check the exchange is done?
}
// handle switched protocols
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
if (switched!=null)
{
// switched protocol!
if (_pipeline!=null)
{
_destination.send(_pipeline);
}
_pipeline = null;
connection=switched;
}
}
// handle pipelined requests
if (_pipeline!=null)
{
if (!persistent || connection!=this)
_destination.send(_pipeline);
else
_exchange=_pipeline;
_pipeline=null;
}
if (_exchange==null && !isReserved()) // TODO how do we return switched connections?
_destination.returnConnection(this, !persistent);
}
}
}
}
}
finally
{
_parser.returnBuffers();
_generator.returnBuffers();
LOG.debug("unhandle {} on {}",_exchange,_endp);
}
return connection;
}
public void onInputShutdown() throws IOException
{
if (_generator.isIdle())
_endp.shutdownOutput();
}
@Override
public boolean send(HttpExchange ex) throws IOException
{
boolean sent=super.send(ex);
if (sent)
_asyncEndp.asyncDispatch();
return sent;
}
}

View File

@ -1,264 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.io.InterruptedIOException;
import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Blocking HTTP Connection
*/
public class BlockingHttpConnection extends AbstractHttpConnection
{
private static final Logger LOG = Log.getLogger(BlockingHttpConnection.class);
private boolean _requestComplete;
private ByteBuffer _requestContentChunk;
BlockingHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endPoint)
{
super(requestBuffers, responseBuffers, endPoint);
}
protected void reset() throws IOException
{
_requestComplete = false;
super.reset();
}
@Override
public Connection handle() throws IOException
{
Connection connection = this;
try
{
boolean failed = false;
// While we are making progress and have not changed connection
while (_endp.isOpen() && connection==this)
{
LOG.debug("open={} more={}",_endp.isOpen(),_parser.isMoreInBuffer());
HttpExchange exchange;
synchronized (this)
{
exchange=_exchange;
while (exchange == null)
{
try
{
this.wait();
exchange=_exchange;
}
catch (InterruptedException e)
{
throw new InterruptedIOException();
}
}
}
LOG.debug("exchange {}",exchange);
try
{
// Should we commit the request?
if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
LOG.debug("commit");
commitRequest();
}
// Generate output
while (_generator.isCommitted() && !_generator.isComplete())
{
if (_generator.flushBuffer()>0)
{
LOG.debug("flushed");
}
// Is there more content to send or should we complete the generator
if (_generator.isState(AbstractGenerator.STATE_CONTENT))
{
// Look for more content to send.
if (_requestContentChunk==null)
_requestContentChunk = exchange.getRequestContentChunk(null);
if (_requestContentChunk==null)
{
LOG.debug("complete");
_generator.complete();
}
else if (_generator.isEmpty())
{
LOG.debug("addChunk");
ByteBuffer chunk=_requestContentChunk;
_requestContentChunk=exchange.getRequestContentChunk(null);
_generator.addContent(chunk,_requestContentChunk==null);
if (_requestContentChunk==null)
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
}
}
// Signal request completion
if (_generator.isComplete() && !_requestComplete)
{
LOG.debug("requestComplete");
_requestComplete = true;
exchange.getEventListener().onRequestComplete();
}
// Read any input that is available
if (!_parser.isComplete() && _parser.parseAvailable())
{
LOG.debug("parsed");
}
// Flush output
_endp.flush();
}
catch (Throwable e)
{
LOG.debug("Failure on " + _exchange, e);
failed = true;
synchronized (this)
{
if (exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
exchange.getStatus() != HttpExchange.STATUS_CANCELLED &&
!exchange.isDone())
{
if(exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
if (e instanceof Error)
throw (Error)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
finally
{
LOG.debug("{} {}",_generator, _parser);
LOG.debug("{}",_endp);
boolean complete = failed || _generator.isComplete() && _parser.isComplete();
if (complete)
{
boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent();
_generator.setPersistent(persistent);
reset();
if (persistent)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
synchronized (this)
{
exchange=_exchange;
_exchange = null;
// Cancel the exchange
if (exchange!=null)
{
exchange.cancelTimeout(_destination.getHttpClient());
// TODO should we check the exchange is done?
}
// handle switched protocols
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
if (switched!=null)
connection=switched;
{
// switched protocol!
_pipeline = null;
if (_pipeline!=null)
_destination.send(_pipeline);
_pipeline = null;
connection=switched;
}
}
// handle pipelined requests
if (_pipeline!=null)
{
if (!persistent || connection!=this)
_destination.send(_pipeline);
else
_exchange=_pipeline;
_pipeline=null;
}
if (_exchange==null && !isReserved()) // TODO how do we return switched connections?
_destination.returnConnection(this, !persistent);
}
}
}
}
}
finally
{
_parser.returnBuffers();
_generator.returnBuffers();
}
return connection;
}
@Override
public boolean send(HttpExchange ex) throws IOException
{
boolean sent=super.send(ex);
if (sent)
{
synchronized (this)
{
notifyAll();
}
}
return sent;
}
}

View File

@ -1,75 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import org.eclipse.jetty.http.HttpFields;
/**
* An exchange that retains response status and response headers for later use.
*/
public class CachedExchange extends HttpExchange
{
private final HttpFields _responseFields;
private volatile int _responseStatus;
/**
* Creates a new CachedExchange.
*
* @param cacheHeaders true to cache response headers, false to not cache them
*/
public CachedExchange(boolean cacheHeaders)
{
_responseFields = cacheHeaders ? new HttpFields() : null;
}
public synchronized int getResponseStatus()
{
if (getStatus() < HttpExchange.STATUS_PARSING_HEADERS)
throw new IllegalStateException("Response not received yet");
return _responseStatus;
}
public synchronized HttpFields getResponseFields()
{
if (getStatus() < HttpExchange.STATUS_PARSING_CONTENT)
throw new IllegalStateException("Headers not completely received yet");
return _responseFields;
}
@Override
protected synchronized void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
_responseStatus = status;
super.onResponseStatus(version, status, reason);
}
@Override
protected synchronized void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (_responseFields != null)
{
_responseFields.add(name, value.asImmutableBuffer());
}
super.onResponseHeader(name, value);
}
}

View File

@ -1,135 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.util.StringUtil;
/**
* A exchange that retains response content for later use.
*/
public class ContentExchange extends CachedExchange
{
private int _bufferSize = 4096;
private String _encoding = "utf-8";
private ByteArrayOutputStream _responseContent;
private File _fileForUpload;
public ContentExchange()
{
super(false);
}
public ContentExchange(boolean cacheFields)
{
super(cacheFields);
}
public synchronized String getResponseContent() throws UnsupportedEncodingException
{
if (_responseContent != null)
return _responseContent.toString(_encoding);
return null;
}
public synchronized byte[] getResponseContentBytes()
{
if (_responseContent != null)
return _responseContent.toByteArray();
return null;
}
@Override
protected synchronized void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if (_responseContent!=null)
_responseContent.reset();
super.onResponseStatus(version,status,reason);
}
@Override
protected synchronized void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
super.onResponseHeader(name, value);
int header = HttpHeader.CACHE.getOrdinal(name);
switch (header)
{
case HttpHeader.CONTENT_LENGTH_ORDINAL:
_bufferSize = BufferUtil.toInt(value);
break;
case HttpHeader.CONTENT_TYPE_ORDINAL:
String mime = StringUtil.asciiToLowerCase(value.toString());
int i = mime.indexOf("charset=");
if (i > 0)
{
_encoding = mime.substring(i + 8);
i = _encoding.indexOf(';');
if (i > 0)
_encoding = _encoding.substring(0, i);
}
break;
}
}
@Override
protected synchronized void onResponseContent(ByteBuffer content) throws IOException
{
super.onResponseContent(content);
if (_responseContent == null)
_responseContent = new ByteArrayOutputStream(_bufferSize);
content.writeTo(_responseContent);
}
@Override
protected synchronized void onRetry() throws IOException
{
if (_fileForUpload != null)
{
setRequestContent(null);
setRequestContentSource(getInputStream());
}
else
super.onRetry();
}
private synchronized InputStream getInputStream() throws IOException
{
return new FileInputStream(_fileForUpload);
}
public synchronized File getFileForUpload()
{
return _fileForUpload;
}
public synchronized void setFileForUpload(File fileForUpload) throws IOException
{
this._fileForUpload = fileForUpload;
setRequestContentSource(getInputStream());
}
}

View File

@ -1,906 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.net.ssl.SSLContext;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.client.security.RealmResolver;
import org.eclipse.jetty.client.security.SecurityListener;
import org.eclipse.jetty.http.HttpBuffers;
import org.eclipse.jetty.http.HttpBuffersImpl;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Buffers.Type;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.util.thread.Timeout;
/**
* Http Client.
* <p/>
* HttpClient is the main active component of the client API implementation.
* It is the opposite of the Connectors in standard Jetty, in that it listens
* for responses rather than requests. Just like the connectors, there is a
* blocking socket version and a non-blocking NIO version (implemented as nested classes
* selected by {@link #setConnectorType(int)}).
* <p/>
* The an instance of {@link HttpExchange} is passed to the {@link #send(HttpExchange)} method
* to send a request. The exchange contains both the headers and content (source) of the request
* plus the callbacks to handle responses. A HttpClient can have many exchanges outstanding
* and they may be queued on the {@link HttpDestination} waiting for a {@link AbstractHttpConnection},
* queued in the {@link AbstractHttpConnection} waiting to be transmitted or pipelined on the actual
* TCP/IP connection waiting for a response.
* <p/>
* The {@link HttpDestination} class is an aggregation of {@link AbstractHttpConnection}s for the
* same host, port and protocol. A destination may limit the number of connections
* open and they provide a pool of open connections that may be reused. Connections may also
* be allocated from a destination, so that multiple request sources are not multiplexed
* over the same connection.
*
* @see HttpExchange
* @see HttpDestination
*/
public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attributes, Dumpable
{
public static final int CONNECTOR_SOCKET = 0;
public static final int CONNECTOR_SELECT_CHANNEL = 2;
private int _connectorType = CONNECTOR_SELECT_CHANNEL;
private boolean _useDirectBuffers = true;
private boolean _connectBlocking = true;
private int _maxConnectionsPerAddress = Integer.MAX_VALUE;
private int _maxQueueSizePerAddress = Integer.MAX_VALUE;
private ConcurrentMap<Address, HttpDestination> _destinations = new ConcurrentHashMap<Address, HttpDestination>();
ThreadPool _threadPool;
Connector _connector;
private long _idleTimeout = 20000;
private long _timeout = 320000;
private int _connectTimeout = 75000;
private Timeout _timeoutQ = new Timeout();
private Timeout _idleTimeoutQ = new Timeout();
private Address _proxy;
private Authentication _proxyAuthentication;
private Set<String> _noProxy;
private int _maxRetries = 3;
private int _maxRedirects = 20;
private LinkedList<String> _registeredListeners;
private final SslContextFactory _sslContextFactory;
private RealmResolver _realmResolver;
private AttributesMap _attributes=new AttributesMap();
private final HttpBuffersImpl _buffers= new HttpBuffersImpl();
/* ------------------------------------------------------------------------------- */
private void setBufferTypes()
{
if (_connectorType==CONNECTOR_SOCKET)
{
_buffers.setRequestBufferType(Type.BYTE_ARRAY);
_buffers.setRequestHeaderType(Type.BYTE_ARRAY);
_buffers.setResponseBufferType(Type.BYTE_ARRAY);
_buffers.setResponseHeaderType(Type.BYTE_ARRAY);
}
else
{
_buffers.setRequestBufferType(Type.DIRECT);
_buffers.setRequestHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
_buffers.setResponseBufferType(Type.DIRECT);
_buffers.setResponseHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
}
}
/* ------------------------------------------------------------------------------- */
public HttpClient()
{
this(new SslContextFactory());
}
/* ------------------------------------------------------------------------------- */
public HttpClient(SslContextFactory sslContextFactory)
{
_sslContextFactory = sslContextFactory;
addBean(_sslContextFactory);
addBean(_buffers);
}
/* ------------------------------------------------------------------------------- */
/**
* @return True if connects will be in blocking mode.
*/
public boolean isConnectBlocking()
{
return _connectBlocking;
}
/* ------------------------------------------------------------------------------- */
/**
* @param connectBlocking True if connects will be in blocking mode.
*/
public void setConnectBlocking(boolean connectBlocking)
{
_connectBlocking = connectBlocking;
}
/* ------------------------------------------------------------------------------- */
public void send(HttpExchange exchange) throws IOException
{
boolean ssl = HttpScheme.HTTPS_BUFFER.equalsIgnoreCase(exchange.getScheme());
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_CONNECTION);
HttpDestination destination = getDestination(exchange.getAddress(), ssl);
destination.send(exchange);
}
/* ------------------------------------------------------------ */
/**
* @return the threadpool
*/
public ThreadPool getThreadPool()
{
return _threadPool;
}
/* ------------------------------------------------------------ */
/** Set the ThreadPool.
* The threadpool passed is added via {@link #addBean(Object)} so that
* it's lifecycle may be managed as a {@link AggregateLifeCycle}.
* @param threadPool the threadPool to set
*/
public void setThreadPool(ThreadPool threadPool)
{
removeBean(_threadPool);
_threadPool = threadPool;
addBean(_threadPool);
}
/* ------------------------------------------------------------ */
/**
* @param name
* @return Attribute associated with client
*/
public Object getAttribute(String name)
{
return _attributes.getAttribute(name);
}
/* ------------------------------------------------------------ */
/**
* @return names of attributes associated with client
*/
public Enumeration getAttributeNames()
{
return _attributes.getAttributeNames();
}
/* ------------------------------------------------------------ */
/**
* @param name
*/
public void removeAttribute(String name)
{
_attributes.removeAttribute(name);
}
/* ------------------------------------------------------------ */
/**
* Set an attribute on the HttpClient.
* Attributes are not used by the client, but are provided for
* so that users of a shared HttpClient may share other structures.
* @param name
* @param attribute
*/
public void setAttribute(String name, Object attribute)
{
_attributes.setAttribute(name,attribute);
}
/* ------------------------------------------------------------ */
public void clearAttributes()
{
_attributes.clearAttributes();
}
/* ------------------------------------------------------------------------------- */
public HttpDestination getDestination(Address remote, boolean ssl) throws IOException
{
if (remote == null)
throw new UnknownHostException("Remote socket address cannot be null.");
HttpDestination destination = _destinations.get(remote);
if (destination == null)
{
destination = new HttpDestination(this, remote, ssl);
if (_proxy != null && (_noProxy == null || !_noProxy.contains(remote.getHost())))
{
destination.setProxy(_proxy);
if (_proxyAuthentication != null)
destination.setProxyAuthentication(_proxyAuthentication);
}
HttpDestination other =_destinations.putIfAbsent(remote, destination);
if (other!=null)
destination=other;
}
return destination;
}
/* ------------------------------------------------------------ */
public void schedule(Timeout.Task task)
{
_timeoutQ.schedule(task);
}
/* ------------------------------------------------------------ */
public void schedule(Timeout.Task task, long timeout)
{
_timeoutQ.schedule(task, timeout - _timeoutQ.getDuration());
}
/* ------------------------------------------------------------ */
public void scheduleIdle(Timeout.Task task)
{
_idleTimeoutQ.schedule(task);
}
/* ------------------------------------------------------------ */
public void cancel(Timeout.Task task)
{
task.cancel();
}
/* ------------------------------------------------------------ */
/**
* Get whether the connector can use direct NIO buffers.
*/
public boolean getUseDirectBuffers()
{
return _useDirectBuffers;
}
/* ------------------------------------------------------------ */
/** Set a RealmResolver for client Authentication.
* If a realmResolver is set, then the HttpDestinations created by
* this client will instantiate a {@link SecurityListener} so that
* BASIC and DIGEST authentication can be performed.
* @param resolver
*/
public void setRealmResolver(RealmResolver resolver)
{
_realmResolver = resolver;
}
/* ------------------------------------------------------------ */
/**
* returns the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
*
* @return the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null
*/
public RealmResolver getRealmResolver()
{
return _realmResolver;
}
/* ------------------------------------------------------------ */
public boolean hasRealms()
{
return _realmResolver == null ? false : true;
}
/* ------------------------------------------------------------ */
/**
* Registers a listener that can listen to the stream of execution between the client and the
* server and influence events. Sequential calls to the method wrapper sequentially wrap the preceding
* listener in a delegation model.
* <p/>
* NOTE: the SecurityListener is a special listener which doesn't need to be added via this
* mechanic, if you register security realms then it will automatically be added as the top listener of the
* delegation stack.
*
* @param listenerClass
*/
public void registerListener(String listenerClass)
{
if (_registeredListeners == null)
{
_registeredListeners = new LinkedList<String>();
}
_registeredListeners.add(listenerClass);
}
/* ------------------------------------------------------------ */
public LinkedList<String> getRegisteredListeners()
{
return _registeredListeners;
}
/* ------------------------------------------------------------ */
/**
* Set to use NIO direct buffers.
*
* @param direct If True (the default), the connector can use NIO direct
* buffers. Some JVMs have memory management issues (bugs) with
* direct buffers.
*/
public void setUseDirectBuffers(boolean direct)
{
_useDirectBuffers = direct;
setBufferTypes();
}
/* ------------------------------------------------------------ */
/**
* Get the type of connector (socket, blocking or select) in use.
*/
public int getConnectorType()
{
return _connectorType;
}
/* ------------------------------------------------------------ */
public void setConnectorType(int connectorType)
{
this._connectorType = connectorType;
setBufferTypes();
}
/* ------------------------------------------------------------ */
public int getMaxConnectionsPerAddress()
{
return _maxConnectionsPerAddress;
}
/* ------------------------------------------------------------ */
public void setMaxConnectionsPerAddress(int maxConnectionsPerAddress)
{
_maxConnectionsPerAddress = maxConnectionsPerAddress;
}
public int getMaxQueueSizePerAddress()
{
return _maxQueueSizePerAddress;
}
public void setMaxQueueSizePerAddress(int maxQueueSizePerAddress)
{
this._maxQueueSizePerAddress = maxQueueSizePerAddress;
}
/* ------------------------------------------------------------ */
@Override
protected void doStart() throws Exception
{
setBufferTypes();
_timeoutQ.setDuration(_timeout);
_timeoutQ.setNow();
_idleTimeoutQ.setDuration(_idleTimeout);
_idleTimeoutQ.setNow();
if (_threadPool==null)
{
QueuedThreadPool pool = new LocalQueuedThreadPool();
pool.setMaxThreads(16);
pool.setDaemon(true);
pool.setName("HttpClient");
_threadPool = pool;
addBean(_threadPool,true);
}
_connector=(_connectorType == CONNECTOR_SELECT_CHANNEL)?new SelectConnector(this):new SocketConnector(this);
addBean(_connector,true);
super.doStart();
_threadPool.dispatch(new Runnable()
{
public void run()
{
while (isRunning())
{
_timeoutQ.tick(System.currentTimeMillis());
_idleTimeoutQ.tick(_timeoutQ.getNow());
try
{
Thread.sleep(200);
}
catch (InterruptedException ignored)
{
}
}
}
});
}
/* ------------------------------------------------------------ */
@Override
protected void doStop() throws Exception
{
for (HttpDestination destination : _destinations.values())
destination.close();
_timeoutQ.cancelAll();
_idleTimeoutQ.cancelAll();
super.doStop();
if (_threadPool instanceof LocalQueuedThreadPool)
{
removeBean(_threadPool);
_threadPool = null;
}
removeBean(_connector);
}
/* ------------------------------------------------------------ */
interface Connector extends LifeCycle
{
public void startConnection(HttpDestination destination) throws IOException;
}
/* ------------------------------------------------------------ */
/**
* if a keystore location has been provided then client will attempt to use it as the keystore,
* otherwise we simply ignore certificates and run with a loose ssl context.
*
* @return the SSL context
*/
protected SSLContext getSSLContext()
{
return _sslContextFactory.getSslContext();
}
/* ------------------------------------------------------------ */
/**
* @return the instance of SslContextFactory associated with the client
*/
public SslContextFactory getSslContextFactory()
{
return _sslContextFactory;
}
/* ------------------------------------------------------------ */
/**
* @return the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed.
*/
public long getIdleTimeout()
{
return _idleTimeout;
}
/* ------------------------------------------------------------ */
/**
* @param ms the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed.
*/
public void setIdleTimeout(long ms)
{
_idleTimeout = ms;
}
/* ------------------------------------------------------------ */
/**
* @return the period in ms that an exchange will wait for a response from the server.
* @deprecated use {@link #getTimeout()} instead.
*/
@Deprecated
public int getSoTimeout()
{
return Long.valueOf(getTimeout()).intValue();
}
/* ------------------------------------------------------------ */
/**
* @deprecated use {@link #setTimeout(long)} instead.
* @param timeout the period in ms that an exchange will wait for a response from the server.
*/
@Deprecated
public void setSoTimeout(int timeout)
{
setTimeout(timeout);
}
/* ------------------------------------------------------------ */
/**
* @return the period in ms that an exchange will wait for a response from the server.
*/
public long getTimeout()
{
return _timeout;
}
/* ------------------------------------------------------------ */
/**
* @param timeout the period in ms that an exchange will wait for a response from the server.
*/
public void setTimeout(long timeout)
{
_timeout = timeout;
}
/* ------------------------------------------------------------ */
/**
* @return the period in ms before timing out an attempt to connect
*/
public int getConnectTimeout()
{
return _connectTimeout;
}
/* ------------------------------------------------------------ */
/**
* @param connectTimeout the period in ms before timing out an attempt to connect
*/
public void setConnectTimeout(int connectTimeout)
{
this._connectTimeout = connectTimeout;
}
/* ------------------------------------------------------------ */
public Address getProxy()
{
return _proxy;
}
/* ------------------------------------------------------------ */
public void setProxy(Address proxy)
{
this._proxy = proxy;
}
/* ------------------------------------------------------------ */
public Authentication getProxyAuthentication()
{
return _proxyAuthentication;
}
/* ------------------------------------------------------------ */
public void setProxyAuthentication(Authentication authentication)
{
_proxyAuthentication = authentication;
}
/* ------------------------------------------------------------ */
public boolean isProxied()
{
return this._proxy != null;
}
/* ------------------------------------------------------------ */
public Set<String> getNoProxy()
{
return _noProxy;
}
/* ------------------------------------------------------------ */
public void setNoProxy(Set<String> noProxyAddresses)
{
_noProxy = noProxyAddresses;
}
/* ------------------------------------------------------------ */
public int maxRetries()
{
return _maxRetries;
}
/* ------------------------------------------------------------ */
public void setMaxRetries(int retries)
{
_maxRetries = retries;
}
/* ------------------------------------------------------------ */
public int maxRedirects()
{
return _maxRedirects;
}
/* ------------------------------------------------------------ */
public void setMaxRedirects(int redirects)
{
_maxRedirects = redirects;
}
public int getRequestBufferSize()
{
return _buffers.getRequestBufferSize();
}
public void setRequestBufferSize(int requestBufferSize)
{
_buffers.setRequestBufferSize(requestBufferSize);
}
public int getRequestHeaderSize()
{
return _buffers.getRequestHeaderSize();
}
public void setRequestHeaderSize(int requestHeaderSize)
{
_buffers.setRequestHeaderSize(requestHeaderSize);
}
public int getResponseBufferSize()
{
return _buffers.getResponseBufferSize();
}
public void setResponseBufferSize(int responseBufferSize)
{
_buffers.setResponseBufferSize(responseBufferSize);
}
public int getResponseHeaderSize()
{
return _buffers.getResponseHeaderSize();
}
public void setResponseHeaderSize(int responseHeaderSize)
{
_buffers.setResponseHeaderSize(responseHeaderSize);
}
public Type getRequestBufferType()
{
return _buffers.getRequestBufferType();
}
public Type getRequestHeaderType()
{
return _buffers.getRequestHeaderType();
}
public Type getResponseBufferType()
{
return _buffers.getResponseBufferType();
}
public Type getResponseHeaderType()
{
return _buffers.getResponseHeaderType();
}
public void setRequestBuffers(Buffers requestBuffers)
{
_buffers.setRequestBuffers(requestBuffers);
}
public void setResponseBuffers(Buffers responseBuffers)
{
_buffers.setResponseBuffers(responseBuffers);
}
public Buffers getRequestBuffers()
{
return _buffers.getRequestBuffers();
}
public Buffers getResponseBuffers()
{
return _buffers.getResponseBuffers();
}
public void setMaxBuffers(int maxBuffers)
{
_buffers.setMaxBuffers(maxBuffers);
}
public int getMaxBuffers()
{
return _buffers.getMaxBuffers();
}
/* ------------------------------------------------------------ */
@Deprecated
public String getTrustStoreLocation()
{
return _sslContextFactory.getTrustStore();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStoreLocation(String trustStoreLocation)
{
_sslContextFactory.setTrustStore(trustStoreLocation);
}
/* ------------------------------------------------------------ */
@Deprecated
public InputStream getTrustStoreInputStream()
{
return _sslContextFactory.getTrustStoreInputStream();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStoreInputStream(InputStream trustStoreInputStream)
{
_sslContextFactory.setTrustStoreInputStream(trustStoreInputStream);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getKeyStoreLocation()
{
return _sslContextFactory.getKeyStorePath();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyStoreLocation(String keyStoreLocation)
{
_sslContextFactory.setKeyStorePath(keyStoreLocation);
}
@Deprecated
public InputStream getKeyStoreInputStream()
{
return _sslContextFactory.getKeyStoreInputStream();
}
@Deprecated
public void setKeyStoreInputStream(InputStream keyStoreInputStream)
{
_sslContextFactory.setKeyStoreInputStream(keyStoreInputStream);
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyStorePassword(String keyStorePassword)
{
_sslContextFactory.setKeyStorePassword(keyStorePassword);
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyManagerPassword(String keyManagerPassword)
{
_sslContextFactory.setKeyManagerPassword(keyManagerPassword);
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStorePassword(String trustStorePassword)
{
_sslContextFactory.setTrustStorePassword(trustStorePassword);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getKeyStoreType()
{
return _sslContextFactory.getKeyStoreType();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyStoreType(String keyStoreType)
{
_sslContextFactory.setKeyStoreType(keyStoreType);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getTrustStoreType()
{
return _sslContextFactory.getTrustStoreType();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustStoreType(String trustStoreType)
{
_sslContextFactory.setTrustStoreType(trustStoreType);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getKeyManagerAlgorithm()
{
return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setKeyManagerAlgorithm(String keyManagerAlgorithm)
{
_sslContextFactory.setSslKeyManagerFactoryAlgorithm(keyManagerAlgorithm);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getTrustManagerAlgorithm()
{
return _sslContextFactory.getTrustManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setTrustManagerAlgorithm(String trustManagerAlgorithm)
{
_sslContextFactory.setTrustManagerFactoryAlgorithm(trustManagerAlgorithm);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getProtocol()
{
return _sslContextFactory.getProtocol();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setProtocol(String protocol)
{
_sslContextFactory.setProtocol(protocol);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getProvider()
{
return _sslContextFactory.getProvider();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setProvider(String provider)
{
_sslContextFactory.setProvider(provider);
}
/* ------------------------------------------------------------ */
@Deprecated
public String getSecureRandomAlgorithm()
{
return _sslContextFactory.getSecureRandomAlgorithm();
}
/* ------------------------------------------------------------ */
@Deprecated
public void setSecureRandomAlgorithm(String secureRandomAlgorithm)
{
_sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm);
}
private static class LocalQueuedThreadPool extends QueuedThreadPool
{
}
}

View File

@ -1,734 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.jetty.client.HttpClient.Connector;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.client.security.SecurityListener;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $
*/
public class HttpDestination implements Dumpable
{
private static final Logger LOG = Log.getLogger(HttpDestination.class);
private final List<HttpExchange> _queue = new LinkedList<HttpExchange>();
private final List<AbstractHttpConnection> _connections = new LinkedList<AbstractHttpConnection>();
private final BlockingQueue<Object> _newQueue = new ArrayBlockingQueue<Object>(10, true);
private final List<AbstractHttpConnection> _idle = new ArrayList<AbstractHttpConnection>();
private final HttpClient _client;
private final Address _address;
private final boolean _ssl;
private final ByteArrayBuffer _hostHeader;
private volatile int _maxConnections;
private volatile int _maxQueueSize;
private int _pendingConnections = 0;
private int _newConnection = 0;
private volatile Address _proxy;
private Authentication _proxyAuthentication;
private PathMap _authorizations;
private List<HttpCookie> _cookies;
HttpDestination(HttpClient client, Address address, boolean ssl)
{
_client = client;
_address = address;
_ssl = ssl;
_maxConnections = _client.getMaxConnectionsPerAddress();
_maxQueueSize = _client.getMaxQueueSizePerAddress();
String addressString = address.getHost();
if (address.getPort() != (_ssl ? 443 : 80))
addressString += ":" + address.getPort();
_hostHeader = new ByteArrayBuffer(addressString);
}
public HttpClient getHttpClient()
{
return _client;
}
public Address getAddress()
{
return _address;
}
public boolean isSecure()
{
return _ssl;
}
public ByteBuffer getHostHeader()
{
return _hostHeader;
}
public int getMaxConnections()
{
return _maxConnections;
}
public void setMaxConnections(int maxConnections)
{
this._maxConnections = maxConnections;
}
public int getMaxQueueSize()
{
return _maxQueueSize;
}
public void setMaxQueueSize(int maxQueueSize)
{
this._maxQueueSize = maxQueueSize;
}
public int getConnections()
{
synchronized (this)
{
return _connections.size();
}
}
public int getIdleConnections()
{
synchronized (this)
{
return _idle.size();
}
}
public void addAuthorization(String pathSpec, Authentication authorization)
{
synchronized (this)
{
if (_authorizations == null)
_authorizations = new PathMap();
_authorizations.put(pathSpec, authorization);
}
// TODO query and remove methods
}
public void addCookie(HttpCookie cookie)
{
synchronized (this)
{
if (_cookies == null)
_cookies = new ArrayList<HttpCookie>();
_cookies.add(cookie);
}
// TODO query, remove and age methods
}
/**
* Get a connection. We either get an idle connection if one is available, or
* we make a new connection, if we have not yet reached maxConnections. If we
* have reached maxConnections, we wait until the number reduces.
*
* @param timeout max time prepared to block waiting to be able to get a connection
* @return a HttpConnection for this destination
* @throws IOException if an I/O error occurs
*/
private AbstractHttpConnection getConnection(long timeout) throws IOException
{
AbstractHttpConnection connection = null;
while ((connection == null) && (connection = getIdleConnection()) == null && timeout > 0)
{
boolean startConnection = false;
synchronized (this)
{
int totalConnections = _connections.size() + _pendingConnections;
if (totalConnections < _maxConnections)
{
_newConnection++;
startConnection = true;
}
}
if (startConnection)
{
startNewConnection();
try
{
Object o = _newQueue.take();
if (o instanceof AbstractHttpConnection)
{
connection = (AbstractHttpConnection)o;
}
else
throw (IOException)o;
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
else
{
try
{
Thread.currentThread();
Thread.sleep(200);
timeout -= 200;
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
}
return connection;
}
public AbstractHttpConnection reserveConnection(long timeout) throws IOException
{
AbstractHttpConnection connection = getConnection(timeout);
if (connection != null)
connection.setReserved(true);
return connection;
}
public AbstractHttpConnection getIdleConnection() throws IOException
{
AbstractHttpConnection connection = null;
while (true)
{
synchronized (this)
{
if (connection != null)
{
_connections.remove(connection);
connection.close();
connection = null;
}
if (_idle.size() > 0)
connection = _idle.remove(_idle.size() - 1);
}
if (connection == null)
{
return null;
}
// Check if the connection was idle,
// but it expired just a moment ago
if (connection.cancelIdleTimeout())
{
return connection;
}
}
}
protected void startNewConnection()
{
try
{
synchronized (this)
{
_pendingConnections++;
}
final Connector connector = _client._connector;
if (connector != null)
connector.startConnection(this);
}
catch (Exception e)
{
LOG.debug(e);
onConnectionFailed(e);
}
}
public void onConnectionFailed(Throwable throwable)
{
Throwable connect_failure = null;
boolean startConnection = false;
synchronized (this)
{
_pendingConnections--;
if (_newConnection > 0)
{
connect_failure = throwable;
_newConnection--;
}
else if (_queue.size() > 0)
{
HttpExchange ex = _queue.remove(0);
if (ex.setStatus(HttpExchange.STATUS_EXCEPTED))
ex.getEventListener().onConnectionFailed(throwable);
// Since an existing connection had failed, we need to create a
// connection if the queue is not empty and client is running.
if (!_queue.isEmpty() && _client.isStarted())
startConnection = true;
}
}
if (startConnection)
startNewConnection();
if (connect_failure != null)
{
try
{
_newQueue.put(connect_failure);
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
}
public void onException(Throwable throwable)
{
synchronized (this)
{
_pendingConnections--;
if (_queue.size() > 0)
{
HttpExchange ex = _queue.remove(0);
if(ex.setStatus(HttpExchange.STATUS_EXCEPTED))
ex.getEventListener().onException(throwable);
}
}
}
public void onNewConnection(final AbstractHttpConnection connection) throws IOException
{
Connection q_connection = null;
synchronized (this)
{
_pendingConnections--;
_connections.add(connection);
if (_newConnection > 0)
{
q_connection = connection;
_newConnection--;
}
else if (_queue.size() == 0)
{
connection.setIdleTimeout();
_idle.add(connection);
}
else
{
EndPoint endPoint = connection.getEndPoint();
if (isProxied() && endPoint instanceof SelectConnector.UpgradableEndPoint)
{
SelectConnector.UpgradableEndPoint proxyEndPoint = (SelectConnector.UpgradableEndPoint)endPoint;
HttpExchange exchange = _queue.get(0);
ConnectExchange connect = new ConnectExchange(getAddress(), proxyEndPoint, exchange);
connect.setAddress(getProxy());
send(connection, connect);
}
else
{
HttpExchange exchange = _queue.remove(0);
send(connection, exchange);
}
}
}
if (q_connection != null)
{
try
{
_newQueue.put(q_connection);
}
catch (InterruptedException e)
{
LOG.ignore(e);
}
}
}
public void returnConnection(AbstractHttpConnection connection, boolean close) throws IOException
{
if (connection.isReserved())
connection.setReserved(false);
if (close)
{
try
{
connection.close();
}
catch (IOException e)
{
LOG.ignore(e);
}
}
if (!_client.isStarted())
return;
if (!close && connection.getEndPoint().isOpen())
{
synchronized (this)
{
if (_queue.size() == 0)
{
connection.setIdleTimeout();
_idle.add(connection);
}
else
{
HttpExchange ex = _queue.remove(0);
send(connection, ex);
}
this.notifyAll();
}
}
else
{
boolean startConnection = false;
synchronized (this)
{
_connections.remove(connection);
if (!_queue.isEmpty())
startConnection = true;
}
if (startConnection)
startNewConnection();
}
}
public void returnIdleConnection(AbstractHttpConnection connection)
{
// TODO work out the real idle time;
long idleForMs=connection!=null&&connection.getEndPoint()!=null?connection.getEndPoint().getMaxIdleTime():-1;
connection.onIdleExpired(idleForMs);
boolean startConnection = false;
synchronized (this)
{
_idle.remove(connection);
_connections.remove(connection);
if (!_queue.isEmpty() && _client.isStarted())
startConnection = true;
}
if (startConnection)
startNewConnection();
}
public void send(HttpExchange ex) throws IOException
{
LinkedList<String> listeners = _client.getRegisteredListeners();
if (listeners != null)
{
// Add registered listeners, fail if we can't load them
for (int i = listeners.size(); i > 0; --i)
{
String listenerClass = listeners.get(i - 1);
try
{
Class listener = Class.forName(listenerClass);
Constructor constructor = listener.getDeclaredConstructor(HttpDestination.class, HttpExchange.class);
HttpEventListener elistener = (HttpEventListener)constructor.newInstance(this, ex);
ex.setEventListener(elistener);
}
catch (final Exception e)
{
throw new IOException("Unable to instantiate registered listener for destination: " + listenerClass)
{
{initCause(e);}
};
}
}
}
// Security is supported by default and should be the first consulted
if (_client.hasRealms())
{
ex.setEventListener(new SecurityListener(this, ex));
}
doSend(ex);
}
public void resend(HttpExchange ex) throws IOException
{
ex.getEventListener().onRetry();
ex.reset();
doSend(ex);
}
protected void doSend(HttpExchange ex) throws IOException
{
// add cookies
// TODO handle max-age etc.
if (_cookies != null)
{
StringBuilder buf = null;
for (HttpCookie cookie : _cookies)
{
if (buf == null)
buf = new StringBuilder();
else
buf.append("; ");
buf.append(cookie.getName()); // TODO quotes
buf.append("=");
buf.append(cookie.getValue()); // TODO quotes
}
if (buf != null)
ex.addRequestHeader(HttpHeader.COOKIE, buf.toString());
}
// Add any known authorizations
if (_authorizations != null)
{
Authentication auth = (Authentication)_authorizations.match(ex.getRequestURI());
if (auth != null)
(auth).setCredentials(ex);
}
// Schedule the timeout here, before we queue the exchange
// so that we count also the queue time in the timeout
ex.scheduleTimeout(this);
AbstractHttpConnection connection = getIdleConnection();
if (connection != null)
{
send(connection, ex);
}
else
{
boolean startConnection = false;
synchronized (this)
{
if (_queue.size() == _maxQueueSize)
throw new RejectedExecutionException("Queue full for address " + _address);
_queue.add(ex);
if (_connections.size() + _pendingConnections < _maxConnections)
startConnection = true;
}
if (startConnection)
startNewConnection();
}
}
protected void exchangeExpired(HttpExchange exchange)
{
// The exchange may expire while waiting in the
// destination queue, make sure it is removed
synchronized (this)
{
_queue.remove(exchange);
}
}
protected void send(AbstractHttpConnection connection, HttpExchange exchange) throws IOException
{
synchronized (this)
{
// If server closes the connection, put the exchange back
// to the exchange queue and recycle the connection
if (!connection.send(exchange))
{
if (exchange.getStatus() <= HttpExchange.STATUS_WAITING_FOR_CONNECTION)
_queue.add(0, exchange);
returnIdleConnection(connection);
}
}
}
@Override
public synchronized String toString()
{
return String.format("HttpDestination@%x//%s:%d(%d/%d,%d,%d/%d)%n",hashCode(),_address.getHost(),_address.getPort(),_connections.size(),_maxConnections,_idle.size(),_queue.size(),_maxQueueSize);
}
public synchronized String toDetailString()
{
StringBuilder b = new StringBuilder();
b.append(toString());
b.append('\n');
synchronized (this)
{
for (AbstractHttpConnection connection : _connections)
{
b.append(connection.toDetailString());
if (_idle.contains(connection))
b.append(" IDLE");
b.append('\n');
}
}
b.append("--");
b.append('\n');
return b.toString();
}
public void setProxy(Address proxy)
{
_proxy = proxy;
}
public Address getProxy()
{
return _proxy;
}
public Authentication getProxyAuthentication()
{
return _proxyAuthentication;
}
public void setProxyAuthentication(Authentication authentication)
{
_proxyAuthentication = authentication;
}
public boolean isProxied()
{
return _proxy != null;
}
public void close() throws IOException
{
synchronized (this)
{
for (AbstractHttpConnection connection : _connections)
{
connection.close();
}
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump()
*/
public String dump()
{
return AggregateLifeCycle.dump(this);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.Dumpable#dump(java.lang.Appendable, java.lang.String)
*/
public void dump(Appendable out, String indent) throws IOException
{
synchronized (this)
{
out.append(String.valueOf(this)+"idle="+_idle.size()+" pending="+_pendingConnections).append("\n");
AggregateLifeCycle.dump(out,indent,_connections);
}
}
private class ConnectExchange extends ContentExchange
{
private final SelectConnector.UpgradableEndPoint proxyEndPoint;
private final HttpExchange exchange;
public ConnectExchange(Address serverAddress, SelectConnector.UpgradableEndPoint proxyEndPoint, HttpExchange exchange)
{
this.proxyEndPoint = proxyEndPoint;
this.exchange = exchange;
setMethod(HttpMethod.CONNECT);
setVersion(exchange.getVersion());
String serverHostAndPort = serverAddress.toString();
setRequestURI(serverHostAndPort);
addRequestHeader(HttpHeader.HOST, serverHostAndPort);
addRequestHeader(HttpHeader.PROXY_CONNECTION, "keep-alive");
addRequestHeader(HttpHeader.USER_AGENT, "Jetty-Client");
}
@Override
protected void onResponseComplete() throws IOException
{
int responseStatus = getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
proxyEndPoint.upgrade();
}
else if(responseStatus == HttpStatus.GATEWAY_TIMEOUT_504)
{
onExpire();
}
else
{
onException(new ProtocolException("Proxy: " + proxyEndPoint.getRemoteAddr() +":" + proxyEndPoint.getRemotePort() + " didn't return http return code 200, but " + responseStatus + " while trying to request: " + exchange.getAddress().toString()));
}
}
@Override
protected void onConnectionFailed(Throwable x)
{
HttpDestination.this.onConnectionFailed(x);
}
@Override
protected void onException(Throwable x)
{
_queue.remove(exchange);
if (exchange.setStatus(STATUS_EXCEPTED))
exchange.getEventListener().onException(x);
}
@Override
protected void onExpire()
{
_queue.remove(exchange);
if (exchange.setStatus(STATUS_EXPIRED))
exchange.getEventListener().onExpire();
}
}
}

View File

@ -1,68 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
/**
*
*
*
*/
public interface HttpEventListener
{
// TODO review the methods here, we can probably trim these down on what to expose
public void onRequestCommitted() throws IOException;
public void onRequestComplete() throws IOException;
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException;
public void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException;
public void onResponseHeaderComplete() throws IOException;
public void onResponseContent(ByteBuffer content) throws IOException;
public void onResponseComplete() throws IOException;
public void onConnectionFailed(Throwable ex);
public void onException(Throwable ex);
public void onExpire();
public void onRetry();
}

View File

@ -1,167 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
public class HttpEventListenerWrapper implements HttpEventListener
{
HttpEventListener _listener;
boolean _delegatingRequests;
boolean _delegatingResponses;
boolean _delegationResult = true;
private ByteBuffer _version;
private int _status;
private ByteBuffer _reason;
public HttpEventListenerWrapper()
{
_listener=null;
_delegatingRequests=false;
_delegatingResponses=false;
}
public HttpEventListenerWrapper(HttpEventListener eventListener,boolean delegating)
{
_listener=eventListener;
_delegatingRequests=delegating;
_delegatingResponses=delegating;
}
public HttpEventListener getEventListener()
{
return _listener;
}
public void setEventListener(HttpEventListener listener)
{
_listener = listener;
}
public boolean isDelegatingRequests()
{
return _delegatingRequests;
}
public boolean isDelegatingResponses()
{
return _delegatingResponses;
}
public void setDelegatingRequests(boolean delegating)
{
_delegatingRequests = delegating;
}
public void setDelegatingResponses(boolean delegating)
{
_delegatingResponses = delegating;
}
public void setDelegationResult( boolean result )
{
_delegationResult = result;
}
public void onConnectionFailed(Throwable ex)
{
if (_delegatingRequests)
_listener.onConnectionFailed(ex);
}
public void onException(Throwable ex)
{
if (_delegatingRequests||_delegatingResponses)
_listener.onException(ex);
}
public void onExpire()
{
if (_delegatingRequests||_delegatingResponses)
_listener.onExpire();
}
public void onRequestCommitted() throws IOException
{
if (_delegatingRequests)
_listener.onRequestCommitted();
}
public void onRequestComplete() throws IOException
{
if (_delegatingRequests)
_listener.onRequestComplete();
}
public void onResponseComplete() throws IOException
{
if (_delegatingResponses)
{
if (_delegationResult == false)
{
_listener.onResponseStatus(_version,_status,_reason);
}
_listener.onResponseComplete();
}
}
public void onResponseContent(ByteBuffer content) throws IOException
{
if (_delegatingResponses)
_listener.onResponseContent(content);
}
public void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (_delegatingResponses)
_listener.onResponseHeader(name,value);
}
public void onResponseHeaderComplete() throws IOException
{
if (_delegatingResponses)
_listener.onResponseHeaderComplete();
}
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if (_delegatingResponses)
{
_listener.onResponseStatus(version,status,reason);
}
else
{
_version = version;
_status = status;
_reason = reason;
}
}
public void onRetry()
{
if (_delegatingRequests)
_listener.onRetry();
}
}

View File

@ -1,212 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
/**
* RedirectListener
*
* Detect and handle the redirect responses
*/
public class RedirectListener extends HttpEventListenerWrapper
{
private final HttpExchange _exchange;
private HttpDestination _destination;
private String _location;
private int _attempts;
private boolean _requestComplete;
private boolean _responseComplete;
private boolean _redirected;
public RedirectListener(HttpDestination destination, HttpExchange ex)
{
// Start of sending events through to the wrapped listener
// Next decision point is the onResponseStatus
super(ex.getEventListener(),true);
_destination = destination;
_exchange = ex;
}
@Override
public void onResponseStatus( ByteBuffer version, int status, ByteBuffer reason )
throws IOException
{
_redirected = ((status == HttpStatus.MOVED_PERMANENTLY_301 ||
status == HttpStatus.MOVED_TEMPORARILY_302) &&
_attempts < _destination.getHttpClient().maxRedirects());
if (_redirected)
{
setDelegatingRequests(false);
setDelegatingResponses(false);
}
super.onResponseStatus(version,status,reason);
}
@Override
public void onResponseHeader( ByteBuffer name, ByteBuffer value )
throws IOException
{
if (_redirected)
{
int header = HttpHeader.CACHE.getOrdinal(name);
switch (header)
{
case HttpHeader.LOCATION_ORDINAL:
_location = value.toString();
break;
}
}
super.onResponseHeader(name,value);
}
@Override
public void onRequestComplete() throws IOException
{
_requestComplete = true;
if (checkExchangeComplete())
{
super.onRequestComplete();
}
}
@Override
public void onResponseComplete() throws IOException
{
_responseComplete = true;
if (checkExchangeComplete())
{
super.onResponseComplete();
}
}
public boolean checkExchangeComplete()
throws IOException
{
if (_redirected && _requestComplete && _responseComplete)
{
if (_location != null)
{
if (_location.indexOf("://")>0)
{
_exchange.setURL(_location);
}
else
{
_exchange.setRequestURI(_location);
}
// destination may have changed
boolean isHttps = HttpScheme.HTTPS.equals(String.valueOf(_exchange.getScheme()));
HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),isHttps);
if (_destination==destination)
{
_destination.resend(_exchange);
}
else
{
// unwrap to find ultimate listener.
HttpEventListener listener=this;
while(listener instanceof HttpEventListenerWrapper)
{
listener=((HttpEventListenerWrapper)listener).getEventListener();
}
//reset the listener
_exchange.getEventListener().onRetry();
_exchange.reset();
_exchange.setEventListener(listener);
// Set the new Host header
Address address = _exchange.getAddress();
int port = address.getPort();
StringBuilder hostHeader = new StringBuilder( 64 );
hostHeader.append( address.getHost() );
if( !( ( port == 80 && !isHttps ) || ( port == 443 && isHttps ) ) )
{
hostHeader.append( ':' );
hostHeader.append( port );
}
_exchange.setRequestHeader( HttpHeader.HOST, hostHeader.toString() );
destination.send(_exchange);
}
return false;
}
else
{
setDelegationResult(false);
}
}
return true;
}
public void onRetry()
{
_redirected=false;
_attempts++;
setDelegatingRequests(true);
setDelegatingResponses(true);
_requestComplete=false;
_responseComplete=false;
super.onRetry();
}
/**
* Delegate failed connection
*/
@Override
public void onConnectionFailed( Throwable ex )
{
setDelegatingRequests(true);
setDelegatingResponses(true);
super.onConnectionFailed( ex );
}
/**
* Delegate onException
*/
@Override
public void onException( Throwable ex )
{
setDelegatingRequests(true);
setDelegatingResponses(true);
super.onException( ex );
}
}

View File

@ -1,444 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.UnresolvedAddressException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager;
import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.Timeout;
import org.eclipse.jetty.util.thread.Timeout.Task;
class SelectConnector extends AggregateLifeCycle implements HttpClient.Connector, Dumpable
{
private static final Logger LOG = Log.getLogger(SelectConnector.class);
private final HttpClient _httpClient;
private final Manager _selectorManager=new Manager();
private final Map<SocketChannel, Timeout.Task> _connectingChannels = new ConcurrentHashMap<SocketChannel, Timeout.Task>();
/* ------------------------------------------------------------ */
/**
* @param httpClient the HttpClient this connector is associated to. It is
* added via the {@link #addBean(Object, boolean)} as an unmanaged bean.
*/
SelectConnector(HttpClient httpClient)
{
_httpClient = httpClient;
addBean(_httpClient,false);
addBean(_selectorManager,true);
}
/* ------------------------------------------------------------ */
public void startConnection( HttpDestination destination )
throws IOException
{
SocketChannel channel = null;
try
{
channel = SocketChannel.open();
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
channel.socket().setTcpNoDelay(true);
if (_httpClient.isConnectBlocking())
{
channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
channel.configureBlocking(false);
_selectorManager.register( channel, destination );
}
else
{
channel.configureBlocking(false);
channel.connect(address.toSocketAddress());
_selectorManager.register(channel,destination);
ConnectTimeout connectTimeout = new ConnectTimeout(channel,destination);
_httpClient.schedule(connectTimeout,_httpClient.getConnectTimeout());
_connectingChannels.put(channel,connectTimeout);
}
}
catch (UnresolvedAddressException ex)
{
if (channel != null)
channel.close();
destination.onConnectionFailed(ex);
}
catch(IOException ex)
{
if (channel != null)
channel.close();
destination.onConnectionFailed(ex);
}
}
/* ------------------------------------------------------------ */
class Manager extends SelectorManager
{
Logger LOG = SelectConnector.LOG;
@Override
public boolean dispatch(Runnable task)
{
return _httpClient._threadPool.dispatch(task);
}
@Override
protected void endPointOpened(SelectChannelEndPoint endpoint)
{
}
@Override
protected void endPointClosed(SelectChannelEndPoint endpoint)
{
}
@Override
protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
{
}
@Override
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
{
return new AsyncHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
}
@Override
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key) throws IOException
{
// We're connected, cancel the connect timeout
Timeout.Task connectTimeout = _connectingChannels.remove(channel);
if (connectTimeout != null)
connectTimeout.cancel();
if (LOG.isDebugEnabled())
LOG.debug("Channels with connection pending: {}", _connectingChannels.size());
// key should have destination at this point (will be replaced by endpoint after this call)
HttpDestination dest=(HttpDestination)key.attachment();
SelectChannelEndPoint scep = new SelectChannelEndPoint(channel, selectSet, key, (int)_httpClient.getIdleTimeout());
AsyncEndPoint ep = scep;
if (dest.isSecure())
{
LOG.debug("secure to {}, proxied={}",channel,dest.isProxied());
ep = new UpgradableEndPoint(ep,newSslEngine(channel));
}
AsyncConnection connection = selectSet.getManager().newConnection(channel,ep, key.attachment());
ep.setConnection(connection);
AbstractHttpConnection httpConnection=(AbstractHttpConnection)connection;
httpConnection.setDestination(dest);
if (dest.isSecure() && !dest.isProxied())
((UpgradableEndPoint)ep).upgrade();
dest.onNewConnection(httpConnection);
return scep;
}
private synchronized SSLEngine newSslEngine(SocketChannel channel) throws IOException
{
SslContextFactory sslContextFactory = _httpClient.getSslContextFactory();
SSLEngine sslEngine;
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
sslEngine = sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
sslEngine = sslContextFactory.newSslEngine();
}
sslEngine.setUseClientMode(true);
sslEngine.beginHandshake();
return sslEngine;
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see org.eclipse.io.nio.SelectorManager#connectionFailed(java.nio.channels.SocketChannel, java.lang.Throwable, java.lang.Object)
*/
@Override
protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
{
Timeout.Task connectTimeout = _connectingChannels.remove(channel);
if (connectTimeout != null)
connectTimeout.cancel();
if (attachment instanceof HttpDestination)
((HttpDestination)attachment).onConnectionFailed(ex);
else
super.connectionFailed(channel,ex,attachment);
}
}
private class ConnectTimeout extends Timeout.Task
{
private final SocketChannel channel;
private final HttpDestination destination;
public ConnectTimeout(SocketChannel channel, HttpDestination destination)
{
this.channel = channel;
this.destination = destination;
}
@Override
public void expired()
{
if (channel.isConnectionPending())
{
LOG.debug("Channel {} timed out while connecting, closing it", channel);
try
{
// This will unregister the channel from the selector
channel.close();
}
catch (IOException x)
{
LOG.ignore(x);
}
destination.onConnectionFailed(new SocketTimeoutException());
}
}
}
public static class UpgradableEndPoint implements AsyncEndPoint
{
AsyncEndPoint _endp;
SSLEngine _engine;
public UpgradableEndPoint(AsyncEndPoint endp, SSLEngine engine) throws IOException
{
_engine=engine;
_endp=endp;
}
public void upgrade()
{
AsyncHttpConnection connection = (AsyncHttpConnection)_endp.getConnection();
SslConnection sslConnection = new SslConnection(_engine,_endp);
_endp.setConnection(sslConnection);
_endp=sslConnection.getSslEndPoint();
sslConnection.getSslEndPoint().setConnection(connection);
LOG.debug("upgrade {} to {} for {}",this,sslConnection,connection);
}
public Connection getConnection()
{
return _endp.getConnection();
}
public void setConnection(Connection connection)
{
_endp.setConnection(connection);
}
public void shutdownOutput() throws IOException
{
_endp.shutdownOutput();
}
public void dispatch()
{
_endp.asyncDispatch();
}
public void asyncDispatch()
{
_endp.asyncDispatch();
}
public boolean isOutputShutdown()
{
return _endp.isOutputShutdown();
}
public void shutdownInput() throws IOException
{
_endp.shutdownInput();
}
public void scheduleWrite()
{
_endp.scheduleWrite();
}
public boolean isInputShutdown()
{
return _endp.isInputShutdown();
}
public void close() throws IOException
{
_endp.close();
}
public int fill(ByteBuffer buffer) throws IOException
{
return _endp.fill(buffer);
}
public boolean isWritable()
{
return _endp.isWritable();
}
public boolean hasProgressed()
{
return _endp.hasProgressed();
}
public int flush(ByteBuffer buffer) throws IOException
{
return _endp.flush(buffer);
}
public void scheduleTimeout(Task task, long timeoutMs)
{
_endp.scheduleTimeout(task,timeoutMs);
}
public void cancelTimeout(Task task)
{
_endp.cancelTimeout(task);
}
public int flush(ByteBuffer header, ByteBuffer buffer, ByteBuffer trailer) throws IOException
{
return _endp.flush(header,buffer,trailer);
}
public String getLocalAddr()
{
return _endp.getLocalAddr();
}
public String getLocalHost()
{
return _endp.getLocalHost();
}
public int getLocalPort()
{
return _endp.getLocalPort();
}
public String getRemoteAddr()
{
return _endp.getRemoteAddr();
}
public String getRemoteHost()
{
return _endp.getRemoteHost();
}
public int getRemotePort()
{
return _endp.getRemotePort();
}
public boolean isBlocking()
{
return _endp.isBlocking();
}
public boolean blockReadable(long millisecs) throws IOException
{
return _endp.blockReadable(millisecs);
}
public boolean blockWritable(long millisecs) throws IOException
{
return _endp.blockWritable(millisecs);
}
public boolean isOpen()
{
return _endp.isOpen();
}
public Object getTransport()
{
return _endp.getTransport();
}
public void flush() throws IOException
{
_endp.flush();
}
public int getMaxIdleTime()
{
return _endp.getMaxIdleTime();
}
public void setMaxIdleTime(int timeMs) throws IOException
{
_endp.setMaxIdleTime(timeMs);
}
public void onIdleExpired(long idleForMs)
{
_endp.onIdleExpired(idleForMs);
}
public void setCheckForIdle(boolean check)
{
_endp.setCheckForIdle(check);
}
public boolean isCheckForIdle()
{
return _endp.isCheckForIdle();
}
public String toString()
{
return "Upgradable:"+_endp.toString();
}
}
}

View File

@ -1,111 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.Socket;
import javax.net.SocketFactory;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
{
private static final Logger LOG = Log.getLogger(SocketConnector.class);
/**
*
*/
private final HttpClient _httpClient;
/**
* @param httpClient
*/
SocketConnector(HttpClient httpClient)
{
_httpClient = httpClient;
}
public void startConnection(final HttpDestination destination) throws IOException
{
Socket socket= destination.isSecure()
?_httpClient.getSslContextFactory().newSslSocket()
:SocketFactory.getDefault().createSocket();
socket.setSoTimeout(0);
socket.setTcpNoDelay(true);
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
socket.connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
final EndPoint endpoint=new SocketEndPoint(socket);
final AbstractHttpConnection connection=new BlockingHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
connection.setDestination(destination);
destination.onNewConnection(connection);
_httpClient.getThreadPool().dispatch(new Runnable()
{
public void run()
{
try
{
Connection con = connection;
while(true)
{
final Connection next = con.handle();
if (next!=con)
{
con=next;
continue;
}
break;
}
}
catch (IOException e)
{
if (e instanceof InterruptedIOException)
LOG.ignore(e);
else
{
LOG.debug(e);
destination.onException(e);
}
}
finally
{
try
{
destination.returnConnection(connection,true);
}
catch (IOException e)
{
LOG.debug(e);
}
}
}
});
}
}

View File

@ -1,33 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
/**
* Simple authentication interface that sets required fields on the exchange.
*/
public interface Authentication
{
public void setCredentials( HttpExchange exchange) throws IOException;
}

View File

@ -1,57 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
/**
* Sets authentication headers for BASIC authentication challenges
*
*
*/
public class BasicAuthentication implements Authentication
{
private ByteBuffer _authorization;
public BasicAuthentication(Realm realm) throws IOException
{
String authenticationString = "Basic " + B64Code.encode( realm.getPrincipal() + ":" + realm.getCredentials(), StringUtil.__ISO_8859_1);
_authorization= new ByteArrayBuffer(authenticationString);
}
/**
* BASIC authentication is of the form
*
* encoded credentials are of the form: username:password
*
*
*/
public void setCredentials( HttpExchange exchange ) throws IOException
{
exchange.setRequestHeader( HttpHeader.AUTHORIZATION_BUFFER, _authorization);
}
}

View File

@ -1,141 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.Map;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
public class DigestAuthentication implements Authentication
{
private static final String NC = "00000001";
Realm securityRealm;
Map details;
public DigestAuthentication(Realm realm, Map details)
{
this.securityRealm=realm;
this.details=details;
}
public void setCredentials( HttpExchange exchange )
throws IOException
{
StringBuilder buffer = new StringBuilder().append("Digest");
buffer.append(" ").append("username").append('=').append('"').append(securityRealm.getPrincipal()).append('"');
buffer.append(", ").append("realm").append('=').append('"').append(String.valueOf(details.get("realm"))).append('"');
buffer.append(", ").append("nonce").append('=').append('"').append(String.valueOf(details.get("nonce"))).append('"');
buffer.append(", ").append("uri").append('=').append('"').append(exchange.getURI()).append('"');
buffer.append(", ").append("algorithm").append('=').append(String.valueOf(details.get("algorithm")));
String cnonce = newCnonce(exchange, securityRealm, details);
buffer.append(", ").append("response").append('=').append('"').append(newResponse(cnonce,
exchange, securityRealm, details)).append('"');
buffer.append(", ").append("qop").append('=').append(String.valueOf(details.get("qop")));
buffer.append(", ").append("nc").append('=').append(NC);
buffer.append(", ").append("cnonce").append('=').append('"').append(cnonce).append('"');
exchange.setRequestHeader( HttpHeader.AUTHORIZATION,
new String(buffer.toString().getBytes(StringUtil.__ISO_8859_1)));
}
protected String newResponse(String cnonce, HttpExchange exchange, Realm securityRealm, Map details)
{
try{
MessageDigest md = MessageDigest.getInstance("MD5");
// calc A1 digest
md.update(securityRealm.getPrincipal().getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(String.valueOf(details.get("realm")).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(securityRealm.getCredentials().getBytes(StringUtil.__ISO_8859_1));
byte[] ha1 = md.digest();
// calc A2 digest
md.reset();
md.update(exchange.getMethod().getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(exchange.getURI().getBytes(StringUtil.__ISO_8859_1));
byte[] ha2=md.digest();
md.update(TypeUtil.toString(ha1,16).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(String.valueOf(details.get("nonce")).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(NC.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(cnonce.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(String.valueOf(details.get("qop")).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(TypeUtil.toString(ha2,16).getBytes(StringUtil.__ISO_8859_1));
byte[] digest=md.digest();
// check digest
return encode(digest);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
protected String newCnonce(HttpExchange exchange, Realm securityRealm, Map details)
{
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b= md.digest(String.valueOf(System.currentTimeMillis()).getBytes(StringUtil.__ISO_8859_1));
return encode(b);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
private static String encode(byte[] data)
{
StringBuilder buffer = new StringBuilder();
for (int i=0; i<data.length; i++)
{
buffer.append(Integer.toHexString((data[i] & 0xf0) >>> 4));
buffer.append(Integer.toHexString(data[i] & 0x0f));
}
return buffer.toString();
}
}

View File

@ -1,45 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jetty.client.HttpDestination;
public class HashRealmResolver implements RealmResolver
{
private Map<String, Realm>_realmMap;
public void addSecurityRealm( Realm realm )
{
if (_realmMap == null)
{
_realmMap = new HashMap<String, Realm>();
}
_realmMap.put( realm.getId(), realm );
}
public Realm getRealm( String realmName, HttpDestination destination, String path ) throws IOException
{
return _realmMap.get( realmName );
}
}

View File

@ -1,57 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
/**
* Sets proxy authentication headers for BASIC authentication challenges
*
*
*/
public class ProxyAuthorization implements Authentication
{
private ByteBuffer _authorization;
public ProxyAuthorization(String username,String password) throws IOException
{
String authenticationString = "Basic " + B64Code.encode( username + ":" + password, StringUtil.__ISO_8859_1);
_authorization= new ByteArrayBuffer(authenticationString);
}
/**
* BASIC proxy authentication is of the form
*
* encoded credentials are of the form: username:password
*
*
*/
public void setCredentials( HttpExchange exchange ) throws IOException
{
exchange.setRequestHeader( HttpHeader.PROXY_AUTHORIZATION_BUFFER, _authorization);
}
}

View File

@ -1,32 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
/**
* Simple security realm interface.
*/
public interface Realm
{
public String getId();
public String getPrincipal();
public String getCredentials();
}

View File

@ -1,28 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import org.eclipse.jetty.client.HttpDestination;
public interface RealmResolver
{
public Realm getRealm( String realmName, HttpDestination destination, String path ) throws IOException;
}

View File

@ -1,276 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.jetty.client.HttpDestination;
import org.eclipse.jetty.client.HttpEventListenerWrapper;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* SecurityListener
*
* Allow for insertion of security dialog when performing an
* HttpExchange.
*/
public class SecurityListener extends HttpEventListenerWrapper
{
private static final Logger LOG = Log.getLogger(SecurityListener.class);
private HttpDestination _destination;
private HttpExchange _exchange;
private boolean _requestComplete;
private boolean _responseComplete;
private boolean _needIntercept;
private int _attempts = 0; // TODO remember to settle on winning solution
public SecurityListener(HttpDestination destination, HttpExchange ex)
{
// Start of sending events through to the wrapped listener
// Next decision point is the onResponseStatus
super(ex.getEventListener(),true);
_destination=destination;
_exchange=ex;
}
/**
* scrapes an authentication type from the authString
*
* @param authString
* @return the authentication type
*/
protected String scrapeAuthenticationType( String authString )
{
String authType;
if ( authString.indexOf( " " ) == -1 )
{
authType = authString.toString().trim();
}
else
{
String authResponse = authString.toString();
authType = authResponse.substring( 0, authResponse.indexOf( " " ) ).trim();
}
return authType;
}
/**
* scrapes a set of authentication details from the authString
*
* @param authString
* @return the authentication details
*/
protected Map<String, String> scrapeAuthenticationDetails( String authString )
{
Map<String, String> authenticationDetails = new HashMap<String, String>();
authString = authString.substring( authString.indexOf( " " ) + 1, authString.length() );
StringTokenizer strtok = new StringTokenizer( authString, ",");
while ( strtok.hasMoreTokens() )
{
String token = strtok.nextToken();
String[] pair = token.split( "=" );
// authentication details ought to come in two parts, if not then just skip
if ( pair.length == 2 )
{
String itemName = pair[0].trim();
String itemValue = pair[1].trim();
itemValue = StringUtil.unquote( itemValue );
authenticationDetails.put( itemName, itemValue );
}
else
{
LOG.debug("SecurityListener: missed scraping authentication details - " + token );
}
}
return authenticationDetails;
}
@Override
public void onResponseStatus( ByteBuffer version, int status, ByteBuffer reason )
throws IOException
{
if (LOG.isDebugEnabled())
LOG.debug("SecurityListener:Response Status: " + status );
if ( status == HttpStatus.UNAUTHORIZED_401 && _attempts<_destination.getHttpClient().maxRetries())
{
// Let's absorb events until we have done some retries
setDelegatingResponses(false);
_needIntercept = true;
}
else
{
setDelegatingResponses(true);
setDelegatingRequests(true);
_needIntercept = false;
}
super.onResponseStatus(version,status,reason);
}
@Override
public void onResponseHeader( ByteBuffer name, ByteBuffer value )
throws IOException
{
if (LOG.isDebugEnabled())
LOG.debug( "SecurityListener:Header: " + name.toString() + " / " + value.toString() );
if (!isDelegatingResponses())
{
int header = HttpHeader.CACHE.getOrdinal(name);
switch (header)
{
case HttpHeader.WWW_AUTHENTICATE_ORDINAL:
// TODO don't hard code this bit.
String authString = value.toString();
String type = scrapeAuthenticationType( authString );
// TODO maybe avoid this map creation
Map<String,String> details = scrapeAuthenticationDetails( authString );
String pathSpec="/"; // TODO work out the real path spec
RealmResolver realmResolver = _destination.getHttpClient().getRealmResolver();
if ( realmResolver == null )
{
break;
}
Realm realm = realmResolver.getRealm( details.get("realm"), _destination, pathSpec ); // TODO work our realm correctly
if ( realm == null )
{
LOG.warn( "Unknown Security Realm: " + details.get("realm") );
}
else if ("digest".equalsIgnoreCase(type))
{
_destination.addAuthorization("/",new DigestAuthentication(realm,details));
}
else if ("basic".equalsIgnoreCase(type))
{
_destination.addAuthorization(pathSpec,new BasicAuthentication(realm));
}
break;
}
}
super.onResponseHeader(name,value);
}
@Override
public void onRequestComplete() throws IOException
{
_requestComplete = true;
if (_needIntercept)
{
if (_requestComplete && _responseComplete)
{
if (LOG.isDebugEnabled())
LOG.debug("onRequestComplete, Both complete: Resending from onResponseComplete "+_exchange);
_responseComplete = false;
_requestComplete = false;
setDelegatingRequests(true);
setDelegatingResponses(true);
_destination.resend(_exchange);
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("onRequestComplete, Response not yet complete onRequestComplete, calling super for "+_exchange);
super.onRequestComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("onRequestComplete, delegating to super with Request complete="+_requestComplete+", response complete="+_responseComplete+" "+_exchange);
super.onRequestComplete();
}
}
@Override
public void onResponseComplete() throws IOException
{
_responseComplete = true;
if (_needIntercept)
{
if (_requestComplete && _responseComplete)
{
if (LOG.isDebugEnabled())
LOG.debug("onResponseComplete, Both complete: Resending from onResponseComplete"+_exchange);
_responseComplete = false;
_requestComplete = false;
setDelegatingResponses(true);
setDelegatingRequests(true);
_destination.resend(_exchange);
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("onResponseComplete, Request not yet complete from onResponseComplete, calling super "+_exchange);
super.onResponseComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("OnResponseComplete, delegating to super with Request complete="+_requestComplete+", response complete="+_responseComplete+" "+_exchange);
super.onResponseComplete();
}
}
@Override
public void onRetry()
{
_attempts++;
setDelegatingRequests(true);
setDelegatingResponses(true);
_requestComplete=false;
_responseComplete=false;
_needIntercept=false;
super.onRetry();
}
}

View File

@ -1,44 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import java.io.IOException;
import org.eclipse.jetty.client.HttpDestination;
/**
* Simple Realm Resolver.
* <p> A Realm Resolver that wraps a single realm.
*
*
*/
public class SimpleRealmResolver implements RealmResolver
{
private Realm _realm;
public SimpleRealmResolver( Realm realm )
{
_realm=realm;
}
public Realm getRealm( String realmName, HttpDestination destination, String path ) throws IOException
{
return _realm;
}
}

View File

@ -1,64 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.CachedExchange;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class MkcolExchange extends CachedExchange
{
private static final Logger LOG = Log.getLogger(MkcolExchange.class);
boolean exists = false;
public MkcolExchange()
{
super(true);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if ( status == HttpStatus.CREATED_201 )
{
LOG.debug( "MkcolExchange:Status: Successfully created resource" );
exists = true;
}
if ( status == HttpStatus.METHOD_NOT_ALLOWED_405 ) // returned when resource exists
{
LOG.debug( "MkcolExchange:Status: Resource must exist" );
exists = true;
}
super.onResponseStatus(version, status, reason);
}
public boolean exists()
{
return exists;
}
}

View File

@ -1,57 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class PropfindExchange extends HttpExchange
{
private static final Logger LOG = Log.getLogger(PropfindExchange.class);
boolean _propertyExists = false;
/* ------------------------------------------------------------ */
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if ( status == HttpStatus.OK_200 )
{
LOG.debug( "PropfindExchange:Status: Exists" );
_propertyExists = true;
}
else
{
LOG.debug( "PropfindExchange:Status: Not Exists" );
}
super.onResponseStatus(version, status, reason);
}
public boolean exists()
{
return _propertyExists;
}
}

View File

@ -1,332 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.HttpDestination;
import org.eclipse.jetty.client.HttpEventListenerWrapper;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.client.security.SecurityListener;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* WebdavListener
*
*
*
*
*/
public class WebdavListener extends HttpEventListenerWrapper
{
private static final Logger LOG = Log.getLogger(WebdavListener.class);
private HttpDestination _destination;
private HttpExchange _exchange;
private boolean _requestComplete;
private boolean _responseComplete;
private boolean _webdavEnabled;
private boolean _needIntercept;
public WebdavListener(HttpDestination destination, HttpExchange ex)
{
// Start of sending events through to the wrapped listener
// Next decision point is the onResponseStatus
super(ex.getEventListener(),true);
_destination=destination;
_exchange=ex;
// We'll only enable webdav if this is a PUT request
if ( HttpMethod.PUT.asString().equalsIgnoreCase( _exchange.getMethod() ) )
{
_webdavEnabled = true;
}
}
@Override
public void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if ( !_webdavEnabled )
{
_needIntercept = false;
super.onResponseStatus(version, status, reason);
return;
}
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Response Status: " + status );
// The dav spec says that CONFLICT should be returned when the parent collection doesn't exist but I am seeing
// FORBIDDEN returned instead so running with that.
if ( status == HttpStatus.FORBIDDEN_403 || status == HttpStatus.CONFLICT_409 )
{
if ( _webdavEnabled )
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Response Status: dav enabled, taking a stab at resolving put issue" );
setDelegatingResponses( false ); // stop delegating, we can try and fix this request
_needIntercept = true;
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Response Status: Webdav Disabled" );
setDelegatingResponses( true ); // just make sure we delegate
setDelegatingRequests( true );
_needIntercept = false;
}
}
else
{
_needIntercept = false;
setDelegatingResponses( true );
setDelegatingRequests( true );
}
super.onResponseStatus(version, status, reason);
}
@Override
public void onResponseComplete() throws IOException
{
_responseComplete = true;
if (_needIntercept)
{
if ( _requestComplete && _responseComplete)
{
try
{
// we have some work to do before retrying this
if ( resolveCollectionIssues() )
{
setDelegatingRequests( true );
setDelegatingResponses(true);
_requestComplete = false;
_responseComplete = false;
_destination.resend(_exchange);
}
else
{
// admit defeat but retry because someone else might have
setDelegationResult(false);
setDelegatingRequests( true );
setDelegatingResponses(true);
super.onResponseComplete();
}
}
catch ( IOException ioe )
{
LOG.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate");
super.onResponseComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Not ready, calling super");
super.onResponseComplete();
}
}
else
{
super.onResponseComplete();
}
}
@Override
public void onRequestComplete () throws IOException
{
_requestComplete = true;
if (_needIntercept)
{
if ( _requestComplete && _responseComplete)
{
try
{
// we have some work to do before retrying this
if ( resolveCollectionIssues() )
{
setDelegatingRequests( true );
setDelegatingResponses(true);
_requestComplete = false;
_responseComplete = false;
_destination.resend(_exchange);
}
else
{
// admit defeat but retry because someone else might have
setDelegatingRequests( true );
setDelegatingResponses(true);
super.onRequestComplete();
}
}
catch ( IOException ioe )
{
LOG.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate");
super.onRequestComplete();
}
}
else
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavListener:Not ready, calling super");
super.onRequestComplete();
}
}
else
{
super.onRequestComplete();
}
}
/**
* walk through the steps to try and resolve missing parent collection issues via webdav
*
* TODO this really ought to use URI itself for this resolution
*
* @return
* @throws IOException
*/
private boolean resolveCollectionIssues() throws IOException
{
String uri = _exchange.getURI();
String[] uriCollection = _exchange.getURI().split("/");
int checkNum = uriCollection.length;
int rewind = 0;
String parentUri = URIUtil.parentPath( uri );
while ( parentUri != null && !checkExists(parentUri) )
{
++rewind;
parentUri = URIUtil.parentPath( parentUri );
}
// confirm webdav is supported for this collection
if ( checkWebdavSupported() )
{
for (int i = 0; i < rewind;)
{
makeCollection(parentUri + "/" + uriCollection[checkNum - rewind - 1]);
parentUri = parentUri + "/" + uriCollection[checkNum - rewind - 1];
--rewind;
}
}
else
{
return false;
}
return true;
}
private boolean checkExists( String uri ) throws IOException
{
if (uri == null)
{
System.out.println("have failed miserably");
return false;
}
PropfindExchange propfindExchange = new PropfindExchange();
propfindExchange.setAddress( _exchange.getAddress() );
propfindExchange.setMethod( HttpMethod.GET ); // PROPFIND acts wonky, just use get
propfindExchange.setScheme( _exchange.getScheme() );
propfindExchange.setEventListener( new SecurityListener( _destination, propfindExchange ) );
propfindExchange.setConfigureListeners( false );
propfindExchange.setRequestURI( uri );
_destination.send( propfindExchange );
try
{
propfindExchange.waitForDone();
return propfindExchange.exists();
}
catch ( InterruptedException ie )
{
LOG.ignore( ie );
return false;
}
}
private boolean makeCollection( String uri ) throws IOException
{
MkcolExchange mkcolExchange = new MkcolExchange();
mkcolExchange.setAddress( _exchange.getAddress() );
mkcolExchange.setMethod( "MKCOL " + uri + " HTTP/1.1" );
mkcolExchange.setScheme( _exchange.getScheme() );
mkcolExchange.setEventListener( new SecurityListener( _destination, mkcolExchange ) );
mkcolExchange.setConfigureListeners( false );
mkcolExchange.setRequestURI( uri );
_destination.send( mkcolExchange );
try
{
mkcolExchange.waitForDone();
return mkcolExchange.exists();
}
catch ( InterruptedException ie )
{
LOG.ignore( ie );
return false;
}
}
private boolean checkWebdavSupported() throws IOException
{
WebdavSupportedExchange supportedExchange = new WebdavSupportedExchange();
supportedExchange.setAddress( _exchange.getAddress() );
supportedExchange.setMethod( HttpMethod.OPTIONS );
supportedExchange.setScheme( _exchange.getScheme() );
supportedExchange.setEventListener( new SecurityListener( _destination, supportedExchange ) );
supportedExchange.setConfigureListeners( false );
supportedExchange.setRequestURI( _exchange.getURI() );
_destination.send( supportedExchange );
try
{
supportedExchange.waitTilCompletion();
return supportedExchange.isWebdavSupported();
}
catch (InterruptedException ie )
{
LOG.ignore( ie );
return false;
}
}
}

View File

@ -1,75 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.webdav;
import java.io.IOException;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class WebdavSupportedExchange extends HttpExchange
{
private static final Logger LOG = Log.getLogger(WebdavSupportedExchange.class);
private boolean _webdavSupported = false;
private boolean _isComplete = false;
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (LOG.isDebugEnabled())
LOG.debug("WebdavSupportedExchange:Header:" + name.toString() + " / " + value.toString() );
if ( "DAV".equals( name.toString() ) )
{
if ( value.toString().indexOf( "1" ) >= 0 || value.toString().indexOf( "2" ) >= 0 )
{
_webdavSupported = true;
}
}
super.onResponseHeader(name, value);
}
public void waitTilCompletion() throws InterruptedException
{
synchronized (this)
{
while ( !_isComplete)
{
this.wait();
}
}
}
@Override
protected void onResponseComplete() throws IOException
{
_isComplete = true;
super.onResponseComplete();
}
public boolean isWebdavSupported()
{
return _webdavSupported;
}
}

View File

@ -1,443 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
/**
* @version $Revision$ $Date$
*/
public abstract class AbstractConnectionTest
{
protected HttpClient newHttpClient()
{
HttpClient httpClient = new HttpClient();
// httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
return httpClient;
}
protected ServerSocket newServerSocket() throws IOException
{
ServerSocket serverSocket=new ServerSocket();
serverSocket.bind(null);
return serverSocket;
}
@Test
public void testServerClosedConnection() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
Socket remote = serverSocket.accept();
// HttpClient.send() above is async, so if we write the response immediately
// there is a chance that it arrives before the request is being sent, so we
// read the request before sending the response to avoid the race
InputStream input = remote.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String line;
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
OutputStream output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 0\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
remote.close();
// Need to wait a bit to allow the client to detect
// that the server has closed the connection
Thread.sleep(500);
// The server has closed the connection and another attempt to send
// with the same connection would fail because the connection has been
// closed by the client as well.
// The client must open a new connection in this case, and we check
// that the new request completes correctly
exchange.reset();
httpClient.send(exchange);
remote = serverSocket.accept();
input = remote.getInputStream();
reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 0\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
}
finally
{
httpClient.stop();
}
}
protected String getScheme()
{
return "http";
}
@Test
public void testServerClosedIncomplete() throws Exception
{
ServerSocket serverSocket = newServerSocket();
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setScheme(getScheme());
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
Socket remote = serverSocket.accept();
// HttpClient.send() above is async, so if we write the response immediately
// there is a chance that it arrives before the request is being sent, so we
// read the request before sending the response to avoid the race
InputStream input = remote.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String line;
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
OutputStream output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 10\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
remote.close();
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
}
finally
{
httpClient.stop();
}
}
@Test
public void testServerHalfClosedIncomplete() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setIdleTimeout(10000);
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
Socket remote = serverSocket.accept();
// HttpClient.send() above is async, so if we write the response immediately
// there is a chance that it arrives before the request is being sent, so we
// read the request before sending the response to avoid the race
InputStream input = remote.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String line;
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
OutputStream output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 10\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
remote.shutdownOutput();
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone());
}
finally
{
httpClient.stop();
}
}
@Test
public void testConnectionFailed() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
serverSocket.close();
HttpClient httpClient = newHttpClient();
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
boolean passed = latch.await(4000, TimeUnit.MILLISECONDS);
assertTrue(passed);
long wait = 100;
long maxWait = 10 * wait;
long curWait = wait;
while (curWait < maxWait && !exchange.isDone())
{
Thread.sleep(wait);
curWait += wait;
}
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.getStatus());
}
finally
{
httpClient.stop();
}
}
@Test
public void testMultipleConnectionsFailed() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
serverSocket.close();
HttpClient httpClient = newHttpClient();
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
HttpExchange[] exchanges = new HttpExchange[20];
final CountDownLatch latch = new CountDownLatch(exchanges.length);
for (int i = 0; i < exchanges.length; ++i)
{
HttpExchange exchange = new HttpExchange()
{
@Override
protected void onConnectionFailed(Throwable x)
{
latch.countDown();
}
};
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
exchanges[i] = exchange;
}
for (HttpExchange exchange : exchanges)
httpClient.send(exchange);
for (HttpExchange exchange : exchanges)
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone());
assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
}
finally
{
httpClient.stop();
}
}
@Test
public void testConnectionTimeout() throws Exception
{
HttpClient httpClient = newHttpClient();
int connectTimeout = 5000;
httpClient.setConnectTimeout(connectTimeout);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
// Using a IP address has a different behavior than using a host name
exchange.setAddress(new Address("127.0.0.1", 1));
exchange.setRequestURI("/");
httpClient.send(exchange);
boolean passed = latch.await(connectTimeout * 2L, TimeUnit.MILLISECONDS);
assertTrue(passed);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
}
finally
{
httpClient.stop();
}
}
@Test
public void testIdleConnection() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
httpClient.setIdleTimeout(700);
httpClient.start();
try
{
HttpExchange exchange = new ConnectionExchange();
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
HttpDestination dest = httpClient.getDestination(new Address("localhost", port),false);
httpClient.send(exchange);
Socket server = serverSocket.accept();
server.setSoTimeout(5000);
byte[] buf = new byte[4096];
int len=server.getInputStream().read(buf);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
Thread.sleep(200); // TODO get rid of this
assertEquals(1,dest.getConnections());
assertEquals(1,dest.getIdleConnections());
exchange = new ConnectionExchange();
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
len=server.getInputStream().read(buf);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
Thread.sleep(500);
assertEquals(1,dest.getConnections());
assertEquals(1,dest.getIdleConnections());
Thread.sleep(500);
assertEquals(0,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
serverSocket.close();
}
finally
{
httpClient.stop();
}
}
protected class ConnectionExchange extends HttpExchange
{
private final CountDownLatch latch;
protected ConnectionExchange()
{
this.latch = null;
}
protected ConnectionExchange(CountDownLatch latch)
{
this.latch = latch;
}
@Override
protected void onConnectionFailed(Throwable ex)
{
if (latch!=null)
latch.countDown();
}
@Override
protected void onException(Throwable x)
{
if (latch!=null)
latch.countDown();
}
}
}

View File

@ -1,500 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.net.SocketTimeoutException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AbstractHttpConnection;
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.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
*/
public abstract class AbstractHttpExchangeCancelTest
{
private Server server;
private Connector connector;
@Before
public void setUp() throws Exception
{
server = new Server();
connector = new SelectChannelConnector();
server.addConnector(connector);
server.setHandler(new EmptyHandler());
server.start();
}
@After
public void tearDown() throws Exception
{
server.stop();
server.join();
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnSend1() throws Exception
{
// One of the first things that HttpClient.send() does
// is to change the status of the exchange
// We exploit that to be sure the exchange is canceled
// without race conditions
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
boolean setStatus(int status)
{
// Cancel before setting the new status
if (getStatus() == HttpExchange.STATUS_START &&
status == STATUS_WAITING_FOR_CONNECTION)
cancel();
return super.setStatus(status);
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
// Cancelling here is wrong and makes the test fail spuriously
// due to a race condition with send(): the send() can complete
// before the exchange is canceled so it will be in STATUS_COMPLETE
// which will fail the test.
// exchange.cancel();
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnSend2() throws Exception
{
// One of the first things that HttpClient.send() does
// is to change the status of the exchange
// We exploit that to be sure the exchange is canceled
// without race conditions
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
boolean setStatus(int status)
{
// Cancel after setting the new status
int oldStatus = getStatus();
boolean set = super.setStatus(status);
if (oldStatus == STATUS_START &&
getStatus() == HttpExchange.STATUS_WAITING_FOR_CONNECTION)
cancel();
return set;
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
// Cancelling here is wrong and makes the test fail spuriously
// due to a race condition with send(): the send() can complete
// before the exchange is canceled so it will be in STATUS_COMPLETE
// which will fail the test.
// exchange.cancel();
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnRequestCommitted() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onRequestCommitted() throws IOException
{
super.onRequestCommitted();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnRequestComplete() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onRequestComplete() throws IOException
{
super.onRequestComplete();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertThat("Exchange Status", status, is(HttpExchange.STATUS_CANCELLED));
assertThat("Exchange.isResponseCompleted", exchange.isResponseCompleted(), is(false));
assertThat("Exchange.isFailed", exchange.isFailed(), is(false));
assertThat("Exchange.isAssociated", exchange.isAssociated(), is(false));
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseStatus() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
super.onResponseStatus(version, status, reason);
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseHeader() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
super.onResponseHeader(name, value);
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseHeadersComplete() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseContent() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseContent(ByteBuffer content) throws IOException
{
super.onResponseContent(content);
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/?action=body");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeCancelOnResponseComplete() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
protected void onResponseComplete() throws IOException
{
super.onResponseComplete();
cancel();
}
};
exchange.setAddress(newAddress());
exchange.setRequestURI("/");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertTrue(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
assertEquals(HttpExchange.STATUS_COMPLETED, status);
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeOnServerException() throws Exception
{
try
{
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(true);
TestHttpExchange exchange = new TestHttpExchange();
exchange.setAddress(newAddress());
exchange.setRequestURI("/?action=throw");
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertTrue(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
finally
{
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(false);
}
}
/* ------------------------------------------------------------ */
@Test
public void testHttpExchangeOnExpire() throws Exception
{
HttpClient httpClient = getHttpClient();
httpClient.stop();
httpClient.setTimeout(1000);
httpClient.start();
TestHttpExchange exchange = new TestHttpExchange();
exchange.setAddress(newAddress());
exchange.setRequestURI("/?action=wait5000");
long start = System.currentTimeMillis();
httpClient.send(exchange);
int status = exchange.waitForDone();
long end = System.currentTimeMillis();
assertTrue(HttpExchange.STATUS_EXPIRED==status||HttpExchange.STATUS_EXCEPTED==status);
assertFalse(exchange.isResponseCompleted());
assertTrue(end-start<4000);
assertTrue(exchange.isExpired());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
}
@Test
public void testHttpExchangeCancelReturnsConnection() throws Exception
{
TestHttpExchange exchange = new TestHttpExchange();
Address address = newAddress();
exchange.setAddress(address);
long delay = 5000;
exchange.setRequestURI("/?action=wait" + delay);
HttpClient httpClient = getHttpClient();
HttpDestination destination = httpClient.getDestination(address, false);
int connections = destination.getConnections();
httpClient.send(exchange);
Thread.sleep(delay / 2);
Assert.assertEquals(connections + 1, destination.getConnections());
exchange.cancel();
Assert.assertEquals(connections, destination.getConnections());
}
/* ------------------------------------------------------------ */
protected abstract HttpClient getHttpClient();
/* ------------------------------------------------------------ */
protected Address newAddress()
{
return new Address("localhost", connector.getLocalPort());
}
/* ------------------------------------------------------------ */
private static class EmptyHandler extends AbstractHandler
{
/* ------------------------------------------------------------ */
public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{
request.setHandled(true);
String action = httpRequest.getParameter("action");
if (action != null)
{
if ("body".equals(action))
{
ServletOutputStream output = httpResponse.getOutputStream();
output.write("body".getBytes("UTF-8"));
// output.flush();
}
else if ("throw".equals(action))
{
throw new ServletException();
}
else if (action.startsWith("wait"))
{
long sleep = Long.valueOf(action.substring("wait".length()));
long start=System.currentTimeMillis();
try
{
Thread.sleep(sleep);
long end=System.currentTimeMillis();
assertTrue("Duration "+(end-start)+" >~ "+sleep,(end-start)>sleep-100);
}
catch (InterruptedException x)
{
Thread.currentThread().interrupt();
}
}
}
}
}
/* ------------------------------------------------------------ */
protected static class TestHttpExchange extends ContentExchange
{
private boolean responseCompleted;
private boolean failed = false;
private boolean expired = false;
/* ------------------------------------------------------------ */
protected TestHttpExchange()
{
super(true);
}
/* ------------------------------------------------------------ */
@Override
protected synchronized void onResponseComplete() throws IOException
{
this.responseCompleted = true;
}
/* ------------------------------------------------------------ */
public synchronized boolean isResponseCompleted()
{
return responseCompleted;
}
/* ------------------------------------------------------------ */
@Override
protected synchronized void onException(Throwable ex)
{
LOG.debug(ex);
if (ex instanceof SocketTimeoutException ||
ex.getCause() instanceof SocketTimeoutException)
expired=true;
else
failed = true;
}
/* ------------------------------------------------------------ */
public synchronized boolean isFailed()
{
return failed;
}
/* ------------------------------------------------------------ */
@Override
protected synchronized void onExpire()
{
this.expired = true;
}
/* ------------------------------------------------------------ */
public synchronized boolean isExpired()
{
return expired;
}
}
}

View File

@ -1,110 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* @version $Revision$ $Date$
*/
public class AsyncCallbackHttpExchangeTest
{
/* ------------------------------------------------------------ */
/**
* If the HttpExchange callbacks are called holding the lock on HttpExchange,
* it will be impossible for the callback to perform some work asynchronously
* and contemporarly accessing the HttpExchange instance synchronized state.
* This test verifies that this situation does not happen.
*
* @throws Exception if the test fails
*/
@Test
public void testAsyncCallback() throws Exception
{
ExecutorService executor = Executors.newCachedThreadPool();
try
{
AtomicReference<Exception> failure = new AtomicReference<Exception>();
TestHttpExchange exchange = new TestHttpExchange(executor, failure);
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT);
exchange.setStatus(HttpExchange.STATUS_SENDING_REQUEST);
// This status change triggers onRequestCommitted()
exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
assertNull(failure.get());
}
finally
{
executor.shutdown();
}
}
/* ------------------------------------------------------------ */
private class TestHttpExchange extends HttpExchange
{
private final ExecutorService executor;
private final AtomicReference<Exception> failure;
/* ------------------------------------------------------------ */
private TestHttpExchange(ExecutorService executor, AtomicReference<Exception> failure)
{
this.executor = executor;
this.failure = failure;
}
/* ------------------------------------------------------------ */
@Override
protected void onRequestCommitted() throws IOException
{
Future<Integer> future = executor.submit(new Callable<Integer>()
{
/* ------------------------------------------------------------ */
public Integer call() throws Exception
{
// Method getStatus() reads synchronized state
return TestHttpExchange.this.getStatus();
}
});
// We're waiting for the future to complete, thus never exiting
// this method; if this method is called with the lock held,
// this method never completes
try
{
future.get(1000, TimeUnit.MILLISECONDS);
// Test green here
}
catch (Exception x)
{
// Timed out, the test did not pass
failure.set(x);
}
}
}
}

View File

@ -1,73 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.net.ServerSocket;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.BeforeClass;
public class AsyncSelectConnectionTest extends AbstractConnectionTest
{
protected HttpClient newHttpClient()
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setConnectBlocking(false);
return httpClient;
}
static SslContextFactory ctx = new SslContextFactory(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
@BeforeClass
public static void initKS() throws Exception
{
ctx.setKeyStorePassword("storepwd");
ctx.setKeyManagerPassword("keypwd");
ctx.start();
}
@Override
protected String getScheme()
{
return "https";
}
@Override
protected ServerSocket newServerSocket() throws IOException
{
return ctx.newSslServerSocket(null,0,100);
}
@Override
public void testServerHalfClosedIncomplete() throws Exception
{
// SSL doesn't do half closes
}
@Override
public void testServerClosedIncomplete() throws Exception
{
super.testServerClosedIncomplete();
}
}

View File

@ -1,53 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.junit.Before;
import org.junit.Test;
public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
private static ServerAndClientCreator serverAndClientCreator = new AsyncSslServerAndClientCreator();
@Before
public void setUpOnce() throws Exception
{
_scheme="https";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
@Test
public void testPerf1() throws Exception
{
sender(1,true);
}
@Override
public void testBigPostWithContentExchange() throws Exception
{
super.testBigPostWithContentExchange();
}
}

View File

@ -1,36 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.junit.Before;
/* ------------------------------------------------------------ */
public class AsyncSslSecurityListenerTest extends SslSecurityListenerTest
{
/* ------------------------------------------------------------ */
@Before
@Override
public void setUp() throws Exception
{
_type = HttpClient.CONNECTOR_SELECT_CHANNEL;
super.setUp();
}
}

View File

@ -1,60 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.junit.After;
import org.junit.Before;
/* ------------------------------------------------------------ */
/**
* @version $Revision$ $Date$
*/
public class BlockingHttpExchangeCancelTest extends AbstractHttpExchangeCancelTest
{
private HttpClient httpClient;
/* ------------------------------------------------------------ */
@Before
@Override
public void setUp() throws Exception
{
super.setUp();
httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
httpClient.start();
}
/* ------------------------------------------------------------ */
@After
@Override
public void tearDown() throws Exception
{
httpClient.stop();
super.tearDown();
}
/* ------------------------------------------------------------ */
@Override
protected HttpClient getHttpClient()
{
return httpClient;
}
}

View File

@ -1,140 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
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.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class CachedHeadersIsolationTest
{
Server server;
HttpClient client;
int port;
@Before
public void setUp() throws Exception
{
server = new Server();
Connector connector = new SelectChannelConnector();
server.addConnector(connector);
server.setHandler(new AbstractHandler()
{
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException
{
response.setStatus(HttpStatus.OK_200);
response.addHeader("For",request.getQueryString());
response.addHeader("Name","Value");
response.getOutputStream().print("blah");
response.flushBuffer();
}
});
server.start();
port = server.getConnectors()[0].getLocalPort();
client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setConnectTimeout(5);
client.start();
}
/* ------------------------------------------------------------ */
@After
public void tearDown() throws Exception
{
server.stop();
client.stop();
}
/* ------------------------------------------------------------ */
@Test
public void testHeaderWhenReadEarly() throws Exception
{
CachedExchange e1 = new CachedExchange(true);
CachedExchange e2 = new CachedExchange(true);
e1.setURL("http://localhost:" + port + "/?a=short");
e2.setURL("http://localhost:" + port + "/?a=something_longer");
client.send(e1);
while (!e1.isDone())
Thread.sleep(100);
assertEquals("Read buffer","Value",e1.getResponseFields().getStringField("Name"));
client.send(e2);
while (!e2.isDone())
Thread.sleep(100);
assertEquals("Overwritten buffer","Value",e1.getResponseFields().getStringField("Name"));
}
/* ------------------------------------------------------------ */
@Test
public void testHeaderWhenReadLate() throws Exception
{
CachedExchange e1 = new CachedExchange(true);
CachedExchange e2 = new CachedExchange(true);
e1.setURL("http://localhost:" + port + "/?a=short");
e2.setURL("http://localhost:" + port + "/?a=something_longer");
client.send(e1);
while (!e1.isDone())
Thread.sleep(100);
client.send(e2);
while (!e2.isDone())
Thread.sleep(100);
for ( Enumeration<String> e = e1.getResponseFields().getValues("Name"); e.hasMoreElements();)
{
System.out.println(e.nextElement());
}
assertEquals("Overwritten buffer","Value",e1.getResponseFields().getStringField("Name"));
}
}

View File

@ -1,389 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.IO;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ContentExchangeTest
{
private static String _content =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
"Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+
"at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+
"velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+
"Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+
"eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+
"sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+
"consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private File _docRoot;
private Server _server;
private HttpClient _client;
private Realm _realm;
private String _protocol;
private String _baseUrl;
private String _requestContent;
/* ------------------------------------------------------------ */
@Before
public void setUp()
throws Exception
{
_docRoot = new File("target/test-output/docroot/");
_docRoot.mkdirs();
_docRoot.deleteOnExit();
File content = new File(_docRoot,"input.txt");
FileOutputStream out = new FileOutputStream(content);
out.write(_content.getBytes("utf-8"));
out.close();
_server = new Server();
configureServer(_server);
_server.start();
int port = _server.getConnectors()[0].getLocalPort();
_baseUrl = _protocol+"://localhost:"+port+ "/";
}
/* ------------------------------------------------------------ */
@After
public void tearDown()
throws Exception
{
if (_server != null)
{
_server.stop();
_server = null;
}
}
/* ------------------------------------------------------------ */
@Test
public void testPut() throws Exception
{
startClient(_realm);
ContentExchange putExchange = new ContentExchange();
putExchange.setURL(getBaseUrl() + "output.txt");
putExchange.setMethod(HttpMethod.PUT);
putExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes()));
_client.send(putExchange);
int state = putExchange.waitForDone();
int responseStatus = putExchange.getResponseStatus();
stopClient();
boolean statusOk = (responseStatus == 200 || responseStatus == 201);
assertTrue(statusOk);
String content = IO.toString(new FileInputStream(new File(_docRoot,"output.txt")));
assertEquals(_content,content);
}
/* ------------------------------------------------------------ */
@Test
public void testGet() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(getBaseUrl() + "input.txt");
getExchange.setMethod(HttpMethod.GET);
_client.send(getExchange);
int state = getExchange.waitForDone();
String content = "";
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
assertEquals(_content,content);
}
/* ------------------------------------------------------------ */
@Test
public void testHead() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(getBaseUrl() + "input.txt");
getExchange.setMethod(HttpMethod.HEAD);
_client.send(getExchange);
getExchange.waitForDone();
int responseStatus = getExchange.getResponseStatus();
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
}
/* ------------------------------------------------------------ */
@Test
public void testPost() throws Exception
{
startClient(_realm);
ContentExchange postExchange = new ContentExchange();
postExchange.setURL(getBaseUrl() + "test");
postExchange.setMethod(HttpMethod.POST);
postExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes()));
_client.send(postExchange);
int state = postExchange.waitForDone();
int responseStatus = postExchange.getResponseStatus();
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
assertEquals(_content,_requestContent);
}
/* ------------------------------------------------------------ */
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
Handler handler = new TestHandler(getBasePath());
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(_docRoot.getAbsolutePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
server.setHandler( handlers );
}
/* ------------------------------------------------------------ */
protected void startClient(Realm realm)
throws Exception
{
_client = new HttpClient();
configureClient(_client);
if (realm != null)
_client.setRealmResolver(new SimpleRealmResolver(realm));
_client.start();
}
/* ------------------------------------------------------------ */
protected void configureClient(HttpClient client)
throws Exception
{
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
}
/* ------------------------------------------------------------ */
protected void stopClient()
throws Exception
{
if (_client != null)
{
_client.stop();
_client = null;
}
}
/* ------------------------------------------------------------ */
protected String getBasePath()
{
return _docRoot.getAbsolutePath();
}
/* ------------------------------------------------------------ */
protected String getBaseUrl()
{
return _baseUrl;
}
/* ------------------------------------------------------------ */
protected HttpClient getClient()
{
return _client;
}
/* ------------------------------------------------------------ */
protected Realm getRealm()
{
return _realm;
}
/* ------------------------------------------------------------ */
protected String getContent()
{
return _content;
}
/* ------------------------------------------------------------ */
protected void setProtocol(String protocol)
{
_protocol = protocol;
}
/* ------------------------------------------------------------ */
protected void setRealm(Realm realm)
{
_realm = realm;
}
/* ------------------------------------------------------------ */
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer=new byte[1024];
int len;
while ((len=in.read(buffer))>=0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println(e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/* ------------------------------------------------------------ */
protected class TestHandler extends AbstractHandler {
private final String resourcePath;
/* ------------------------------------------------------------ */
public TestHandler(String repositoryPath) {
this.resourcePath = repositoryPath;
}
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if (baseRequest.isHandled())
{
return;
}
OutputStream out = null;
if (baseRequest.getMethod().equals("PUT"))
{
baseRequest.setHandled(true);
File file = new File(resourcePath, URLDecoder.decode(request.getPathInfo()));
file.getParentFile().mkdirs();
file.deleteOnExit();
out = new FileOutputStream(file);
response.setStatus(HttpServletResponse.SC_CREATED);
}
if (baseRequest.getMethod().equals("POST"))
{
baseRequest.setHandled(true);
out = new ByteArrayOutputStream();
response.setStatus(HttpServletResponse.SC_OK);
}
if (out != null)
{
ServletInputStream in = request.getInputStream();
try
{
copyStream( in, out );
}
finally
{
in.close();
out.close();
}
if (!(out instanceof FileOutputStream))
_requestContent = out.toString();
}
}
}
}

View File

@ -1,200 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpMethod;
/* ------------------------------------------------------------ */
/** A simple test http client like curl.
* <p>
* Usage is java -cp $CLASSPATH org.eclipse.jetty.client.Curl [ option | URL ] ...
* Options supported are: <ul>
* <li>--async : The following URLs are fetched in parallel (default)
* <li>--sync : The following URLs are fetched in sequence
* <li>--dump : The content is dumped to stdout
* <li>--nodump : The content is suppressed (default)
* </ul>
*/
public class Curl
{
public static void main(String[] args)
throws Exception
{
if (args.length==0)
args=new String[]
{ "--sync", "http://www.sun.com/robots.txt", "http://www.sun.com/favicon.ico" , "--dump", "http://www.sun.com/robots.txt"};
HttpClient client = new HttpClient();
client.setIdleTimeout(2000);
client.start();
boolean async=true;
boolean dump= false;
boolean verbose= false;
int urls=0;
for (String arg : args)
{
if (!arg.startsWith("-"))
urls++;
}
final CountDownLatch latch = new CountDownLatch(urls);
for (String arg : args)
{
if ("--verbose".equals(arg))
{
verbose=true;
continue;
}
if ("--sync".equals(arg))
{
async=false;
continue;
}
if ("--async".equals(arg))
{
async=true;
continue;
}
if ("--dump".equals(arg))
{
dump=true;
continue;
}
if ("--nodump".equals(arg))
{
dump=false;
continue;
}
final boolean d = dump;
final boolean v = verbose;
HttpExchange ex = new HttpExchange()
{
AtomicBoolean counted=new AtomicBoolean(false);
@Override
protected void onConnectionFailed(Throwable ex)
{
if (!counted.getAndSet(true))
latch.countDown();
super.onConnectionFailed(ex);
}
@Override
protected void onException(Throwable ex)
{
if (!counted.getAndSet(true))
latch.countDown();
super.onException(ex);
}
@Override
protected void onExpire()
{
if (!counted.getAndSet(true))
latch.countDown();
super.onExpire();
}
@Override
protected void onResponseComplete() throws IOException
{
if (!counted.getAndSet(true))
latch.countDown();
super.onResponseComplete();
}
@Override
protected void onResponseContent(ByteBuffer content) throws IOException
{
super.onResponseContent(content);
if (d)
System.out.print(content.toString());
if (v)
System.err.println("got "+content.length());
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.ByteBuffer, org.eclipse.jetty.io.ByteBuffer)
*/
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
super.onResponseHeader(name,value);
if (v)
System.err.println(name+": "+value);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete()
*/
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
if (v)
System.err.println();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.ByteBuffer, int, org.eclipse.jetty.io.ByteBuffer)
*/
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
super.onResponseStatus(version,status,reason);
if (v)
System.err.println(version+" "+status+" "+reason);
}
};
ex.setMethod(HttpMethod.GET);
ex.setURL(arg);
System.err.println("\nSending "+ex);
client.send(ex);
if (!async)
{
System.err.println("waiting...");
ex.waitForDone();
System.err.println("Done");
}
}
latch.await();
}
}

View File

@ -1,276 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class ErrorStatusTest
extends ContentExchangeTest
{
/* ------------------------------------------------------------ */
@Test
public void testPutBadRequest()
throws Exception
{
doPutFail(HttpStatus.BAD_REQUEST_400);
}
/* ------------------------------------------------------------ */
@Test
public void testPutUnauthorized()
throws Exception
{
doPutFail(HttpStatus.UNAUTHORIZED_401);
}
/* ------------------------------------------------------------ */
@Test
public void testPutForbidden()
throws Exception
{
doPutFail(HttpStatus.FORBIDDEN_403);
}
/* ------------------------------------------------------------ */
@Test
public void testPutNotFound()
throws Exception
{
doPutFail(HttpStatus.NOT_FOUND_404);
}
/* ------------------------------------------------------------ */
@Test
public void testPutServerError()
throws Exception
{
doPutFail(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
/* ------------------------------------------------------------ */
@Test
public void testGetBadRequest()
throws Exception
{
doGetFail(HttpStatus.BAD_REQUEST_400);
}
/* ------------------------------------------------------------ */
@Test
public void testGetUnauthorized()
throws Exception
{
doGetFail(HttpStatus.UNAUTHORIZED_401);
}
/* ------------------------------------------------------------ */
@Test
public void testGetNotFound()
throws Exception
{
doGetFail(HttpStatus.NOT_FOUND_404);
}
/* ------------------------------------------------------------ */
@Test
public void testGetServerError()
throws Exception
{
doGetFail(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
/* ------------------------------------------------------------ */
@Test
public void testPostBadRequest()
throws Exception
{
doPostFail(HttpStatus.BAD_REQUEST_400);
}
/* ------------------------------------------------------------ */
@Test
public void testPostUnauthorized()
throws Exception
{
doPostFail(HttpStatus.UNAUTHORIZED_401);
}
/* ------------------------------------------------------------ */
@Test
public void testPostForbidden()
throws Exception
{
doPostFail(HttpStatus.FORBIDDEN_403);
}
/* ------------------------------------------------------------ */
@Test
public void testPostNotFound()
throws Exception
{
doPostFail(HttpStatus.NOT_FOUND_404);
}
/* ------------------------------------------------------------ */
@Test
public void testPostServerError()
throws Exception
{
doPostFail(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
/* ------------------------------------------------------------ */
protected void doPutFail(int status)
throws Exception
{
startClient(getRealm());
ContentExchange putExchange = new ContentExchange();
putExchange.setURL(getBaseUrl() + "output.txt");
putExchange.setMethod(HttpMethod.PUT);
putExchange.setRequestHeader("X-Response-Status",Integer.toString(status));
putExchange.setRequestContent(new ByteArrayBuffer(getContent().getBytes()));
getClient().send(putExchange);
int state = putExchange.waitForDone();
int responseStatus = putExchange.getResponseStatus();
stopClient();
assertEquals(status, responseStatus);
}
/* ------------------------------------------------------------ */
protected void doGetFail(int status)
throws Exception
{
startClient(getRealm());
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(getBaseUrl() + "input.txt");
getExchange.setMethod(HttpMethod.GET);
getExchange.setRequestHeader("X-Response-Status",Integer.toString(status));
getClient().send(getExchange);
int state = getExchange.waitForDone();
String content;
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200) {
content = getExchange.getResponseContent();
}
stopClient();
assertEquals(status, responseStatus);
}
/* ------------------------------------------------------------ */
protected void doPostFail(int status)
throws Exception
{
startClient(getRealm());
ContentExchange postExchange = new ContentExchange();
postExchange.setURL(getBaseUrl() + "test");
postExchange.setMethod(HttpMethod.POST);
postExchange.setRequestHeader("X-Response-Status",Integer.toString(status));
postExchange.setRequestContent(new ByteArrayBuffer(getContent().getBytes()));
getClient().send(postExchange);
int state = postExchange.waitForDone();
int responseStatus = postExchange.getResponseStatus();
stopClient();
assertEquals(status, responseStatus);
}
/* ------------------------------------------------------------ */
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
Handler status = new StatusHandler();
Handler test = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{status, test, root});
server.setHandler( handlers );
}
/* ------------------------------------------------------------ */
protected static class StatusHandler extends AbstractHandler {
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if (baseRequest.isHandled())
return;
int statusValue = 0;
String statusHeader = request.getHeader("X-Response-Status");
if (statusHeader != null)
{
statusValue = Integer.parseInt(statusHeader);
}
if (statusValue != 0)
{
response.setStatus(statusValue);
baseRequest.setHandled(true);
}
}
}
}

View File

@ -1,197 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Ignore;
public class ExpirationWithLimitedConnectionsTest
{
@Ignore
public void testExpirationWithMaxConnectionPerAddressReached() throws Exception
{
final Logger logger = Log.getLogger("org.eclipse.jetty.client");
logger.setDebugEnabled(true);
HttpClient client = new HttpClient();
int maxConnectionsPerAddress = 10;
client.setMaxConnectionsPerAddress(maxConnectionsPerAddress);
long timeout = 1000;
client.setTimeout(timeout);
client.start();
final List<Socket> sockets = new CopyOnWriteArrayList<Socket>();
final List<Exception> failures = new CopyOnWriteArrayList<Exception>();
final AtomicLong processingDelay = new AtomicLong(200);
final ExecutorService threadPool = Executors.newCachedThreadPool();
final ServerSocket server = new ServerSocket(0);
threadPool.submit(new Runnable()
{
public void run()
{
while (true)
{
try
{
final Socket socket = server.accept();
sockets.add(socket);
logger.debug("CONNECTION {}", socket.getRemoteSocketAddress());
threadPool.submit(new Runnable()
{
public void run()
{
while (true)
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
String firstLine = reader.readLine();
String line = firstLine;
while (line != null)
{
if (line.length() == 0)
break;
line = reader.readLine();
}
if (line == null)
break;
long sleep = processingDelay.get();
logger.debug("{} {} {} ms", firstLine, socket.getRemoteSocketAddress(), sleep);
TimeUnit.MILLISECONDS.sleep(sleep);
String response = "" +
"HTTP/1.1 200 OK\r\n" +
"Content-Length: 0\r\n" +
"\r\n";
OutputStream output = socket.getOutputStream();
output.write(response.getBytes("UTF-8"));
output.flush();
}
catch (Exception x)
{
failures.add(x);
break;
}
}
}
});
}
catch (Exception x)
{
failures.add(x);
break;
}
}
}
});
List<ContentExchange> exchanges = new ArrayList<ContentExchange>();
final AtomicBoolean firstExpired = new AtomicBoolean();
int count = 0;
int maxAdditionalRequest = 100;
int additionalRequests = 0;
while (true)
{
TimeUnit.MILLISECONDS.sleep(1); // Just avoid being too fast
ContentExchange exchange = new ContentExchange(true)
{
@Override
protected void onResponseComplete() throws IOException
{
logger.debug("{} {} OK", getMethod(), getRequestURI());
}
@Override
protected void onExpire()
{
logger.debug("{} {} EXPIRED {}", getMethod(), getRequestURI(), this);
firstExpired.compareAndSet(false, true);
}
};
exchanges.add(exchange);
Address address = new Address("localhost", server.getLocalPort());
exchange.setAddress(address);
exchange.setMethod("GET");
exchange.setRequestURI("/" + count);
exchange.setVersion("HTTP/1.1");
exchange.setRequestHeader("Host", address.toString());
logger.debug("{} {} SENT", exchange.getMethod(), exchange.getRequestURI());
client.send(exchange);
++count;
if (processingDelay.get() > 0)
{
if (client.getDestination(address, false).getConnections() == maxConnectionsPerAddress)
{
if (firstExpired.get())
{
++additionalRequests;
if (additionalRequests == maxAdditionalRequest)
processingDelay.set(0);
}
}
}
else
{
++additionalRequests;
if (additionalRequests == 2 * maxAdditionalRequest)
break;
}
}
for (ContentExchange exchange : exchanges)
{
int status = exchange.waitForDone();
Assert.assertTrue(status == HttpExchange.STATUS_COMPLETED || status == HttpExchange.STATUS_EXPIRED);
}
client.stop();
Assert.assertTrue(failures.isEmpty());
for (Socket socket : sockets)
socket.close();
server.close();
threadPool.shutdown();
threadPool.awaitTermination(5, TimeUnit.SECONDS);
}
}

View File

@ -1,117 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
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.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.After;
import org.junit.Before;
import org.junit.Test;
/**
* Test contributed by: Michiel Thuys for JETTY-806
*/
public class ExpireTest
{
private Server server;
private HttpClient client;
private int port;
@Before
public void init() throws Exception
{
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setHost("localhost");
connector.setPort(0);
server.addConnector(connector);
server.setHandler(new AbstractHandler()
{
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws IOException, ServletException
{
request.setHandled(true);
try
{
Thread.sleep(2000);
}
catch (InterruptedException x)
{
}
}
});
server.start();
port = connector.getLocalPort();
client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setTimeout(200);
client.setMaxRetries(0);
client.setMaxConnectionsPerAddress(100);
client.start();
}
@After
public void destroy() throws Exception
{
client.stop();
server.stop();
server.join();
}
@Test
public void testExpire() throws Exception
{
String baseUrl = "http://" + "localhost" + ":" + port + "/";
int count = 200;
final CountDownLatch expires = new CountDownLatch(count);
for (int i=0;i<count;i++)
{
final ContentExchange exchange = new ContentExchange()
{
@Override
protected void onExpire()
{
expires.countDown();
}
};
exchange.setMethod("GET");
exchange.setURL(baseUrl);
client.send(exchange);
}
// Wait to be sure that all exchanges have expired
assertTrue(expires.await(5, TimeUnit.SECONDS));
}
}

View File

@ -1,37 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.eclipse.jetty.client.helperClasses.ExternalKeyStoreAsyncSslServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.junit.Before;
public class ExternalKeyStoreAsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
private static ServerAndClientCreator serverAndClientCreator = new ExternalKeyStoreAsyncSslServerAndClientCreator();
@Before
public void setUpOnce() throws Exception
{
_scheme="https";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
}

View File

@ -1,245 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
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.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
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.eclipse.jetty.util.log.Log;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class Http100ContinueTest
{
private static final int TIMEOUT = 500;
private static final String CONTENT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "
+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "
+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "
+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "
+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "
+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "
+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "
+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "
+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "
+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "
+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private static TestFeature _feature;
private static Server _server;
private static TestHandler _handler;
private static HttpClient _client;
private static String _requestUrl;
@BeforeClass
public static void init() throws Exception
{
File docRoot = new File("target/test-output/docroot/");
if (!docRoot.exists())
assertTrue(docRoot.mkdirs());
docRoot.deleteOnExit();
_server = new Server();
Connector connector = new SelectChannelConnector();
_server.addConnector(connector);
_handler = new TestHandler();
_server.setHandler(_handler);
_server.start();
_client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_client.setTimeout(TIMEOUT);
_client.setMaxRetries(0);
_client.start();
_requestUrl = "http://localhost:" + connector.getLocalPort() + "/";
}
@AfterClass
public static void destroy() throws Exception
{
_client.stop();
_server.stop();
_server.join();
}
@Test
public void testSuccess() throws Exception
{
// Handler to send CONTINUE 100
_feature = TestFeature.CONTINUE;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(Http100ContinueTest.CONTENT,content);
}
@Test
public void testMissingContinue() throws Exception
{
// Handler does not send CONTINUE 100
_feature = TestFeature.NORMAL;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(Http100ContinueTest.CONTENT,content);
}
@Test
public void testError() throws Exception
{
// Handler sends NOT FOUND 404 response
_feature = TestFeature.NOTFOUND;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.NOT_FOUND_404,responseStatus);
}
@Test
public void testTimeout() throws Exception
{
// Handler delays response till client times out
_feature = TestFeature.TIMEOUT;
final CountDownLatch expires = new CountDownLatch(1);
ContentExchange exchange = new ContentExchange()
{
@Override
protected void onExpire()
{
expires.countDown();
}
};
configureExchange(exchange);
_client.send(exchange);
assertTrue(expires.await(TIMEOUT*10,TimeUnit.MILLISECONDS));
}
public ContentExchange sendExchange() throws Exception
{
ContentExchange exchange = new ContentExchange();
configureExchange(exchange);
_client.send(exchange);
return exchange;
}
public void configureExchange(ContentExchange exchange)
{
exchange.setURL(_requestUrl);
exchange.setMethod(HttpMethod.GET);
exchange.addRequestHeader("User-Agent","Jetty-Client/7.0");
exchange.addRequestHeader("Expect","100-continue"); //server to send CONTINUE 100
}
private static class TestHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (baseRequest.isHandled())
return;
baseRequest.setHandled(true);
switch (_feature)
{
case CONTINUE:
// force 100 Continue response to be sent
request.getInputStream();
// next send data
case NORMAL:
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(CONTENT);
break;
case NOTFOUND:
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
break;
case TIMEOUT:
try
{
Thread.sleep(TIMEOUT*4);
}
catch (InterruptedException ex)
{
Log.ignore(ex);
}
break;
}
}
}
enum TestFeature {
CONTINUE,
NORMAL,
NOTFOUND,
TIMEOUT
}
}

View File

@ -1,47 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.util.Collections;
import java.util.List;
import org.eclipse.jetty.http.HttpFields;
import org.junit.Assert;
public final class HttpAsserts
{
public static void assertContainsHeaderKey(String expectedKey, HttpFields headers)
{
if (headers.containsKey(expectedKey))
{
return;
}
List<String> names = Collections.list(headers.getFieldNames());
StringBuilder err = new StringBuilder();
err.append("Missing expected header key [").append(expectedKey);
err.append("] (of ").append(names.size()).append(" header fields)");
for (int i = 0; i < names.size(); i++)
{
String value = headers.getStringField(names.get(i));
err.append("\n").append(i).append("] ").append(names.get(i));
err.append(": ").append(value);
}
Assert.fail(err.toString());
}
}

View File

@ -1,225 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.RejectedExecutionException;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
public class HttpDestinationQueueTest
{
private static HttpClient _httpClient;
private static long _timeout = 200;
@BeforeClass
public static void beforeOnce() throws Exception
{
_httpClient = new HttpClient();
_httpClient.setMaxConnectionsPerAddress(1);
_httpClient.setMaxQueueSizePerAddress(1);
_httpClient.setTimeout(_timeout);
_httpClient.start();
}
@Test
public void testDestinationMaxQueueSize() throws Exception
{
ServerSocket server = new ServerSocket(0);
// This will keep the connection busy
HttpExchange exchange1 = new HttpExchange();
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// This will be queued
HttpExchange exchange2 = new HttpExchange();
exchange2.setMethod("GET");
exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2");
_httpClient.send(exchange2);
// This will be rejected, since the connection is busy and the queue is full
HttpExchange exchange3 = new HttpExchange();
exchange3.setMethod("GET");
exchange3.setURL("http://localhost:" + server.getLocalPort() + "/exchange3");
try
{
_httpClient.send(exchange3);
Assert.fail();
}
catch (RejectedExecutionException x)
{
// Expected
}
// Send the response to avoid exceptions in the console
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8"));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone());
// Be sure that the second exchange can be sent
request.setLength(0);
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange2"));
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n".getBytes("UTF-8"));
socket.close();
Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange2.waitForDone());
server.close();
}
@Test
public void testDefaultTimeoutIncludesQueuingExchangeExpiresInQueue() throws Exception
{
ServerSocket server = new ServerSocket(0);
// This will keep the connection busy
HttpExchange exchange1 = new HttpExchange();
exchange1.setTimeout(_timeout * 3); // Be sure it does not expire
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// This will be queued
HttpExchange exchange2 = new HttpExchange();
exchange2.setMethod("GET");
exchange2.setURL("http://localhost:" + server.getLocalPort() + "/exchange2");
_httpClient.send(exchange2);
// Wait until the queued exchange times out in the queue
Thread.sleep(_timeout * 2);
Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange2.getStatus());
// Send the response to the first exchange to avoid exceptions in the console
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes("UTF-8"));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED,exchange1.waitForDone());
socket.close();
server.close();
}
@Test
public void testDefaultTimeoutIncludesQueuingExchangeExpiresDuringRequest() throws Exception
{
ServerSocket server = new ServerSocket(0);
HttpExchange exchange1 = new HttpExchange();
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// Wait until the exchange times out during the request
Thread.sleep(_timeout * 2);
Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus());
socket.close();
server.close();
}
@Test
public void testExchangeTimeoutIncludesQueuingExchangeExpiresDuringResponse() throws Exception
{
ServerSocket server = new ServerSocket(0);
long timeout = 1000;
HttpExchange exchange1 = new HttpExchange();
exchange1.setTimeout(timeout);
exchange1.setMethod("GET");
exchange1.setURL("http://localhost:" + server.getLocalPort() + "/exchange1");
_httpClient.send(exchange1);
// Read request so we are sure that this exchange is out of the queue
Socket socket = server.accept();
byte[] buffer = new byte[1024];
StringBuilder request = new StringBuilder();
while (true)
{
int read = socket.getInputStream().read(buffer);
request.append(new String(buffer,0,read,"UTF-8"));
if (request.toString().endsWith("\r\n\r\n"))
break;
}
Assert.assertTrue(request.toString().contains("exchange1"));
// Write part of the response
socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: 1\r\n\r\n".getBytes("UTF-8"));
// Wait until the exchange times out during the response
Thread.sleep(timeout * 2);
Assert.assertEquals(HttpExchange.STATUS_EXPIRED,exchange1.getStatus());
socket.close();
server.close();
}
}

View File

@ -1,699 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.matchers.JUnitMatchers.containsString;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.client.helperClasses.HttpServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.eclipse.jetty.client.security.ProxyAuthorization;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.Stress;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* Functional testing for HttpExchange.
*/
public class HttpExchangeTest
{
final static boolean verbose=HttpExchange.LOG.isDebugEnabled();
protected static int _maxConnectionsPerAddress = 2;
protected static String _scheme = "http";
protected static Server _server;
protected static int _port;
protected static HttpClient _httpClient;
protected static AtomicInteger _count = new AtomicInteger();
protected static ServerAndClientCreator serverAndClientCreator = new HttpServerAndClientCreator();
protected static URI getBaseURI()
{
return URI.create(_scheme + "://localhost:" + _port + "/");
}
/* ------------------------------------------------------------ */
// TODO work out why BeforeClass does not work here?
@Before
public void setUpOnce() throws Exception
{
_scheme = "http";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
/* ------------------------------------------------------------ */
@After
public void tearDownOnce() throws Exception
{
_httpClient.stop();
long startTime = System.currentTimeMillis();
while (!_httpClient.getState().equals(AbstractLifeCycle.STOPPED))
{
if (System.currentTimeMillis() - startTime > 1000)
break;
Thread.sleep(5);
}
_server.stop();
}
/* ------------------------------------------------------------ */
@Test
public void testResetNewExchange() throws Exception
{
HttpExchange exchange = new HttpExchange();
exchange.reset();
}
/* ------------------------------------------------------------ */
@Test
public void testPerf() throws Exception
{
sender(1,false);
sender(1,true);
sender(10,false);
sender(10,true);
if (Stress.isEnabled())
{
sender(100,false);
sender(100,true);
sender(10000,false);
sender(10000,true);
}
}
/* ------------------------------------------------------------ */
/**
* Test sending data through the exchange.
*
* @throws IOException
*/
public void sender(final int nb, final boolean close) throws Exception
{
// System.err.printf("%nSENDER %d %s%n",nb,close);
_count.set(0);
final CountDownLatch complete = new CountDownLatch(nb);
final AtomicInteger allcontent = new AtomicInteger(nb);
HttpExchange[] httpExchange = new HttpExchange[nb];
long start = System.currentTimeMillis();
for (int i = 0; i < nb; i++)
{
final int n = i;
httpExchange[n] = new HttpExchange()
{
String result = "pending";
int len = 0;
/* ------------------------------------------------------------ */
@Override
protected void onRequestCommitted()
{
if (verbose)
System.err.println(n+" [ "+this);
result = "committed";
}
/* ------------------------------------------------------------ */
@Override
protected void onRequestComplete() throws IOException
{
if (verbose)
System.err.println(n+" [ ==");
result = "sent";
}
@Override
/* ------------------------------------------------------------ */
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason)
{
if (verbose)
System.err.println(n+" ] "+version+" "+status+" "+reason);
result = "status";
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value)
{
if (verbose)
System.err.println(n+" ] "+name+": "+value);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseHeaderComplete() throws IOException
{
if (verbose)
System.err.println(n+" ] -");
result = "content";
super.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseContent(ByteBuffer content)
{
len += content.length();
if (verbose)
System.err.println(n+" ] "+content.length()+" -> "+len);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseComplete()
{
if (verbose)
System.err.println(n+" ] == "+len+" "+complete.getCount()+"/"+nb);
result = "complete";
if (len == 2009)
allcontent.decrementAndGet();
else
System.err.println(n+ " ONLY " + len+ "/2009");
complete.countDown();
}
/* ------------------------------------------------------------ */
@Override
protected void onConnectionFailed(Throwable ex)
{
if (verbose)
System.err.println(n+" ] "+ex);
complete.countDown();
result = "failed";
System.err.println(n+ " FAILED " + ex);
super.onConnectionFailed(ex);
}
/* ------------------------------------------------------------ */
@Override
protected void onException(Throwable ex)
{
if (verbose)
System.err.println(n+" ] "+ex);
complete.countDown();
result = "excepted";
System.err.println(n+ " EXCEPTED " + ex);
super.onException(ex);
}
/* ------------------------------------------------------------ */
@Override
protected void onExpire()
{
if (verbose)
System.err.println(n+" ] expired");
complete.countDown();
result = "expired";
System.err.println(n + " EXPIRED " + len);
super.onExpire();
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return n+"/"+result+"/"+len+"/"+super.toString();
}
};
httpExchange[n].setURI(getBaseURI().resolve("/" + n));
httpExchange[n].addRequestHeader("arbitrary","value");
if (close)
httpExchange[n].setRequestHeader("Connection","close");
_httpClient.send(httpExchange[n]);
}
if (!complete.await(2,TimeUnit.SECONDS))
System.err.println(_httpClient.dump());
assertTrue(complete.await(20,TimeUnit.SECONDS));
assertEquals("nb="+nb+" close="+close,0,allcontent.get());
}
/* ------------------------------------------------------------ */
@Test
public void testPostWithContentExchange() throws Exception
{
for (int i=0;i<20;i++)
{
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<hello />"));
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertEquals("i="+i,"<hello />",result);
}
}
/* ------------------------------------------------------------ */
@Test
public void testGetWithContentExchange() throws Exception
{
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
URI uri = getBaseURI().resolve("?i=" + i);
httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf("<hello>"));
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
Thread.sleep(5);
}
}
/* ------------------------------------------------------------ */
@Test
public void testLocalAddressAvailabilityWithContentExchange() throws Exception
{
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
URI uri = getBaseURI().resolve("?i=" + i);
httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
assertNotNull(httpExchange.getLocalAddress());
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf("<hello>"));
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
Thread.sleep(5);
}
}
/* ------------------------------------------------------------ */
@Test
public void testShutdownWithExchange() throws Exception
{
final AtomicReference<Throwable> throwable=new AtomicReference<Throwable>();
HttpExchange httpExchange=new HttpExchange()
{
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onException(java.lang.Throwable)
*/
@Override
protected void onException(Throwable x)
{
throwable.set(x);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onConnectionFailed(java.lang.Throwable)
*/
@Override
protected void onConnectionFailed(Throwable x)
{
throwable.set(x);
}
};
httpExchange.setURI(getBaseURI());
httpExchange.setMethod("SLEEP");
_httpClient.send(httpExchange);
new Thread()
{
@Override
public void run()
{
try {
Thread.sleep(500);
_httpClient.stop();
} catch(Exception e) {e.printStackTrace();}
}
}.start();
int status = httpExchange.waitForDone();
System.err.println(throwable.get());
assertTrue(throwable.get().toString().indexOf("close")>=0);
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
_httpClient.start();
}
/* ------------------------------------------------------------ */
@Test
public void testBigPostWithContentExchange() throws Exception
{
int size =32;
ContentExchange httpExchange=new ContentExchange()
{
int total;
@Override
protected synchronized void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
if (verbose)
System.err.println("] "+version+" "+status+" "+reason);
super.onResponseStatus(version,status,reason);
}
@Override
protected synchronized void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
if (verbose)
System.err.println("] "+name+": "+value);
super.onResponseHeader(name,value);
}
@Override
protected synchronized void onResponseContent(ByteBuffer content) throws IOException
{
if (verbose)
{
total+=content.length();
System.err.println("] "+content.length()+" -> "+total);
}
super.onResponseContent(content);
}
@Override
protected void onRequestComplete() throws IOException
{
if (verbose)
System.err.println("] ==");
super.onRequestComplete();
}
@Override
protected void onResponseHeaderComplete() throws IOException
{
if (verbose)
System.err.println("] --");
super.onResponseHeaderComplete();
}
};
ByteBuffer babuf = new ByteArrayBuffer(size*36*1024);
ByteBuffer niobuf = new DirectNIOBuffer(size*36*1024);
byte[] bytes="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes();
for (int i=0;i<size*1024;i++)
{
babuf.put(bytes);
niobuf.put(bytes);
}
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(babuf);
_httpClient.send(httpExchange);
long start=System.currentTimeMillis();
while(!httpExchange.isDone())
{
long now=System.currentTimeMillis();
if ((now-start)>=10000)
{
System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!");
System.err.println("CLIENT:");
System.err.println(_httpClient.dump());
System.err.println("SERVER:");
_server.dumpStdErr();
break;
}
Thread.sleep(100);
}
int status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
String result=httpExchange.getResponseContent();
assertEquals(babuf.length(),result.length());
httpExchange.reset();
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(niobuf);
_httpClient.send(httpExchange);
start=System.currentTimeMillis();
while(!httpExchange.isDone())
{
long now=System.currentTimeMillis();
if ((now-start)>=10000)
{
System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!");
System.err.println("CLIENT:");
System.err.println(_httpClient.dump());
System.err.println("SERVER:");
_server.dumpStdErr();
break;
}
Thread.sleep(100);
}
status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
result=httpExchange.getResponseContent();
assertEquals(niobuf.length(),result.length());
}
/* ------------------------------------------------------------ */
@Test
public void testSlowPost() throws Exception
{
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethod.POST);
final String data="012345678901234567890123456789012345678901234567890123456789";
InputStream content = new InputStream()
{
int _index=0;
@Override
public int read() throws IOException
{
// System.err.printf("reading 1 of %d/%d%n",_index,data.length());
if (_index>=data.length())
return -1;
try
{
Thread.sleep(5);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
// System.err.printf("read 1%n");
return data.charAt(_index++);
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
// System.err.printf("reading %d of %d/%d%n",len,_index,data.length());
if (_index >= data.length())
return -1;
try
{
Thread.sleep(25);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
int l = 0;
while (l < 5 && _index < data.length() && l < len)
b[off + l++] = (byte)data.charAt(_index++);
// System.err.printf("read %d%n",l);
return l;
}
};
httpExchange.setRequestContentSource(content);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
String result = httpExchange.getResponseContent();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
assertEquals(data,result);
}
/* ------------------------------------------------------------ */
@Test
public void testProxy() throws Exception
{
if (_scheme.equals("https"))
return;
try
{
_httpClient.setProxy(new Address("127.0.0.1",_port));
_httpClient.setProxyAuthentication(new ProxyAuthorization("user","password"));
ContentExchange httpExchange=new ContentExchange();
httpExchange.setAddress(new Address("jetty.eclipse.org",8080));
httpExchange.setMethod(HttpMethod.GET);
httpExchange.setRequestURI("/jetty-6");
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
result=result.trim();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertTrue(result.startsWith("Proxy request: http://jetty.eclipse.org:8080/jetty-6"));
assertTrue(result.endsWith("Basic dXNlcjpwYXNzd29yZA=="));
}
finally
{
_httpClient.setProxy(null);
}
}
/* ------------------------------------------------------------ */
@Test
public void testReserveConnections () throws Exception
{
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
final HttpDestination destination = _httpClient.getDestination(new Address("localhost",_port),_scheme.equalsIgnoreCase("https"));
final org.eclipse.jetty.client.AbstractHttpConnection[] connections = new org.eclipse.jetty.client.AbstractHttpConnection[_maxConnectionsPerAddress];
for (int i = 0; i < _maxConnectionsPerAddress; i++)
{
connections[i] = destination.reserveConnection(200);
assertNotNull(connections[i]);
HttpExchange ex = new ContentExchange();
ex.setURI(getBaseURI().resolve("?i=" + i));
ex.setMethod(HttpMethod.GET);
connections[i].send(ex);
}
// try to get a connection, and only wait 500ms, as we have
// already reserved the max, should return null
Connection c = destination.reserveConnection(500);
assertNull(c);
// unreserve first connection
destination.returnConnection(connections[0],false);
// reserving one should now work
c = destination.reserveConnection(500);
assertNotNull(c);
// release connections
for (AbstractHttpConnection httpConnection : connections){
destination.returnConnection(httpConnection,false);
}
}
@Test
public void testOptionsWithExchange() throws Exception
{
ContentExchange httpExchange = new ContentExchange(true);
httpExchange.setURL(getBaseURI().toASCIIString());
httpExchange.setRequestURI("*");
httpExchange.setMethod(HttpMethod.OPTIONS);
// httpExchange.setRequestHeader("Connection","close");
_httpClient.send(httpExchange);
int state = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
assertEquals(HttpStatus.OK_200,httpExchange.getResponseStatus());
HttpFields headers = httpExchange.getResponseFields();
HttpAsserts.assertContainsHeaderKey("Content-Length", headers);
assertEquals("Content-Length header value", 0, headers.getLongField("Content-Length"));
HttpAsserts.assertContainsHeaderKey("Allow",headers);
String allow = headers.getStringField("Allow");
String expectedMethods[] =
{ "GET", "HEAD", "POST", "PUT", "DELETE", "MOVE", "OPTIONS", "TRACE" };
for (String expectedMethod : expectedMethods)
{
assertThat(allow,containsString(expectedMethod));
}
}
/* ------------------------------------------------------------ */
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println("HttpExchangeTest#copyStream: " + e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

View File

@ -1,237 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
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.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class HttpGetRedirectTest
{
private static String _content =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
"Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+
"at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+
"velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+
"Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+
"eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+
"sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+
"consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private File _docRoot;
private Server _server;
private HttpClient _client;
private Realm _realm;
private String _protocol;
private String _requestUrl;
private String _requestUrl2;
private RedirectHandler _handler;
/* ------------------------------------------------------------ */
@Before
public void setUp()
throws Exception
{
_docRoot = new File("target/test-output/docroot/");
_docRoot.mkdirs();
_docRoot.deleteOnExit();
_server = new Server();
configureServer(_server);
org.eclipse.jetty.server.bio.SocketConnector connector = new org.eclipse.jetty.server.bio.SocketConnector();
_server.addConnector(connector);
_server.start();
int port = _server.getConnectors()[0].getLocalPort();
_requestUrl = _protocol+"://localhost:"+port+ "/content.txt";
_handler._toURL=_protocol+"://localhost:"+connector.getLocalPort()+ "/moved.txt";
}
/* ------------------------------------------------------------ */
@After
public void tearDown()
throws Exception
{
if (_server != null)
{
_server.stop();
_server = null;
}
}
/* ------------------------------------------------------------ */
@Test
public void testGet() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(_requestUrl);
getExchange.setMethod(HttpMethod.GET);
_client.send(getExchange);
int state = getExchange.waitForDone();
String content = "";
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
assertEquals(HttpStatus.OK_200,responseStatus);
assertEquals(_content,content);
stopClient();
}
/* ------------------------------------------------------------ */
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
_handler = new RedirectHandler(HttpStatus.MOVED_PERMANENTLY_301, "/content.txt", "WAIT FOR IT", 2);
server.setHandler( _handler );
}
/* ------------------------------------------------------------ */
protected void startClient(Realm realm)
throws Exception
{
_client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_client.registerListener("org.eclipse.jetty.client.RedirectListener");
if (realm != null)
_client.setRealmResolver(new SimpleRealmResolver(realm));
_client.start();
}
/* ------------------------------------------------------------ */
protected void stopClient()
throws Exception
{
if (_client != null)
{
_client.stop();
_client = null;
}
}
/* ------------------------------------------------------------ */
protected String getBasePath()
{
return _docRoot.getAbsolutePath();
}
/* ------------------------------------------------------------ */
protected void setProtocol(String protocol)
{
_protocol = protocol;
}
/* ------------------------------------------------------------ */
protected void setRealm(Realm realm)
{
_realm = realm;
}
/* ------------------------------------------------------------ */
private static class RedirectHandler
extends AbstractHandler
{
private final String _fromURI;
private final int _code;
private final int _maxRedirects;
private int _redirectCount = 0;
private String _toURL;
/* ------------------------------------------------------------ */
public RedirectHandler( final int code, final String fromURI, final String toURL, final int maxRedirects )
{
this._code = code;
this._fromURI = fromURI;
this._toURL = toURL;
this._maxRedirects = maxRedirects;
if (_fromURI==null || _toURL==null)
throw new IllegalArgumentException();
}
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if ( baseRequest.isHandled() )
{
return;
}
if (request.getRequestURI().equals(_fromURI))
{
_redirectCount++;
String location = ( _redirectCount <= _maxRedirects )?_fromURI:_toURL;
response.setStatus( _code );
response.setHeader( "Location", location );
( (Request) request ).setHandled( true );
}
else
{
PrintWriter out = response.getWriter();
out.write(_content);
baseRequest.setHandled( true );
}
}
}
}

View File

@ -1,193 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
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.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class HttpHeadersTest
{
private static final Logger LOG = Log.getLogger(HttpHeadersTest.class);
private static final String CONTENT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "
+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "
+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
+ "Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "
+ "at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "
+ "velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "
+ "Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "
+ "eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "
+ "sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "
+ "consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "
+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "
+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private Server _server;
private TestHeaderHandler _handler;
private int _port;
@Before
public void init() throws Exception
{
File docRoot = new File("target/test-output/docroot/");
if (!docRoot.exists())
assertTrue(docRoot.mkdirs());
docRoot.deleteOnExit();
_server = new Server();
Connector connector = new SelectChannelConnector();
_server.addConnector(connector);
_handler = new TestHeaderHandler();
_server.setHandler(_handler);
_server.start();
_port = connector.getLocalPort();
}
@After
public void destroy() throws Exception
{
_server.stop();
_server.join();
}
@Test
public void testHttpHeaders() throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.start();
try
{
String requestUrl = "http://localhost:" + _port + "/header";
ContentExchange exchange = new ContentExchange();
exchange.setURL(requestUrl);
exchange.setMethod(HttpMethod.GET);
exchange.addRequestHeader("User-Agent","Jetty-Client/7.0");
httpClient.send(exchange);
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(HttpHeadersTest.CONTENT,content);
assertEquals("Jetty-Client/7.0",_handler.headers.get("User-Agent"));
}
finally
{
httpClient.stop();
}
}
@Test
public void testHttpHeadersSize() throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.start();
try
{
String requestUrl = "http://localhost:" + _port + "/header";
ContentExchange exchange = new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
// suppress exception
LOG.ignore(x);
}
};
exchange.setURL(requestUrl);
exchange.setMethod(HttpMethod.GET);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 1024; j++)
{
exchange.addRequestHeader("header" + i + "-" + j,"v");
}
}
httpClient.send(exchange);
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_EXCEPTED, state);
}
finally
{
httpClient.stop();
}
}
private static class TestHeaderHandler extends AbstractHandler
{
protected Map<String, String> headers;
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (baseRequest.isHandled())
return;
headers = new HashMap<String, String>();
for (Enumeration e = request.getHeaderNames(); e.hasMoreElements();)
{
String name = (String)e.nextElement();
headers.put(name,request.getHeader(name));
}
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(CONTENT);
baseRequest.setHandled(true);
}
}
}

View File

@ -1,123 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.client.security.BasicAuthentication;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
public class HttpsProxyAuthenticationTest
{
private Server _proxy = new Server();
private HttpClient _client = new HttpClient();
private boolean authHandlerSend;
@Before
public void init() throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
_proxy.addConnector(connector);
_proxy.setHandler(new ConnectHandler()
{
@Override
protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException
{
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.length() > 0)
authHandlerSend = true;
return super.handleAuthentication(request,response,address);
}
});
_proxy.start();
int proxyPort = connector.getLocalPort();
Authentication authentication = new BasicAuthentication(new Realm()
{
public String getId()
{
return "MyRealm";
}
public String getPrincipal()
{
return "jetty";
}
public String getCredentials()
{
return "jetty";
}
});
_client.setProxy(new Address("localhost", proxyPort));
_client.setProxyAuthentication(authentication);
_client.start();
}
@After
public void destroy() throws Exception
{
_client.stop();
_proxy.stop();
_proxy.join();
}
@Test
public void httpsViaProxyThatReturns504ErrorTest() throws Exception
{
// Assume that we can connect to google
String host = "google.com";
int port = 443;
Socket socket = new Socket();
try
{
socket.connect(new InetSocketAddress(host, port), 1000);
}
catch (IOException x)
{
Assume.assumeNoException(x);
}
finally
{
socket.close();
}
HttpExchange exchange = new ContentExchange();
exchange.setURL("https://" + host + ":" + port);
exchange.addRequestHeader("behaviour", "google");
_client.send(exchange);
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
Assert.assertTrue("Authorization header not set!", authHandlerSend);
}
}

View File

@ -1,141 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.net.ProtocolException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* This UnitTest class executes two tests. Both will send a http request to https://google.com through a misbehaving proxy server.
* <p/>
* The first test runs against a proxy which simply closes the connection (as nginx does) for a connect request. The second proxy server always responds with a
* 500 error.
* <p/>
* The expected result for both tests is an exception and the HttpExchange should have status HttpExchange.STATUS_EXCEPTED.
*/
public class HttpsViaBrokenHttpProxyTest
{
private Server _proxy = new Server();
private HttpClient _client = new HttpClient();
@Before
public void init() throws Exception
{
// setup proxies with different behaviour
_proxy.addConnector(new SelectChannelConnector());
_proxy.setHandler(new BadBehavingConnectHandler());
_proxy.start();
int proxyClosingConnectionPort = _proxy.getConnectors()[0].getLocalPort();
_client.setProxy(new Address("localhost", proxyClosingConnectionPort));
_client.start();
}
@After
public void destroy() throws Exception
{
_client.stop();
_proxy.stop();
}
@Test
public void httpsViaProxyThatClosesConnectionOnConnectRequestTest() throws Exception
{
sendRequestThroughProxy(new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
}
}, "close", 9);
}
@Test
public void httpsViaProxyThatReturns500ErrorTest() throws Exception
{
HttpExchange exchange = new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
// Suppress logging for expected exception
if (!(x instanceof ProtocolException))
super.onException(x);
}
};
sendRequestThroughProxy(exchange, "error500", 9);
}
@Test
public void httpsViaProxyThatReturns504ErrorTest() throws Exception
{
sendRequestThroughProxy(new ContentExchange(), "error504", 8);
}
private void sendRequestThroughProxy(HttpExchange exchange, String desiredBehaviour, int exptectedStatus) throws Exception
{
String url = "https://" + desiredBehaviour + ".com/";
exchange.setURL(url);
exchange.addRequestHeader("behaviour", desiredBehaviour);
_client.send(exchange);
assertEquals(HttpExchange.toState(exptectedStatus) + " status awaited", exptectedStatus, exchange.waitForDone());
}
private class BadBehavingConnectHandler extends ConnectHandler
{
@Override
protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress)
throws ServletException, IOException
{
if (serverAddress.contains("close"))
{
AbstractHttpConnection.getCurrentConnection().getEndPoint().close();
}
else if (serverAddress.contains("error500"))
{
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
else if (serverAddress.contains("error504"))
{
response.setStatus(HttpStatus.GATEWAY_TIMEOUT_504);
}
baseRequest.setHandled(true);
}
}
}

View File

@ -1,64 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.junit.After;
import org.junit.Before;
/* ------------------------------------------------------------ */
/**
* @version $Revision$ $Date$
*/
public class NonBlockingHttpExchangeCancelTest extends AbstractHttpExchangeCancelTest
{
private HttpClient httpClient;
/* ------------------------------------------------------------ */
@Before
@Override
public void setUp() throws Exception
{
super.setUp();
httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.start();
}
/* ------------------------------------------------------------ */
@After
@Override
public void tearDown() throws Exception
{
httpClient.stop();
super.tearDown();
}
/* ------------------------------------------------------------ */
@Override
protected HttpClient getHttpClient()
{
return httpClient;
}
/* ------------------------------------------------------------ */
public void testHttpExchangeCancelOnRequestComplete() throws Exception
{
super.testHttpExchangeCancelOnRequestComplete();
}
}

View File

@ -1,228 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.eclipse.jetty.toolchain.test.IO;
public class ProxyFakeTunnelTest extends ProxyTunnellingTest
{
ServerSocket _proxySocket;
Thread _proxyThread;
protected int proxyPort()
{
return _proxySocket.getLocalPort();
}
protected void startProxy() throws Exception
{
_proxySocket = new ServerSocket(0);
_proxyThread = new Thread()
{
@Override
public void run()
{
while (!_proxySocket.isClosed())
{
try
{
Socket socket=_proxySocket.accept();
System.err.println("accepted "+socket);
new FakeProxy(socket).start();
}
catch (IOException e)
{
}
}
}
};
_proxyThread.setDaemon(true);
_proxyThread.start();
}
protected void stopProxy() throws Exception
{
_proxySocket.close();
_proxyThread.interrupt();
}
static class FakeProxy extends Thread
{
Socket _socket;
public FakeProxy(Socket socket)
{
_socket=socket;
}
public void run()
{
Socket toserver=null;
final InputStream in;
final OutputStream out;
try
{
in = _socket.getInputStream();
out = _socket.getOutputStream();
String address="";
int state=0;
for (int b=in.read();b>=0;b=in.read())
{
switch(state)
{
case 0:
if (' '==b)
state=1;
break;
case 1:
if (' '==b)
state=2;
else
address+=(char)b;
break;
case 2:
if ('\r'==b)
state=3;
break;
case 3:
if ('\n'==b)
state=4;
else
state=2;
break;
case 4:
if ('\r'==b)
state=5;
else
state=2;
break;
case 5:
if ('\n'==b)
{
state=6;
System.err.println("address="+address);
String[] parts=address.split(":");
try
{
toserver = new Socket(parts[0],Integer.parseInt(parts[1]));
out.write((
"HTTP/1.1 200 OK\r\n"+
"Server: fake\r\n"+
// "Content-Length: 0\r\n"+
"\r\n"
).getBytes());
}
catch(IOException e)
{
out.write((
"HTTP/1.1 503 Unavailable\r\n"+
"Server: fake\r\n"+
"Content-Length: 0\r\n"+
"\r\n"
).getBytes());
}
out.flush();
if (toserver!=null)
{
final InputStream from = toserver.getInputStream();
Thread copy = new Thread()
{
public void run()
{
try
{
IO.copy(from,out);
out.close();
}
catch (IOException e)
{
}
finally
{
try
{
out.close();
}
catch (IOException e)
{
}
}
}
};
copy.setDaemon(true);
copy.start();
}
}
else
state=2;
break;
case 6:
toserver.getOutputStream().write((byte)b);
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (toserver!=null)
{
try
{
toserver.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
}

View File

@ -1,276 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.*;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After;
import org.junit.Test;
public class ProxyTunnellingTest
{
private Server server;
private Connector serverConnector;
private Server proxy;
private Connector proxyConnector;
private int serverConnectTimeout = 1000;
protected int proxyPort()
{
return proxyConnector.getLocalPort();
}
protected void startSSLServer(Handler handler) throws Exception
{
SslSelectChannelConnector connector = new SslSelectChannelConnector();
String keyStorePath = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keyStorePath);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
startServer(connector, handler);
}
protected void startServer(Connector connector, Handler handler) throws Exception
{
server = new Server();
serverConnector = connector;
server.addConnector(serverConnector);
server.setHandler(handler);
server.start();
}
protected void startProxy() throws Exception
{
proxy = new Server();
proxyConnector = new SelectChannelConnector();
proxy.addConnector(proxyConnector);
ConnectHandler connectHandler = new ConnectHandler();
// Under Windows, it takes a while to detect that a connection
// attempt fails, so use an explicit timeout
connectHandler.setConnectTimeout(serverConnectTimeout);
proxy.setHandler(connectHandler);
proxy.start();
}
@After
public void stop() throws Exception
{
stopProxy();
stopServer();
}
protected void stopServer() throws Exception
{
server.stop();
server.join();
}
protected void stopProxy() throws Exception
{
proxy.stop();
proxy.join();
}
@Test
public void testOneMessageSSL() throws Exception
{
startSSLServer(new ServerHandler());
startProxy();
HttpClient httpClient = new HttpClient();
httpClient.setProxy(new Address("localhost", proxyPort()));
httpClient.start();
try
{
ContentExchange exchange = new ContentExchange(true);
exchange.setMethod(HttpMethod.GET);
String body = "BODY";
exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo?body=" + URLEncoder.encode(body, "UTF-8"));
httpClient.send(exchange);
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
String content = exchange.getResponseContent();
assertEquals(body, content);
}
finally
{
httpClient.stop();
}
}
@Test
public void testTwoMessagesSSL() throws Exception
{
startSSLServer(new ServerHandler());
startProxy();
HttpClient httpClient = new HttpClient();
httpClient.setProxy(new Address("localhost", proxyPort()));
httpClient.start();
try
{
ContentExchange exchange = new ContentExchange(true);
exchange.setMethod(HttpMethod.GET);
String body = "BODY";
exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo?body=" + URLEncoder.encode(body, "UTF-8"));
httpClient.send(exchange);
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
String content = exchange.getResponseContent();
assertEquals(body, content);
exchange = new ContentExchange(true);
exchange.setMethod(HttpMethod.POST);
exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo");
exchange.setRequestHeader(HttpHeader.CONTENT_TYPE, MimeTypes.FORM_ENCODED);
content = "body=" + body;
exchange.setRequestHeader(HttpHeader.CONTENT_LENGTH, String.valueOf(content.length()));
exchange.setRequestContent(new ByteArrayBuffer(content, "UTF-8"));
httpClient.send(exchange);
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
content = exchange.getResponseContent();
assertEquals(body, content);
}
finally
{
httpClient.stop();
}
}
@Test
public void testProxyDown() throws Exception
{
startSSLServer(new ServerHandler());
startProxy();
int proxyPort = proxyPort();
stopProxy();
HttpClient httpClient = new HttpClient();
httpClient.setProxy(new Address("localhost", proxyPort));
httpClient.start();
try
{
final CountDownLatch latch = new CountDownLatch(1);
ContentExchange exchange = new ContentExchange(true)
{
@Override
protected void onConnectionFailed(Throwable x)
{
latch.countDown();
}
};
exchange.setMethod(HttpMethod.GET);
String body = "BODY";
exchange.setURL("https://localhost:" + serverConnector.getLocalPort() + "/echo?body=" + URLEncoder.encode(body, "UTF-8"));
httpClient.send(exchange);
assertTrue(latch.await(1000, TimeUnit.MILLISECONDS));
}
finally
{
httpClient.stop();
}
}
@Test
public void testServerDown() throws Exception
{
startSSLServer(new ServerHandler());
int serverPort = serverConnector.getLocalPort();
stopServer();
startProxy();
HttpClient httpClient = new HttpClient();
httpClient.setProxy(new Address("localhost", proxyPort()));
httpClient.start();
try
{
final CountDownLatch latch = new CountDownLatch(1);
ContentExchange exchange = new ContentExchange(true)
{
@Override
protected void onException(Throwable x)
{
latch.countDown();
}
};
exchange.setMethod(HttpMethod.GET);
String body = "BODY";
exchange.setURL("https://localhost:" + serverPort + "/echo?body=" + URLEncoder.encode(body, "UTF-8"));
httpClient.send(exchange);
assertTrue("Server connect exception should have occurred", latch.await(serverConnectTimeout * 2, TimeUnit.MILLISECONDS));
}
finally
{
httpClient.stop();
}
}
private static class ServerHandler extends AbstractHandler
{
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{
request.setHandled(true);
String uri = httpRequest.getRequestURI();
if ("/echo".equals(uri))
{
String body = httpRequest.getParameter("body");
ServletOutputStream output = httpResponse.getOutputStream();
output.print(body);
}
else
{
throw new ServletException();
}
}
}
}

View File

@ -1,108 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
public class SecuredContentExchangeTest
extends ContentExchangeTest
{
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
setRealm(new Realm()
{
public String getId()
{
return "MyRealm";
}
public String getPrincipal()
{
return "jetty";
}
public String getCredentials()
{
return "jetty";
}
});
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties");
LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath());
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate( true );
constraint.setRoles(new String[]{"user", "admin"});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec( "/*" );
mapping.setConstraint( constraint );
Set<String> knownRoles = new HashSet<String>();
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
Handler handler = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
security.setHandler(handlers);
}
}

View File

@ -1,193 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.junit.Test;
public class SecuredErrorStatusTest
extends ErrorStatusTest
{
private Realm _testRealm;
private Realm _dummyRealm;
/* ------------------------------------------------------------ */
@Test
@Override
public void testPutUnauthorized()
throws Exception
{
setRealm(null);
doPutFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
@Test
public void testPutWrongPassword()
throws Exception
{
setRealm(_dummyRealm);
doPutFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
@Test
@Override
public void testGetUnauthorized()
throws Exception
{
setRealm(null);
doGetFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
@Test
public void testGetWrongPassword()
throws Exception
{
setRealm(_dummyRealm);
doGetFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
@Override
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
_testRealm = new Realm()
{
/* ------------------------------------------------------------ */
public String getId()
{
return "MyRealm";
}
/* ------------------------------------------------------------ */
public String getPrincipal()
{
return "jetty";
}
/* ------------------------------------------------------------ */
public String getCredentials()
{
return "jetty";
}
};
_dummyRealm = new Realm()
{
/* ------------------------------------------------------------ */
public String getId()
{
return "MyRealm";
}
/* ------------------------------------------------------------ */
public String getPrincipal()
{
return "jetty";
}
/* ------------------------------------------------------------ */
public String getCredentials()
{
return "dummy";
}
};
setRealm(_testRealm);
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties");
LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath());
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate( true );
constraint.setRoles(new String[]{"user", "admin"});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec( "/*" );
mapping.setConstraint( constraint );
Set<String> knownRoles = new HashSet<String>();
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
Handler status = new StatusHandler();
Handler test = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{status, test, root});
security.setHandler(handlers);
}
}

View File

@ -1,355 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
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.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* Functional testing for HttpExchange.
*/
public class SecurityListenerTest
{
private Server _server;
private int _port;
private HttpClient _httpClient;
private Realm _jettyRealm;
private static final String APP_CONTEXT = "localhost /";
/* ------------------------------------------------------------ */
@Before
public void setUp() throws Exception
{
startServer();
_httpClient=new HttpClient();
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(2);
_httpClient.start();
_jettyRealm = new Realm()
{
public String getId()
{
return "MyRealm";
}
public String getPrincipal()
{
return "jetty";
}
public String getCredentials()
{
return "jetty";
}
};
_httpClient.setRealmResolver( new SimpleRealmResolver(_jettyRealm) );
}
/* ------------------------------------------------------------ */
@After
public void tearDown() throws Exception
{
stopServer();
_httpClient.stop();
}
/* ------------------------------------------------------------ */
// @Test
public void xtestPerf() throws Exception
{
sender(1);
Thread.sleep(200);
sender(10);
Thread.sleep(200);
sender(100);
Thread.sleep(200);
sender(1000);
Thread.sleep(200);
sender(10000);
}
/* ------------------------------------------------------------ */
public void sender(final int nb) throws Exception
{
final CountDownLatch latch=new CountDownLatch(nb);
long l0=System.currentTimeMillis();
for (int i=0; i<nb; i++)
{
final int n=i;
if (n%1000==0)
{
Thread.sleep(200);
}
HttpExchange httpExchange=new HttpExchange()
{
@Override
protected void onRequestCommitted()
{
// System.err.println("Request committed");
}
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason)
{
// System.err.println("Response Status: " + version+" "+status+" "+reason);
}
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value)
{
// System.err.println("Response header: " + name + " = " + value);
}
@Override
protected void onResponseContent(ByteBuffer content)
{
// System.err.println("Response content:" + content);
}
@Override
protected void onResponseComplete()
{
// System.err.println("Response completed "+n);
latch.countDown();
}
};
httpExchange.setURL("http://localhost:"+_port+"/");
httpExchange.addRequestHeader("arbitrary","value");
_httpClient.send(httpExchange);
}
long last=latch.getCount();
while(last>0)
{
// System.err.println("waiting for "+last+" sent "+(System.currentTimeMillis()-l0)/1000 + "s ago ...");
latch.await(5,TimeUnit.SECONDS);
long next=latch.getCount();
if (last==next)
break;
last=next;
}
// System.err.println("missed "+latch.getCount()+" sent "+(System.currentTimeMillis()-l0)/1000 + "s ago.");
assertEquals(0,latch.getCount());
long l1=System.currentTimeMillis();
}
//TODO jaspi hangs ???
// public void testGetWithContentExchange() throws Exception
// {
// int i = 1;
//
// final CyclicBarrier barrier = new CyclicBarrier(2);
// ContentExchange httpExchange = new ContentExchange()
// {
// protected void onResponseComplete() throws IOException
// {
// super.onResponseComplete();
// try{barrier.await();}catch(Exception e){}
// }
// };
// httpExchange.setURL("http://localhost:" + _port + "/?i=" + i);
// httpExchange.setMethod(HttpMethods.GET);
//
// _httpClient.send(httpExchange);
//
// try{barrier.await();}catch(Exception e){}
//
// }
/* ------------------------------------------------------------ */
@Test
public void testDestinationSecurityCaching() throws Exception
{
final CyclicBarrier barrier = new CyclicBarrier(2);
ContentExchange httpExchange = new ContentExchange()
{
@Override
protected void onResponseComplete() throws IOException
{
super.onResponseComplete();
try{barrier.await();}catch(Exception e){}
}
};
httpExchange.setURL("http://localhost:" + _port + "/?i=1");
httpExchange.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange);
try{barrier.await();}catch(Exception e){}
barrier.reset();
ContentExchange httpExchange2 = new ContentExchange()
{
@Override
protected void onResponseComplete() throws IOException
{
super.onResponseComplete();
try{barrier.await();}catch(Exception e){}
}
};
httpExchange2.setURL("http://localhost:" + _port + "/?i=2");
httpExchange2.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange2);
try{barrier.await();}catch(Exception e){}
assertFalse( "exchange was retried", httpExchange2.getRetryStatus() );
}
/* ------------------------------------------------------------ */
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer=new byte[1024];
int len;
while ((len=in.read(buffer))>=0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println(e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/* ------------------------------------------------------------ */
private void startServer() throws Exception
{
_server = new Server();
_server.setGracefulShutdown(500);
Connector connector = new SelectChannelConnector();
connector.setPort(0);
_server.setConnectors(new Connector[]{connector});
Constraint constraint = new Constraint();
constraint.setName("Need User or Admin");
constraint.setRoles(new String[]{"user", "admin"});
constraint.setAuthenticate(true);
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(constraint);
cm.setPathSpec("/*");
File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties");
LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath());
ConstraintSecurityHandler sh = new ConstraintSecurityHandler();
sh.setLoginService(loginService);
sh.setAuthenticator(new BasicAuthenticator());
//ServerAuthentication serverAuthentication = new BasicServerAuthentication(loginService, "MyRealm");
//sh.setServerAuthentication(serverAuthentication);
_server.setHandler(sh);
Handler testHandler = new AbstractHandler()
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
// System.out.println("passed authentication!");
baseRequest.setHandled(true);
response.setStatus(200);
if (request.getServerName().equals("jetty.eclipse.org"))
{
response.getOutputStream().println("Proxy request: "+request.getRequestURL());
}
else if (request.getMethod().equalsIgnoreCase("GET"))
{
response.getOutputStream().println("<hello>");
for (int i=0; i<100; i++)
{
response.getOutputStream().println(" <world>"+i+"</world>");
if (i%20==0)
response.getOutputStream().flush();
}
response.getOutputStream().println("</hello>");
}
else
{
copyStream(request.getInputStream(),response.getOutputStream());
}
}
};
sh.setHandler(testHandler);
_server.start();
_port = connector.getLocalPort();
}
/* ------------------------------------------------------------ */
private void stopServer() throws Exception
{
_server.stop();
}
}

View File

@ -1,30 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
public class SelectConnectionTest extends AbstractConnectionTest
{
protected HttpClient newHttpClient()
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setConnectBlocking(true);
return httpClient;
}
}

View File

@ -1,229 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/* ------------------------------------------------------------ */
/**
*/
public class Siege
{
private static final class ConcurrentExchange extends HttpExchange
{
private final long _start=System.currentTimeMillis();
private final HttpClient _client;
private final CountDownLatch _latch;
volatile int _status;
volatile int _count;
volatile long _bytes;
final List<String> _uris;
final int _repeats;
int _u;
int _r;
AtomicBoolean counted=new AtomicBoolean(false);
public ConcurrentExchange(HttpClient client,CountDownLatch latch, List<String> uris, int repeats)
{
_client = client;
_latch = latch;
_uris = uris;
_repeats = repeats;
}
@Override
protected void onConnectionFailed(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onConnectionFailed(ex);
}
@Override
protected void onException(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onException(ex);
}
@Override
protected void onExpire()
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onExpire();
}
@Override
protected void onResponseComplete() throws IOException
{
if (_status==200)
_count++;
if (!next() && !counted.getAndSet(true))
{
_latch.countDown();
long duration=System.currentTimeMillis()-_start;
System.err.printf("Got %d/%d with %dB in %dms %d%n",_count,_uris.size()*_repeats,_bytes,duration,_latch.getCount());
}
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseContent(ByteBuffer content) throws IOException
{
_bytes+=content.length();
super.onResponseContent(content);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.ByteBuffer, org.eclipse.jetty.io.ByteBuffer)
*/
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
super.onResponseHeader(name,value);
if ("Set-Cookie".equalsIgnoreCase(name.toString()))
{
String v=value.toString();
int c = v.indexOf(';');
if (c>=0)
v=v.substring(0,c);
addRequestHeader("Cookie",v);
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete()
*/
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.ByteBuffer, int, org.eclipse.jetty.io.ByteBuffer)
*/
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
_status=status;
super.onResponseStatus(version,status,reason);
}
public boolean next()
{
if (_u>=_uris.size())
{
_u=0;
_r++;
if (_r>=_repeats)
return false;
}
String uri=_uris.get(_u++);
reset();
setMethod(HttpMethod.GET);
setURL(uri);
try
{
_client.send(this);
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
}
public static void main(String[] args)
throws Exception
{
if (args.length==0)
args=new String[]
{ "-c", "2", "-r", "2", "http://localhost:8080/dump", "http://localhost:8080/d.txt"};
int concurrent=1;
int repeats=1;
final List<String> uris = new ArrayList<String>();
for (int i=0; i<args.length; i++)
{
String arg=args[i];
if ("-c".equals(arg))
{
concurrent=Integer.parseInt(args[++i]);
continue;
}
if ("-r".equals(arg))
{
repeats=Integer.parseInt(args[++i]);
continue;
}
uris.add(arg);
}
QueuedThreadPool pool = new QueuedThreadPool();
pool.setMaxThreads(500);
pool.setDaemon(true);
HttpClient client = new HttpClient();
client.setThreadPool(pool);
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setIdleTimeout(30000);
client.setConnectTimeout(30000);
client.setMaxConnectionsPerAddress(concurrent*2);
client.start();
final CountDownLatch latch = new CountDownLatch(concurrent);
for (int i=0;i<concurrent;i++)
{
ConcurrentExchange ex = new ConcurrentExchange(client,latch,uris,repeats);
if (!ex.next())
latch.countDown();
}
latch.await();
client.stop();
pool.stop();
}
}

View File

@ -1,264 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.junit.Test;
/**
* A class that attempts to simulate a client communicating with a slow server. It imposes a delay between each handle() call made to the server's handler.
*
* The client sends a binary blob of data to the server, and this blob is then inspected to verify correct transfer.
*/
public class SluggishServerTest
{
/** msec to wait between reads in the handler -- may need to adjust based on OS/HW/etc. to reproduce bug */
private final static int READ_DELAY = 5;
private final static String URL = "http://localhost:";
/** Stream providing a binary message to send */
private static class SluggishStream extends InputStream
{
private final byte[] request;
private int pos;
public SluggishStream(byte[] request)
{
this.request = request;
this.pos = 0;
}
@Override
public int read() throws IOException
{
if (pos < request.length)
{
int byteVal = request[pos++] & 0xFF;
return byteVal;
}
else
{
return -1;
}
}
}
/** Sends a message containing random binary content to a SluggishHandler */
private static class SluggishExchange extends HttpExchange
{
private byte[] request;
public SluggishExchange(int port, int count)
{
request = new byte[count];
for (int i=0;i<count;i++)
request[i]=(byte)('A'+(i%26));
setURL(URL+port);
setRequestContentSource(new SluggishStream(request));
setRequestContentType("application/octet-stream");
setRequestHeader(HttpHeader.TRANSFER_ENCODING,HttpHeaderValue.CHUNKED);
}
public byte[] getRequestBody()
{
return request;
}
@Override
protected void onRequestComplete()
{
//System.err.println("REQUEST COMPLETE " + this);
}
@Override
protected void onResponseComplete()
{
//System.err.println("RESPONSE COMPLETE " + this);
}
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
//System.err.printf("<<< %s %d %s%n",version,status,reason);
super.onResponseStatus(version,status,reason);
}
@Override
protected void onResponseHeader(ByteBuffer name, ByteBuffer value) throws IOException
{
//System.err.printf("<<< %s: %s%n",name,value);
super.onResponseHeader(name,value);
}
@Override
protected void onResponseHeaderComplete() throws IOException
{
//System.err.printf("<<< --%n");
super.onResponseHeaderComplete();
}
}
/** Receives binary message from a SluggishExchange & stores it for validation */
private static class SluggishHandler extends AbstractHandler
{
private final ArrayList<Byte> accumulatedRequest;
public SluggishHandler(int requestSize)
{
accumulatedRequest = new ArrayList<Byte>(requestSize);
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
accumulatedRequest.clear();
ServletInputStream input = request.getInputStream();
byte[] buffer = new byte[16384];
int bytesAvailable;
while ((bytesAvailable = input.read(buffer,0,buffer.length)) > 0)
{
//System.err.println("AVAILABLE FOR READ = " + bytesAvailable);
for (int n = 0; n < bytesAvailable; ++n)
{
accumulatedRequest.add(buffer[n]);
}
try
{
Thread.sleep(READ_DELAY);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
//System.err.println("HANDLED");
}
public byte[] getAccumulatedRequest()
{
byte[] buffer = new byte[accumulatedRequest.size()];
int pos = 0;
for (Byte b : accumulatedRequest)
{
buffer[pos++] = b;
}
return buffer;
}
}
private static boolean compareBuffers(byte[] sent, byte[] received)
{
if (sent.length != received.length)
{
System.err.format("Mismatch in sent/received lengths: sent=%d received=%d\n",sent.length,received.length);
return false;
}
else
{
for (int n = 0; n < sent.length; ++n)
{
if (sent[n] != received[n])
{
System.err.format("Mismatch at offset %d: request=%d response=%d\n",n,sent[n],received[n]);
return false;
}
}
}
return true;
}
@Test
public void test0() throws Exception
{
goSlow(20000,10);
}
@Test
public void test1() throws Exception
{
goSlow(200000,5);
}
@Test
public void test2() throws Exception
{
goSlow(2000000,2);
}
void goSlow(int requestSize,int iterations) throws Exception
{
Server server = new Server();
SocketConnector connector = new SocketConnector();
server.addConnector(connector);
SluggishHandler handler = new SluggishHandler(requestSize);
server.setHandler(handler);
server.start();
int port = connector.getLocalPort();
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setConnectTimeout(5000);
client.setIdleTimeout(60000);
client.start();
try
{
for (int i = 0; i < iterations; ++i)
{
//System.err.format("-------------- ITERATION %d ------------------\n",i);
SluggishExchange exchange = new SluggishExchange(port,requestSize);
long startTime = System.currentTimeMillis();
client.send(exchange);
exchange.waitForDone();
long endTime = System.currentTimeMillis();
//System.err.println("EXCHANGE STATUS = " + exchange);
//System.err.println("ELAPSED MSEC = " + (endTime - startTime));
Assert.assertTrue(compareBuffers(exchange.getRequestBody(),handler.getAccumulatedRequest()));
}
}
finally
{
server.stop();
server.join();
}
}
}

View File

@ -1,101 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
public class SocketConnectionTest extends AbstractConnectionTest
{
protected HttpClient newHttpClient()
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
return httpClient;
}
@Override
public void testServerClosedConnection() throws Exception
{
// Differently from the SelectConnector, the SocketConnector cannot detect server closes.
// Therefore, upon a second send, the exchange will fail.
// Applications needs to retry it explicitly.
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
int port=serverSocket.getLocalPort();
HttpClient httpClient = this.newHttpClient();
httpClient.setMaxConnectionsPerAddress(1);
httpClient.start();
try
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
Socket remote = serverSocket.accept();
// HttpClient.send() above is async, so if we write the response immediately
// there is a chance that it arrives before the request is being sent, so we
// read the request before sending the response to avoid the race
InputStream input = remote.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
String line;
while ((line = reader.readLine()) != null)
{
if (line.length() == 0)
break;
}
OutputStream output = remote.getOutputStream();
output.write("HTTP/1.1 200 OK\r\n".getBytes("UTF-8"));
output.write("Content-Length: 0\r\n".getBytes("UTF-8"));
output.write("\r\n".getBytes("UTF-8"));
output.flush();
assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
remote.close();
exchange.reset();
httpClient.send(exchange);
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone());
}
finally
{
httpClient.stop();
}
}
public void testIdleConnection() throws Exception
{
super.testIdleConnection();
}
}

View File

@ -1,166 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class SslBytesClientTest extends SslBytesTest
{
private ExecutorService threadPool;
private HttpClient client;
private SimpleProxy proxy;
private SSLServerSocket acceptor;
@Before
public void init() throws Exception
{
threadPool = Executors.newCachedThreadPool();
client = new HttpClient();
client.setMaxConnectionsPerAddress(1);
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
File keyStore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory cf = client.getSslContextFactory();
cf.setKeyStorePath(keyStore.getAbsolutePath());
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
client.start();
SSLContext sslContext = cf.getSslContext();
acceptor = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(0);
int serverPort = acceptor.getLocalPort();
proxy = new SimpleProxy(threadPool, "localhost", serverPort);
proxy.start();
logger.debug(":{} <==> :{}", proxy.getPort(), serverPort);
}
@After
public void destroy() throws Exception
{
if (acceptor != null)
acceptor.close();
if (proxy != null)
proxy.stop();
if (client != null)
client.stop();
if (threadPool != null)
threadPool.shutdownNow();
}
@Test
public void testHandshake() throws Exception
{
ContentExchange exchange = new ContentExchange(true);
exchange.setURL("https://localhost:" + proxy.getPort());
String method = HttpMethod.GET;
exchange.setMethod(method);
client.send(exchange);
Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS));
final SSLSocket server = (SSLSocket)acceptor.accept();
server.setUseClientMode(false);
Future<Object> handshake = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
server.startHandshake();
return null;
}
});
// Client Hello
TLSRecord record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToServer(record);
// Server Hello + Certificate + Server Done
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToClient(record);
// Client Key Exchange
record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToServer(record);
// Change Cipher Spec
record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
proxy.flushToServer(record);
// Client Done
record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToServer(record);
// Change Cipher Spec
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
proxy.flushToClient(record);
// Server Done
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToClient(record);
Assert.assertNull(handshake.get(5, TimeUnit.SECONDS));
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
// Read request
BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream(), "UTF-8"));
String line = reader.readLine();
Assert.assertTrue(line.startsWith(method));
while (line.length() > 0)
line = reader.readLine();
// Write response
OutputStream output = server.getOutputStream();
output.write(("HTTP/1.1 200 OK\r\n" +
"Content-Length: 0\r\n" +
"\r\n").getBytes("UTF-8"));
output.flush();
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
Assert.assertEquals(HttpStatus.OK_200, exchange.getResponseStatus());
}
}

View File

@ -1,371 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
public abstract class SslBytesTest
{
protected final Logger logger = Log.getLogger(getClass());
public static class TLSRecord
{
private final SslBytesServerTest.TLSRecord.Type type;
private final byte[] bytes;
public TLSRecord(SslBytesServerTest.TLSRecord.Type type, byte[] bytes)
{
this.type = type;
this.bytes = bytes;
}
public SslBytesServerTest.TLSRecord.Type getType()
{
return type;
}
public byte[] getBytes()
{
return bytes;
}
@Override
public String toString()
{
return "TLSRecord [" + type + "] " + bytes.length + " bytes";
}
public enum Type
{
CHANGE_CIPHER_SPEC(20), ALERT(21), HANDSHAKE(22), APPLICATION(23);
private int code;
private Type(int code)
{
this.code = code;
SslBytesServerTest.TLSRecord.Type.Mapper.codes.put(this.code, this);
}
public static SslBytesServerTest.TLSRecord.Type from(int code)
{
SslBytesServerTest.TLSRecord.Type result = SslBytesServerTest.TLSRecord.Type.Mapper.codes.get(code);
if (result == null)
throw new IllegalArgumentException("Invalid TLSRecord.Type " + code);
return result;
}
private static class Mapper
{
private static final Map<Integer, SslBytesServerTest.TLSRecord.Type> codes = new HashMap<Integer, SslBytesServerTest.TLSRecord.Type>();
}
}
}
public class SimpleProxy implements Runnable
{
private final CountDownLatch latch = new CountDownLatch(1);
private final ExecutorService threadPool;
private final String serverHost;
private final int serverPort;
private volatile ServerSocket serverSocket;
private volatile Socket server;
private volatile Socket client;
public SimpleProxy(ExecutorService threadPool, String serverHost, int serverPort)
{
this.threadPool = threadPool;
this.serverHost = serverHost;
this.serverPort = serverPort;
}
public void start() throws Exception
{
// serverSocket = new ServerSocket(5871);
serverSocket = new ServerSocket(0);
Thread acceptor = new Thread(this);
acceptor.start();
server = new Socket(serverHost, serverPort);
}
public void stop() throws Exception
{
serverSocket.close();
}
public void run()
{
try
{
client = serverSocket.accept();
latch.countDown();
}
catch (IOException x)
{
x.printStackTrace();
}
}
public int getPort()
{
return serverSocket.getLocalPort();
}
public TLSRecord readFromClient() throws IOException
{
TLSRecord record = read(client);
logger.debug("C --> P {}", record);
return record;
}
private TLSRecord read(Socket socket) throws IOException
{
InputStream input = socket.getInputStream();
int first = -2;
while (true)
{
try
{
socket.setSoTimeout(500);
first = input.read();
break;
}
catch (SocketTimeoutException x)
{
if (Thread.currentThread().isInterrupted())
break;
}
}
if (first == -2)
throw new InterruptedIOException();
else if (first == -1)
return null;
if (first >= 0x80)
{
// SSLv2 Record
int hiLength = first & 0x3F;
int loLength = input.read();
int length = (hiLength << 8) + loLength;
byte[] bytes = new byte[2 + length];
bytes[0] = (byte)first;
bytes[1] = (byte)loLength;
return read(TLSRecord.Type.HANDSHAKE, input, bytes, 2, length);
}
else
{
// TLS Record
int major = input.read();
int minor = input.read();
int hiLength = input.read();
int loLength = input.read();
int length = (hiLength << 8) + loLength;
byte[] bytes = new byte[1 + 2 + 2 + length];
bytes[0] = (byte)first;
bytes[1] = (byte)major;
bytes[2] = (byte)minor;
bytes[3] = (byte)hiLength;
bytes[4] = (byte)loLength;
return read(TLSRecord.Type.from(first), input, bytes, 5, length);
}
}
private TLSRecord read(SslBytesServerTest.TLSRecord.Type type, InputStream input, byte[] bytes, int offset, int length) throws IOException
{
while (length > 0)
{
int read = input.read(bytes, offset, length);
if (read < 0)
throw new EOFException();
offset += read;
length -= read;
}
return new TLSRecord(type, bytes);
}
public void flushToServer(TLSRecord record) throws Exception
{
flushToServer(record, 100);
}
public void flushToServer(TLSRecord record, long sleep) throws Exception
{
if (record == null)
{
server.shutdownOutput();
if (client.isOutputShutdown())
{
client.close();
server.close();
}
}
else
{
flush(sleep, server, record.getBytes());
}
}
public void flushToServer(long sleep, byte... bytes) throws Exception
{
flush(sleep, server, bytes);
}
private void flush(long sleep, Socket socket, byte... bytes) throws Exception
{
OutputStream output = socket.getOutputStream();
output.write(bytes);
output.flush();
if (sleep > 0)
TimeUnit.MILLISECONDS.sleep(sleep);
}
public TLSRecord readFromServer() throws IOException
{
TLSRecord record = read(server);
logger.debug("P <-- S {}", record);
return record;
}
public void flushToClient(TLSRecord record) throws Exception
{
if (record == null)
{
client.shutdownOutput();
if (server.isOutputShutdown())
{
server.close();
client.close();
}
}
else
{
flush(0, client, record.getBytes());
}
}
public SslBytesServerTest.SimpleProxy.AutomaticFlow startAutomaticFlow() throws InterruptedException
{
final CountDownLatch startLatch = new CountDownLatch(2);
final CountDownLatch stopLatch = new CountDownLatch(2);
Future<Object> clientToServer = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
startLatch.countDown();
logger.debug("Automatic flow C --> S started");
try
{
while (true)
{
flushToServer(readFromClient(), 0);
}
}
catch (InterruptedIOException x)
{
return null;
}
finally
{
stopLatch.countDown();
logger.debug("Automatic flow C --> S finished");
}
}
});
Future<Object> serverToClient = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
startLatch.countDown();
logger.debug("Automatic flow C <-- S started");
try
{
while (true)
{
flushToClient(readFromServer());
}
}
catch (InterruptedIOException x)
{
return null;
}
finally
{
stopLatch.countDown();
logger.debug("Automatic flow C <-- S finished");
}
}
});
Assert.assertTrue(startLatch.await(5, TimeUnit.SECONDS));
return new SslBytesServerTest.SimpleProxy.AutomaticFlow(stopLatch, clientToServer, serverToClient);
}
public boolean awaitClient(int time, TimeUnit unit) throws InterruptedException
{
return latch.await(time, unit);
}
public void sendRSTToServer() throws IOException
{
// Calling setSoLinger(true, 0) causes close()
// to send a RST instead of a FIN, causing an
// exception to be thrown on the other end
server.setSoLinger(true, 0);
server.close();
}
public class AutomaticFlow
{
private final CountDownLatch stopLatch;
private final Future<Object> clientToServer;
private final Future<Object> serverToClient;
public AutomaticFlow(CountDownLatch stopLatch, Future<Object> clientToServer, Future<Object> serverToClient)
{
this.stopLatch = stopLatch;
this.clientToServer = clientToServer;
this.serverToClient = serverToClient;
}
public boolean stop(long time, TimeUnit unit) throws InterruptedException
{
clientToServer.cancel(true);
serverToClient.cancel(true);
return stopLatch.await(time, unit);
}
}
}
}

View File

@ -1,174 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.security.auth.Subject;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.MappedLoginService.KnownUser;
import org.eclipse.jetty.security.authentication.ClientCertAuthenticator;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslCertSecuredExchangeTest// extends ContentExchangeTest
{
// certificate is valid until Jan 1, 2050
private String _keypath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-valid.keystore").getAbsolutePath();
private String _trustpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-trust.keystore").getAbsolutePath();
private String _clientpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-client.keystore").getAbsolutePath();
private String _crlpath = MavenTestingUtils.getTargetFile("test-policy/validation/crlfile.pem").getAbsolutePath();
private String _password = "OBF:1wnl1sw01ta01z0f1tae1svy1wml";
protected void configureServer(Server server)
throws Exception
{
//setProtocol("https");
SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslContextFactory cf = connector.getSslContextFactory();
cf.setValidateCerts(true);
cf.setCrlPath(_crlpath);
cf.setNeedClientAuth(true);
cf.setKeyStorePath(_keypath);
cf.setKeyStorePassword(_password);
cf.setKeyManagerPassword(_password);
cf.setTrustStore(_trustpath);
cf.setTrustStorePassword(_password);
server.addConnector(connector);
LoginService loginService = new LoginService() {
public String getName()
{
return "MyLoginService";
}
public UserIdentity login(String username, Object credentials)
{
return new UserIdentity() {
public Subject getSubject()
{
Subject subject = new Subject();
subject.getPrincipals().add(getUserPrincipal());
subject.setReadOnly();
return subject;
}
public Principal getUserPrincipal()
{
return new KnownUser("client", new Credential() {
@Override
public boolean check(Object credentials)
{
return true;
}
});
}
public boolean isUserInRole(String role, Scope scope) { return true; }
};
}
public boolean validate(UserIdentity user) { return true; }
public IdentityService getIdentityService() { return null; }
public void setIdentityService(IdentityService service) {}
public void logout(UserIdentity user) {}
};
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate( true );
constraint.setRoles(new String[]{"user", "admin"});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec( "/*" );
mapping.setConstraint( constraint );
Set<String> knownRoles = new HashSet<String>();
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setLoginService(loginService);
ClientCertAuthenticator auth = new ClientCertAuthenticator();
auth.setValidateCerts(true);
auth.setCrlPath(_crlpath);
auth.setTrustStore(_trustpath);
auth.setTrustStorePassword(_password);
security.setAuthenticator(auth);
security.setAuthMethod(auth.getAuthMethod());
security.setRealmName("MyRealm");
security.setStrict(true);
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
// root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
// Handler handler = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
// handlers.setHandlers(new Handler[]{handler, root});
security.setHandler(handlers);
}
// @Override
// protected void configureClient(HttpClient client) throws Exception
// {
// SslContextFactory cf = client.getSslContextFactory();
// cf.setValidateCerts(true);
// cf.setCrlPath(_crlpath);
//
// cf.setCertAlias("client");
// cf.setKeyStorePath(_clientpath);
// cf.setKeyStorePassword(_password);
// cf.setKeyManagerPassword(_password);
//
// cf.setTrustStore(_trustpath);
// cf.setTrustStorePassword(_password);
// }
}

View File

@ -1,74 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.File;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslContentExchangeTest
extends ContentExchangeTest
{
protected void configureServer(Server server)
throws Exception
{
setProtocol("https");
SslSelectChannelConnector connector = new SslSelectChannelConnector();
File keystore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keystore.getAbsolutePath());
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
cf.setSessionCachingEnabled(true);
server.addConnector(connector);
Handler handler = new TestHandler(getBasePath());
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
server.setHandler( handlers );
}
@Override
protected void configureClient(HttpClient client)
throws Exception
{
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
SslContextFactory cf = client.getSslContextFactory();
cf.setSessionCachingEnabled(true);
}
}

View File

@ -1,108 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.SslServerAndClientCreator;
import org.eclipse.jetty.server.Connector;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
/**
* Functional testing for HttpExchange.
*/
public class SslHttpExchangeTest extends HttpExchangeTest
{
protected static ServerAndClientCreator serverAndClientCreator = new SslServerAndClientCreator();
/* ------------------------------------------------------------ */
@Before
public void setUpOnce() throws Exception
{
_scheme="https";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
Connector[] connectors = _server.getConnectors();
_port = connectors[0].getLocalPort();
}
/* ------------------------------------------------------------ */
private void IgnoreTestOnBuggyIBM()
{
// Use Junit 4.x to flag test as ignored if encountering IBM JVM
// Will show up in various junit reports as an ignored test as well.
Assume.assumeThat(System.getProperty("java.vendor").toLowerCase(),not(containsString("ibm")));
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchangeTest#testGetWithContentExchange()
*/
@Test
@Override
public void testGetWithContentExchange() throws Exception
{
// TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532
IgnoreTestOnBuggyIBM();
super.testGetWithContentExchange();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchangeTest#testPerf()
*/
@Test
@Override
public void testPerf() throws Exception
{
// TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532
IgnoreTestOnBuggyIBM();
super.testPerf();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchangeTest#testPostWithContentExchange()
*/
@Test
@Override
public void testPostWithContentExchange() throws Exception
{
// TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532
IgnoreTestOnBuggyIBM();
super.testPostWithContentExchange();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchangeTest#testReserveConnections()
*/
@Test
@Override
public void testReserveConnections() throws Exception
{
// TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532
IgnoreTestOnBuggyIBM();
super.testReserveConnections();
}
}

View File

@ -1,114 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslSecuredContentExchangeTest
extends ContentExchangeTest
{
protected void configureServer(Server server)
throws Exception
{
setProtocol("https");
setRealm(new Realm()
{
public String getId()
{
return "MyRealm";
}
public String getPrincipal()
{
return "jetty";
}
public String getCredentials()
{
return "jetty";
}
});
SslSelectChannelConnector connector = new SslSelectChannelConnector();
File keystore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keystore.getAbsolutePath());
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
server.addConnector(connector);
File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties");
LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath());
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate( true );
constraint.setRoles(new String[]{"user", "admin"});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec( "/*" );
mapping.setConstraint( constraint );
Set<String> knownRoles = new HashSet<String>();
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
Handler handler = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
security.setHandler(handlers);
}
}

View File

@ -1,191 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.junit.Test;
/* ------------------------------------------------------------ */
public class SslSecuredErrorStatusTest
extends ErrorStatusTest
{
private Realm _testRealm;
private Realm _dummyRealm;
/* ------------------------------------------------------------ */
@Test
public void testPutUnauthorized()
throws Exception
{
setRealm(null);
doPutFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
@Test
public void testPutWrongPassword()
throws Exception
{
setRealm(_dummyRealm);
doPutFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
@Test
public void testGetUnauthorized()
throws Exception
{
setRealm(null);
doGetFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
@Test
public void testGetWrongPassword()
throws Exception
{
setRealm(_dummyRealm);
doGetFail(HttpStatus.UNAUTHORIZED_401);
setRealm(_testRealm);
}
/* ------------------------------------------------------------ */
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
_testRealm = new Realm()
{
/* ------------------------------------------------------------ */
public String getId()
{
return "MyRealm";
}
/* ------------------------------------------------------------ */
public String getPrincipal()
{
return "jetty";
}
/* ------------------------------------------------------------ */
public String getCredentials()
{
return "jetty";
}
};
_dummyRealm = new Realm()
{
/* ------------------------------------------------------------ */
public String getId()
{
return "MyRealm";
}
/* ------------------------------------------------------------ */
public String getPrincipal()
{
return "jetty";
}
/* ------------------------------------------------------------ */
public String getCredentials()
{
return "dummy";
}
};
setRealm(_testRealm);
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties");
LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath());
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate( true );
constraint.setRoles(new String[]{"user", "admin"});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec( "/*" );
mapping.setConstraint( constraint );
Set<String> knownRoles = new HashSet<String>();
knownRoles.add("user");
knownRoles.add("admin");
security.setConstraintMappings(Collections.singletonList(mapping), knownRoles);
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setStrict(false);
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(getBasePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
Handler status = new StatusHandler();
Handler test = new TestHandler(getBasePath());
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{status, test, root});
security.setHandler(handlers);
}
}

View File

@ -1,268 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.HashRealmResolver;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* Functional testing.
*/
public class SslSecurityListenerTest
{
private static final Logger LOG = Log.getLogger(SslSecurityListenerTest.class);
protected Server _server;
protected int _port;
protected HttpClient _httpClient;
protected Realm _jettyRealm;
protected int _type = HttpClient.CONNECTOR_SOCKET;
private static final String APP_CONTEXT = "localhost /";
/* ------------------------------------------------------------ */
@Before
public void setUp() throws Exception
{
startServer();
_httpClient = new HttpClient();
_httpClient.setConnectorType(_type);
_httpClient.setMaxConnectionsPerAddress(2);
_httpClient.start();
_jettyRealm = new Realm()
{
/* ------------------------------------------------------------ */
public String getId()
{
return "MyRealm";
}
/* ------------------------------------------------------------ */
public String getPrincipal()
{
return "jetty";
}
/* ------------------------------------------------------------ */
public String getCredentials()
{
return "jetty";
}
};
HashRealmResolver resolver = new HashRealmResolver();
resolver.addSecurityRealm(_jettyRealm);
_httpClient.setRealmResolver(resolver);
}
/* ------------------------------------------------------------ */
@After
public void tearDown() throws Exception
{
Thread.sleep(1000);
_httpClient.stop();
Thread.sleep(1000);
stopServer();
}
/* ------------------------------------------------------------ */
@Test
public void testSslGet() throws Exception
{
// TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532
if (System.getProperty("java.vendor").toLowerCase().indexOf("ibm")>=0)
{
LOG.warn("Skipped SSL testSslGet on IBM JVM");
return;
}
final CyclicBarrier barrier = new CyclicBarrier(2);
ContentExchange httpExchange = new ContentExchange(true)
{
/* ------------------------------------------------------------ */
@Override
protected void onResponseComplete() throws IOException
{
super.onResponseComplete();
try{barrier.await();}catch(Exception e){}
}
};
httpExchange.setURL("https://127.0.0.1:" + _port + "/");
httpExchange.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange);
barrier.await(10000,TimeUnit.SECONDS);
assertEquals(HttpServletResponse.SC_OK,httpExchange.getResponseStatus());
assertTrue(httpExchange.getResponseContent().length()>400);
}
/* ------------------------------------------------------------ */
protected void startServer() throws Exception
{
_server = new Server();
//SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslSocketConnector connector = new SslSocketConnector();
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
connector.setPort(0);
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keystore);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
_server.setConnectors(new Connector[]
{ connector });
Constraint constraint = new Constraint();
constraint.setName("Need User or Admin");
constraint.setRoles(new String[]
{ "user", "admin" });
constraint.setAuthenticate(true);
ConstraintMapping cm = new ConstraintMapping();
cm.setConstraint(constraint);
cm.setPathSpec("/*");
File realmPropFile = MavenTestingUtils.getTestResourceFile("realm.properties");
LoginService loginService = new HashLoginService("MyRealm",realmPropFile.getAbsolutePath());
_server.addBean(loginService);
BasicAuthenticator authenticator = new BasicAuthenticator();
ConstraintSecurityHandler sh = new ConstraintSecurityHandler();
sh.setAuthenticator(authenticator);
Set<String> roles = new HashSet<String>(Arrays.asList(new String[]{"user", "admin"}));
sh.setConstraintMappings(Collections.singletonList(cm), roles);
_server.setHandler(sh);
Handler testHandler = new AbstractHandler()
{
/* ------------------------------------------------------------ */
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
// System.err.println("passed authentication!\n"+((Request)request).getConnection().getRequestFields());
baseRequest.setHandled(true);
response.setStatus(200);
response.setContentType("text/plain");
if (request.getServerName().equals("jetty.eclipse.org"))
{
response.getOutputStream().println("Proxy request: " + request.getRequestURL());
}
else if (request.getMethod().equalsIgnoreCase("GET"))
{
response.getOutputStream().println("<hello>");
for (int i = 0; i < 100; i++)
{
response.getOutputStream().println(" <world>" + i + "</world>");
if (i % 20 == 0)
response.getOutputStream().flush();
}
response.getOutputStream().println("</hello>");
}
else
{
copyStream(request.getInputStream(),response.getOutputStream());
}
}
};
sh.setHandler(testHandler);
_server.start();
_port = connector.getLocalPort();
}
/* ------------------------------------------------------------ */
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) >= 0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println(e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/* ------------------------------------------------------------ */
private void stopServer() throws Exception
{
_server.stop();
}
}

View File

@ -1,30 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
public class SslSelectChannelValidationTest extends SslValidationTestBase
{
static
{
__klass = SslSelectChannelConnector.class;
__konnector = HttpClient.CONNECTOR_SELECT_CHANNEL;
}
}

View File

@ -1,30 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
public class SslSocketValidationTest extends SslValidationTestBase
{
static
{
__klass = SslSocketConnector.class;
__konnector = HttpClient.CONNECTOR_SOCKET;
}
}

View File

@ -1,103 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
public abstract class SslValidationTestBase //extends ContentExchangeTest
{
protected static Class<? extends SslConnector> __klass;
protected static int __konnector;
// certificate is valid until Jan 1, 2050
private String _keypath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-valid.keystore").getAbsolutePath();
private String _trustpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-trust.keystore").getAbsolutePath();
private String _clientpath = MavenTestingUtils.getTargetFile("test-policy/validation/jetty-client.keystore").getAbsolutePath();
private String _crlpath = MavenTestingUtils.getTargetFile("test-policy/validation/crlfile.pem").getAbsolutePath();
private String _password = "OBF:1wnl1sw01ta01z0f1tae1svy1wml";
protected void configureServer(Server server)
throws Exception
{
// setProtocol("https");
//
// SslContextFactory srvFactory = new SslContextFactory() {
// @Override
// protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
// {
// return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword);
// }
//
// @Override
// protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
// {
// return CertificateUtils.loadCRL(crlPath);
// }
// };
// srvFactory.setValidateCerts(true);
// srvFactory.setCrlPath(_crlpath);
// srvFactory.setNeedClientAuth(true);
//
// srvFactory.setKeyStorePath(_keypath);
// srvFactory.setKeyStorePassword(_password);
// srvFactory.setKeyManagerPassword(_password);
//
// srvFactory.setTrustStore(_trustpath);
// srvFactory.setTrustStorePassword(_password);
//
// Constructor<? extends SslConnector> constructor = __klass.getConstructor(SslContextFactory.class);
// SslConnector connector = constructor.newInstance(srvFactory);
// connector.setIdleTimeout(5000);
// server.addConnector(connector);
//
// Handler handler = new TestHandler(getBasePath());
//
// ServletContextHandler root = new ServletContextHandler();
// root.setContextPath("/");
// root.setResourceBase(getBasePath());
// ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
// servletHolder.setInitParameter( "gzip", "true" );
// root.addServlet( servletHolder, "/*" );
//
// HandlerCollection handlers = new HandlerCollection();
// handlers.setHandlers(new Handler[]{handler, root});
// server.setHandler( handlers );
// }
//
// @Override
// protected void configureClient(HttpClient client)
// throws Exception
// {
// client.setConnectorType(__konnector);
//
// SslContextFactory cf = client.getSslContextFactory();
// cf.setValidateCerts(true);
// cf.setCrlPath(_crlpath);
//
// cf.setKeyStorePath(_clientpath);
// cf.setKeyStorePassword(_password);
// cf.setKeyManagerPassword(_password);
//
// cf.setTrustStore(_trustpath);
// cf.setTrustStorePassword(_password);
}
}

View File

@ -1,379 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.IOException;
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 junit.framework.Assert;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
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.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TimeoutExchangeTest
{
private static HttpClient _httpClient;
private static Server _server;
private static int _port;
@BeforeClass
public static void startServer() throws Exception
{
_server = new Server();
_server.setGracefulShutdown(500);
Connector _connector = new SelectChannelConnector();
_server.addConnector(_connector);
Handler handler = new AbstractHandler()
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException
{
try
{
Long sleep = Long.parseLong(request.getParameter("sleep"));
Thread.sleep(sleep);
response.setContentType("text/html");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("<h1>Hello</h1>");
baseRequest.setHandled(true);
}
catch (InterruptedException x)
{
Thread.currentThread().interrupt();
throw new ServletException(x);
}
}
};
_server.setHandler(handler);
_server.start();
_port = _connector.getLocalPort();
}
@AfterClass
public static void stopServer() throws Exception
{
_server.stop();
_server.join();
_server = null;
}
@After
public void stopClient() throws Exception
{
if (_httpClient != null)
{
_httpClient.stop();
_httpClient = null;
}
}
private void startClient(long clientTimeout) throws Exception
{
startClient(clientTimeout, 20000);
}
private void startClient(long clientTimeout, long maxIdleTimeout) throws Exception
{
_httpClient = new HttpClient();
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(2);
_httpClient.setTimeout(clientTimeout);
_httpClient.setIdleTimeout(maxIdleTimeout);
_httpClient.start();
}
@Test
public void testDefaultTimeoutNotExpiring() throws Exception
{
startClient(300);
long serverSleep = 100;
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(4 * serverSleep, TimeUnit.MILLISECONDS));
Assert.assertFalse(httpExchange.isTimeoutOccurred());
Assert.assertTrue(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
@Test
public void testDefaultTimeoutExpiring() throws Exception
{
startClient(100);
long serverSleep = 200;
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS));
Assert.assertTrue(httpExchange.isTimeoutOccurred());
Assert.assertFalse(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
@Test
public void testExchangeTimeoutNotExpiring() throws Exception
{
startClient(100);
long serverSleep = 200;
long exchangeTimeout = 300;
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
httpExchange.setTimeout(exchangeTimeout);
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(2 * exchangeTimeout, TimeUnit.MILLISECONDS));
Assert.assertFalse(httpExchange.isTimeoutOccurred());
Assert.assertTrue(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
@Test
public void testExchangeTimeoutExpiring() throws Exception
{
startClient(500);
long serverSleep = 300;
long exchangeTimeout = 100;
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
httpExchange.setTimeout(exchangeTimeout);
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS));
Assert.assertTrue(httpExchange.isTimeoutOccurred());
Assert.assertFalse(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
@Test
public void testDefaultTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception
{
startClient(500,150);
long serverSleep = 300;
// The idle timeout is shorter than the default timeout, but will be
// temporarily increased on the endpoint in order for the exchange to complete.
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS));
Assert.assertFalse(httpExchange.isTimeoutOccurred());
Assert.assertTrue(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
@Test
public void testExchangeTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception
{
startClient(500,150);
long serverSleep = 150;
long exchangeTimeout = 300;
// The idle timeout is shorter than the default timeout, but will be
// temporarily increased on the endpoint in order for the exchange to complete.
CustomContentExchange httpExchange = new CustomContentExchange();
httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep);
httpExchange.setMethod(HttpMethod.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>"));
httpExchange.setTimeout(exchangeTimeout);
_httpClient.send(httpExchange);
Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS));
Assert.assertFalse(httpExchange.isTimeoutOccurred());
Assert.assertTrue(httpExchange.isResponseReceived());
Assert.assertFalse(httpExchange.isErrorOccurred());
}
private class CustomContentExchange extends ContentExchange
{
private final CountDownLatch _doneLatch = new CountDownLatch(1);
private boolean _errorOccurred = false;
private boolean _timeoutOccurred = false;
private boolean _responseReceived = false;
public boolean isErrorOccurred()
{
return _errorOccurred;
}
public boolean isTimeoutOccurred()
{
return _timeoutOccurred;
}
public boolean isResponseReceived()
{
return _responseReceived;
}
public CustomContentExchange()
{
super(true);
}
@Override
protected void onResponseComplete() throws IOException
{
try
{
super.onResponseComplete();
}
finally
{
doTaskCompleted();
}
}
@Override
protected void onExpire()
{
try
{
super.onExpire();
}
finally
{
doTaskCompleted();
}
}
@Override
protected void onException(Throwable ex)
{
try
{
super.onException(ex);
}
finally
{
doTaskCompleted(ex);
}
}
@Override
protected void onConnectionFailed(Throwable ex)
{
try
{
super.onConnectionFailed(ex);
}
finally
{
doTaskCompleted(ex);
}
}
protected void doTaskCompleted()
{
int exchangeState = getStatus();
try
{
if (exchangeState == HttpExchange.STATUS_COMPLETED)
{
// process the response as the state is ok
try
{
int responseCode = getResponseStatus();
if (responseCode >= HttpStatus.CONTINUE_100 && responseCode < HttpStatus.MULTIPLE_CHOICES_300)
{
_responseReceived = true;
}
else
{
_errorOccurred = true;
}
}
catch (Exception e)
{
_errorOccurred = true;
e.printStackTrace();
}
}
else if (exchangeState == HttpExchange.STATUS_EXPIRED)
{
_timeoutOccurred = true;
}
else
{
_errorOccurred = true;
}
}
finally
{
// make sure to lower the latch
getDoneLatch().countDown();
}
}
protected void doTaskCompleted(Throwable ex)
{
try
{
_errorOccurred = true;
}
finally
{
// make sure to lower the latch
getDoneLatch().countDown();
}
}
public CountDownLatch getDoneLatch()
{
return _doneLatch;
}
}
}

View File

@ -1,438 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.hamcrest.Matchers.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
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.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class TimeoutTest
{
private static final Logger logger = Log.getLogger(TimeoutTest.class);
private final AtomicInteger httpParses = new AtomicInteger();
private final AtomicInteger httpRequests = new AtomicInteger();
private ExecutorService threadPool;
private Server server;
private int serverPort;
private final AtomicReference<EndPoint> serverEndPoint = new AtomicReference<EndPoint>();
@Before
public void init() throws Exception
{
threadPool = Executors.newCachedThreadPool();
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector()
{
@Override
protected AsyncConnection newConnection(SocketChannel channel, final AsyncEndPoint endPoint)
{
serverEndPoint.set(endPoint);
return new org.eclipse.jetty.server.AsyncHttpConnection(this,endPoint,getServer())
{
@Override
protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler)
{
return new HttpParser(requestBuffers,endPoint,requestHandler)
{
@Override
public int parseNext() throws IOException
{
httpParses.incrementAndGet();
return super.parseNext();
}
};
}
};
}
};
connector.setMaxIdleTime(2000);
// connector.setPort(5870);
connector.setPort(0);
server.addConnector(connector);
server.setHandler(new AbstractHandler()
{
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException,
ServletException
{
httpRequests.incrementAndGet();
request.setHandled(true);
String contentLength = request.getHeader("Content-Length");
if (contentLength != null)
{
int length = Integer.parseInt(contentLength);
ServletInputStream input = request.getInputStream();
for (int i = 0; i < length; ++i)
input.read();
}
}
});
server.start();
serverPort = connector.getLocalPort();
httpRequests.set(0);
logger.debug(" => :{}",serverPort);
}
@After
public void destroy() throws Exception
{
if (server != null)
server.stop();
if (threadPool != null)
threadPool.shutdownNow();
}
private Socket newClient() throws IOException, InterruptedException
{
Socket client = new Socket("localhost",serverPort);
return client;
}
/**
* Test that performs a normal http POST request, with connection:close.
* Check that shutdownOutput is sufficient to close the server connection.
*/
@Test
public void testServerCloseClientDoesClose() throws Exception
{
// Log.getLogger("").setDebugEnabled(true);
final Socket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
byte[] data = new byte[3 * 1024];
Arrays.fill(data,(byte)'Y');
String content = new String(data,"UTF-8");
// The request section
StringBuilder req = new StringBuilder();
req.append("POST / HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Content-Type: text/plain\r\n");
req.append("Content-Length: ").append(content.length()).append("\r\n");
req.append("Connection: close\r\n");
req.append("\r\n");
// and now, the POST content section.
req.append(content);
// Send request to server
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
InputStream in = null;
InputStreamReader isr = null;
BufferedReader reader = null;
try
{
in = client.getInputStream();
isr = new InputStreamReader(in);
reader = new BufferedReader(isr);
// Read the response header
String line = reader.readLine();
Assert.assertNotNull(line);
Assert.assertThat(line,startsWith("HTTP/1.1 200 "));
while ((line = reader.readLine()) != null)
{
if (line.trim().length() == 0)
{
break;
}
}
Assert.assertEquals("one request handled",1,httpRequests.get());
Assert.assertEquals("EOF received",-1,client.getInputStream().read());
// shutdown the output
client.shutdownOutput();
// Check that we did not spin
int httpParseCount = httpParses.get();
Assert.assertThat(httpParseCount,lessThan(50));
// Try to write another request (to prove that stream is closed)
try
{
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
Assert.fail("Should not have been able to send a second POST request (connection: close)");
}
catch(SocketException e)
{
}
Assert.assertEquals("one request handled",1,httpRequests.get());
}
finally
{
IO.close(reader);
IO.close(isr);
IO.close(in);
closeClient(client);
}
}
/**
* Test that performs a seemingly normal http POST request, but with
* a client that issues "connection: close", and then attempts to
* write a second POST request.
* <p>
* The connection should be closed by the server
*/
@Test
public void testServerCloseClientMoreDataSent() throws Exception
{
// Log.getLogger("").setDebugEnabled(true);
final Socket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
byte[] data = new byte[3 * 1024];
Arrays.fill(data,(byte)'Y');
String content = new String(data,"UTF-8");
// The request section
StringBuilder req = new StringBuilder();
req.append("POST / HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Content-Type: text/plain\r\n");
req.append("Content-Length: ").append(content.length()).append("\r\n");
req.append("Connection: close\r\n");
req.append("\r\n");
// and now, the POST content section.
req.append(content);
// Send request to server
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
InputStream in = null;
InputStreamReader isr = null;
BufferedReader reader = null;
try
{
in = client.getInputStream();
isr = new InputStreamReader(in);
reader = new BufferedReader(isr);
// Read the response header
String line = reader.readLine();
Assert.assertNotNull(line);
Assert.assertThat(line,startsWith("HTTP/1.1 200 "));
while ((line = reader.readLine()) != null)
{
if (line.trim().length() == 0)
{
break;
}
}
Assert.assertEquals("EOF received",-1,client.getInputStream().read());
Assert.assertEquals("one request handled",1,httpRequests.get());
// Don't shutdown the output
// client.shutdownOutput();
// server side seeking EOF
Assert.assertTrue("is open",serverEndPoint.get().isOpen());
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
Assert.assertFalse("close not received",serverEndPoint.get().isInputShutdown());
// Check that we did not spin
TimeUnit.SECONDS.sleep(1);
int httpParseCount = httpParses.get();
Assert.assertThat(httpParseCount,lessThan(50));
// Write another request (which is ignored as the stream is closing), which causes real close.
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
// Check that we did not spin
TimeUnit.SECONDS.sleep(1);
httpParseCount = httpParses.get();
Assert.assertThat(httpParseCount,lessThan(50));
// server side is closed
Assert.assertFalse("is open",serverEndPoint.get().isOpen());
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
Assert.assertTrue("close not received",serverEndPoint.get().isInputShutdown());
Assert.assertEquals("one request handled",1,httpRequests.get());
}
finally
{
IO.close(reader);
IO.close(isr);
IO.close(in);
closeClient(client);
}
}
/**
* Test that performs a seemingly normal http POST request, but with
* a client that issues "connection: close", and then does not close
* the connection after reading the response.
* <p>
* The connection should be closed by the server after a timeout.
*/
@Test
public void testServerCloseClientDoesNotClose() throws Exception
{
// Log.getLogger("").setDebugEnabled(true);
final Socket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
byte[] data = new byte[3 * 1024];
Arrays.fill(data,(byte)'Y');
String content = new String(data,"UTF-8");
// The request section
StringBuilder req = new StringBuilder();
req.append("POST / HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Content-Type: text/plain\r\n");
req.append("Content-Length: ").append(content.length()).append("\r\n");
req.append("Connection: close\r\n");
req.append("\r\n");
// and now, the POST content section.
req.append(content);
// Send request to server
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
InputStream in = null;
InputStreamReader isr = null;
BufferedReader reader = null;
try
{
in = client.getInputStream();
isr = new InputStreamReader(in);
reader = new BufferedReader(isr);
// Read the response header
String line = reader.readLine();
Assert.assertNotNull(line);
Assert.assertThat(line,startsWith("HTTP/1.1 200 "));
while ((line = reader.readLine()) != null)
{
if (line.trim().length() == 0)
{
break;
}
}
Assert.assertEquals("EOF received",-1,client.getInputStream().read());
Assert.assertEquals("one request handled",1,httpRequests.get());
// Don't shutdown the output
// client.shutdownOutput();
// server side seeking EOF
Assert.assertTrue("is open",serverEndPoint.get().isOpen());
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
Assert.assertFalse("close not received",serverEndPoint.get().isInputShutdown());
// Wait for the server idle timeout
TimeUnit.SECONDS.sleep(3);
int httpParseCount = httpParses.get();
Assert.assertThat(httpParseCount,lessThan(50));
// server side is closed
Assert.assertFalse("is open",serverEndPoint.get().isOpen());
Assert.assertTrue("close sent",serverEndPoint.get().isOutputShutdown());
Assert.assertTrue("close not received",serverEndPoint.get().isInputShutdown());
Assert.assertEquals("one request handled",1,httpRequests.get());
// client will eventually get broken pipe if it keeps writing
try
{
for (int i=0;i<1000;i++)
{
clientOutput.write(req.toString().getBytes("UTF-8"));
clientOutput.flush();
}
Assert.fail("Client should have seen a broken pipe");
}
catch(IOException e)
{
// expected broken pipe
}
}
finally
{
IO.close(reader);
IO.close(isr);
IO.close(in);
closeClient(client);
}
}
private void closeClient(Socket client) throws IOException
{
client.close();
}
}

View File

@ -1,181 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpMethod;
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.eclipse.jetty.util.IO;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Functional testing for HttpExchange.
*
* @author Matthew Purland
* @author Greg Wilkins
*/
public class UnexpectedDataTest
{
private Server _server;
private int _port;
private HttpClient _httpClient;
private Connector _connector;
private AtomicInteger _count = new AtomicInteger();
@Before
public void setUp() throws Exception
{
startServer();
_httpClient = new HttpClient();
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(1);
_httpClient.start();
}
@After
public void tearDown() throws Exception
{
_httpClient.stop();
Thread.sleep(500);
stopServer();
}
@Test
public void testUnexpectedData() throws Exception
{
for (int i = 0; i < 4; ++i)
{
final CountDownLatch done = new CountDownLatch(1);
ContentExchange httpExchange = new ContentExchange()
{
protected void onResponseComplete() throws IOException
{
super.onResponseComplete();
done.countDown();
}
};
httpExchange.setURL("http://localhost:" + _port + "/?i=" + i);
httpExchange.setMethod(HttpMethod.GET);
_httpClient.send(httpExchange);
Assert.assertTrue(done.await(1000, TimeUnit.SECONDS));
int status = httpExchange.getStatus();
String result = httpExchange.getResponseContent();
Assert.assertEquals("i=" + i, 0, result.indexOf("<hello>"));
Assert.assertEquals("i=" + i, result.length() - 10, result.indexOf("</hello>"));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, status);
// Give the client the time to read -1 from server before issuing the next request
// There is currently no simple way to be notified of connection closed.
Thread.sleep(500);
}
}
protected void newServer() throws Exception
{
_server = new Server();
_server.setGracefulShutdown(500);
_connector = new SelectChannelConnector();
_connector.setPort(0);
_server.setConnectors(new Connector[]{_connector});
}
protected void startServer() throws Exception
{
newServer();
_server.setHandler(new AbstractHandler()
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
int i = 0;
try
{
baseRequest.setHandled(true);
response.setStatus(200);
_count.incrementAndGet();
if (request.getMethod().equalsIgnoreCase("GET"))
{
StringBuilder buffer = new StringBuilder();
buffer.append("<hello>\r\n");
for (; i < 100; i++)
{
buffer.append(" <world>").append(i).append("</world>\r\n");
}
buffer.append("</hello>\r\n");
byte[] buff = buffer.toString().getBytes();
response.setContentLength(buff.length);
buffer.append("extra data");
buff = buffer.toString().getBytes();
OutputStream out = response.getOutputStream();
out.write(buff, 0, buff.length);
out.flush();
}
else
{
response.setContentType(request.getContentType());
int size = request.getContentLength();
ByteArrayOutputStream bout = new ByteArrayOutputStream(size > 0 ? size : 32768);
IO.copy(request.getInputStream(), bout);
response.getOutputStream().write(bout.toByteArray());
}
}
catch (IOException e)
{
e.printStackTrace();
throw e;
}
catch (Throwable e)
{
e.printStackTrace();
throw new ServletException(e);
}
}
});
_server.start();
_port = _connector.getLocalPort();
}
private void stopServer() throws Exception
{
_server.stop();
}
}

View File

@ -1,264 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketBuffers;
import org.eclipse.jetty.websocket.WebSocketConnectionD00;
import org.eclipse.jetty.websocket.WebSocketHandler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* Functional testing for HttpExchange.
*/
public class WebSocketUpgradeTest
{
protected Server _server;
protected int _port;
protected HttpClient _httpClient;
protected Connector _connector;
protected ConcurrentLinkedQueue<TestWebSocket> _webSockets= new ConcurrentLinkedQueue<TestWebSocket>();
protected WebSocketHandler _handler;
protected TestWebSocket _websocket;
final BlockingQueue<Object> _results = new ArrayBlockingQueue<Object>(100);
/* ------------------------------------------------------------ */
@Before
public void setUp() throws Exception
{
startServer();
_httpClient=new HttpClient();
_httpClient.setIdleTimeout(2000);
_httpClient.setTimeout(2500);
_httpClient.setConnectTimeout(1000);
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(10);
_httpClient.start();
}
/* ------------------------------------------------------------ */
@After
public void tearDown() throws Exception
{
_httpClient.stop();
Thread.sleep(500);
stopServer();
}
/* ------------------------------------------------------------ */
@Test
public void testGetWithContentExchange() throws Exception
{
final WebSocket clientWS = new WebSocket.OnTextMessage()
{
Connection _connection;
/* ------------------------------------------------------------ */
public void onClose(int closeCode, String message)
{
}
/* ------------------------------------------------------------ */
public void onOpen(Connection connection)
{
_connection=connection;
_results.add("clientWS.onConnect");
_results.add(_connection);
}
/* ------------------------------------------------------------ */
public void onMessage(String data)
{
_results.add("clientWS.onMessage");
_results.add(data);
}
};
HttpExchange httpExchange=new HttpExchange()
{
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.ByteBuffer, int, org.eclipse.jetty.io.ByteBuffer)
*/
@Override
protected void onResponseStatus(ByteBuffer version, int status, ByteBuffer reason) throws IOException
{
waitFor(2);
_results.add(new Integer(status));
super.onResponseStatus(version,status,reason);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onSwitchProtocol(org.eclipse.jetty.io.EndPoint)
*/
@Override
protected Connection onSwitchProtocol(EndPoint endp) throws IOException
{
waitFor(3);
WebSocketConnectionD00 connection = new WebSocketConnectionD00(clientWS,endp,new WebSocketBuffers(4096),System.currentTimeMillis(),1000,"");
_results.add("onSwitchProtocol");
_results.add(connection);
clientWS.onOpen(connection);
return connection;
}
/* ------------------------------------------------------------ */
private void waitFor(int results)
{
try
{
int c=10;
while(_results.size()<results && c-->0)
Thread.sleep(10);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
};
httpExchange.setURL("http://localhost:"+_port+"/");
httpExchange.setMethod(HttpMethod.GET);
httpExchange.addRequestHeader("Upgrade","WebSocket");
httpExchange.addRequestHeader("Connection","Upgrade");
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertEquals("serverWS.onConnect", _results.poll(1,TimeUnit.SECONDS));
TestWebSocket serverWS = (TestWebSocket)_results.poll(1,TimeUnit.SECONDS);
assertEquals(new Integer(101), _results.poll(1,TimeUnit.SECONDS));
assertEquals("onSwitchProtocol", _results.poll(1,TimeUnit.SECONDS));
WebSocketConnectionD00 client_conn=(WebSocketConnectionD00)_results.poll(1,TimeUnit.SECONDS);
assertEquals("clientWS.onConnect", _results.poll(1,TimeUnit.SECONDS));
assertEquals(client_conn, _results.poll(1,TimeUnit.SECONDS));
client_conn.sendMessage("hello world");
assertEquals("serverWS.onMessage", _results.poll(1,TimeUnit.SECONDS));
assertEquals("hello world", _results.poll(1,TimeUnit.SECONDS));
serverWS.sendMessage("buongiorno");
assertEquals("clientWS.onMessage", _results.poll(1,TimeUnit.SECONDS));
assertEquals("buongiorno", _results.poll(1,TimeUnit.SECONDS));
}
/* ------------------------------------------------------------ */
protected void newServer() throws Exception
{
_server=new Server();
_server.setGracefulShutdown(500);
_connector=new SelectChannelConnector();
_connector.setPort(0);
_server.setConnectors(new Connector[] { _connector });
}
/* ------------------------------------------------------------ */
protected void startServer() throws Exception
{
newServer();
_handler= new WebSocketHandler()
{
/* ------------------------------------------------------------ */
public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
{
_websocket = new TestWebSocket();
return _websocket;
}
};
_server.setHandler(_handler);
_server.start();
_port=_connector.getLocalPort();
}
/* ------------------------------------------------------------ */
private void stopServer() throws Exception
{
_server.stop();
_server.join();
}
/* ------------------------------------------------------------ */
class TestWebSocket implements WebSocket.OnTextMessage
{
Connection _connection;
/* ------------------------------------------------------------ */
public void onOpen(Connection connection)
{
_connection=connection;
_webSockets.add(this);
_results.add("serverWS.onConnect");
_results.add(this);
}
/* ------------------------------------------------------------ */
public void onMessage(final String data)
{
_results.add("serverWS.onMessage");
_results.add(data);
}
/* ------------------------------------------------------------ */
public void onClose(int code, String message)
{
_results.add("onClose");
_webSockets.remove(this);
}
/* ------------------------------------------------------------ */
public void sendMessage(String msg) throws IOException
{
_connection.sendMessage(msg);
}
}
}

View File

@ -1,144 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client;
import java.io.File;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.PathAssert;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
* Functional testing for HttpExchange.
*/
public class WebdavListenerTest
{
protected String _scheme = "http://";
protected Server _server;
protected int _port;
protected HttpClient _httpClient;
protected Connector _connector;
private String _username = "janb";
private String _password = "xxxxx";
private String _singleFileURL;
private String _dirFileURL;
private String _dirURL;
@Before
public void setUp() throws Exception
{
_singleFileURL = "https://dav.codehaus.org/user/" + _username + "/foo.txt";
_dirURL = "https://dav.codehaus.org/user/" + _username + "/ttt/";
_dirFileURL = _dirURL+"foo.txt";
_scheme="https://";
_httpClient=new HttpClient();
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
//_httpClient.setMaxConnectionsPerAddress(4);
_httpClient.setRealmResolver( new SimpleRealmResolver (
new Realm(){
public String getId()
{
return _username + "'s webspace"; //To change body of implemented methods use File | Settings | File Templates.
}
public String getPrincipal()
{
return _username; //To change body of implemented methods use File | Settings | File Templates.
}
public String getCredentials()
{
return _password; //To change body of implemented methods use File | Settings | File Templates.
}
}
));
_httpClient.registerListener( "org.eclipse.jetty.client.webdav.WebdavListener");
_httpClient.start();
}
@After
public void tearDown () throws Exception
{
_httpClient.stop();
}
@Test
@Ignore("Only works with real WebDAV server")
public void testPUTandDELETEwithSSL() throws Exception
{
File file = MavenTestingUtils.getTestResourceFile("foo.txt");
PathAssert.assertFileExists("WebDAV test file", file);
//PUT a FILE
ContentExchange singleFileExchange = new ContentExchange();
singleFileExchange.setURL(_singleFileURL);
singleFileExchange.setMethod( HttpMethod.PUT );
singleFileExchange.setFileForUpload(file);
singleFileExchange.setRequestHeader( "Content-Type", "application/octet-stream");
singleFileExchange.setRequestHeader("Content-Length", String.valueOf( file.length() ));
_httpClient.send(singleFileExchange);
singleFileExchange.waitForDone();
String result = singleFileExchange.getResponseContent();
Assert.assertEquals(201, singleFileExchange.getResponseStatus());
//PUT a FILE in a directory hierarchy
ContentExchange dirFileExchange = new ContentExchange();
dirFileExchange.setURL(_dirFileURL);
dirFileExchange.setMethod( HttpMethod.PUT );
dirFileExchange.setFileForUpload(file);
dirFileExchange.setRequestHeader( "Content-Type", "application/octet-stream");
dirFileExchange.setRequestHeader("Content-Length", String.valueOf( file.length() ));
_httpClient.send(dirFileExchange);
dirFileExchange.waitForDone();
result = dirFileExchange.getResponseContent();
Assert.assertEquals(201, singleFileExchange.getResponseStatus());
//DELETE the single file
HttpExchange del = new HttpExchange();
del.setURL(_singleFileURL);
del.setMethod(HttpMethod.DELETE);
_httpClient.send(del);
del.waitForDone();
//DELETE the whole dir
del.setURL(_dirURL);
del.setMethod(HttpMethod.DELETE);
del.setRequestHeader("Depth", "infinity");
_httpClient.send(del);
del.waitForDone();
}
}

View File

@ -1,60 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.helperClasses;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/* ------------------------------------------------------------ */
/**
*/
public abstract class AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
private static final Logger LOG = Log.getLogger(AbstractSslServerAndClientCreator.class);
/* ------------------------------------------------------------ */
public Server createServer() throws Exception
{
Server server = new Server();
// SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslSocketConnector connector = new SslSocketConnector();
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
connector.setPort(0);
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keystore);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
server.setConnectors(new Connector[]{ connector });
server.setHandler(new GenericServerHandler());
server.start();
return server;
}
}

View File

@ -1,42 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.helperClasses;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
public class AsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
/* ------------------------------------------------------------ */
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setMaxConnectionsPerAddress(2);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
httpClient.getSslContextFactory().setKeyStorePath(keystore);
httpClient.getSslContextFactory().setKeyStorePassword("storepwd");
httpClient.getSslContextFactory().setKeyManagerPassword("keypwd");
httpClient.start();
return httpClient;
}
}

View File

@ -1,45 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.helperClasses;
import java.io.FileInputStream;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
public class ExternalKeyStoreAsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setMaxConnectionsPerAddress(2);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
httpClient.setKeyStorePassword("storepwd");
httpClient.setKeyManagerPassword("keypwd");
httpClient.start();
return httpClient;
}
}

View File

@ -1,109 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.helperClasses;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* Generic Server Handler used for various client tests.
*/
public class GenericServerHandler extends AbstractHandler
{
private static final Logger LOG = Log.getLogger(GenericServerHandler.class);
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
int i = 0;
try
{
baseRequest.setHandled(true);
response.setStatus(200);
if (request.getServerName().equals("jetty.eclipse.org"))
{
response.getOutputStream().println("Proxy request: " + request.getRequestURL());
response.getOutputStream().println(request.getHeader(HttpHeader.PROXY_AUTHORIZATION));
}
else if (request.getMethod().equalsIgnoreCase("GET"))
{
response.getOutputStream().println("<hello>");
for (; i < 100; i++)
{
response.getOutputStream().println(" <world>" + i + "</world");
if (i % 20 == 0)
response.getOutputStream().flush();
}
response.getOutputStream().println("</hello>");
}
else if (request.getMethod().equalsIgnoreCase("OPTIONS"))
{
if ("*".equals(target))
{
response.setContentLength(0);
response.setHeader("Allow","GET,HEAD,POST,PUT,DELETE,MOVE,OPTIONS,TRACE");
}
}
else if (request.getMethod().equalsIgnoreCase("SLEEP"))
{
Thread.sleep(10000);
}
else
{
response.setContentType(request.getContentType());
int size = request.getContentLength();
ByteArrayOutputStream bout = new ByteArrayOutputStream(size > 0?size:32768);
IO.copy(request.getInputStream(),bout);
response.getOutputStream().write(bout.toByteArray());
}
}
catch (InterruptedException e)
{
LOG.debug(e);
}
catch (EofException e)
{
LOG.info(e.toString());
LOG.debug(e);
throw e;
}
catch (IOException e)
{
LOG.warn(e);
throw e;
}
catch (Throwable e)
{
LOG.warn(e);
throw new ServletException(e);
}
}
}

View File

@ -1,54 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.helperClasses;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
public class HttpServerAndClientCreator implements ServerAndClientCreator
{
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setIdleTimeout(idleTimeout);
httpClient.setTimeout(timeout);
httpClient.setConnectTimeout(connectTimeout);
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setMaxConnectionsPerAddress(2);
httpClient.start();
return httpClient;
}
public Server createServer() throws Exception
{
Server _server = new Server();
_server.setGracefulShutdown(500);
Connector _connector = new SelectChannelConnector();
_connector.setMaxIdleTime(3000000);
_connector.setPort(0);
_server.setConnectors(new Connector[]{ _connector });
_server.setHandler(new GenericServerHandler());
_server.start();
return _server;
}
}

View File

@ -1,29 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.helperClasses;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Server;
public interface ServerAndClientCreator
{
Server createServer() throws Exception;
HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception;
}

View File

@ -1,37 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.helperClasses;
import org.eclipse.jetty.client.HttpClient;
public class SslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setIdleTimeout(idleTimeout);
httpClient.setTimeout(timeout);
httpClient.setConnectTimeout(connectTimeout);
httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
httpClient.setMaxConnectionsPerAddress(2);
httpClient.start();
return httpClient;
}
}

View File

@ -1,51 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.client.security;
import org.junit.Test;
public class SecurityResolverTest
{
@Test
public void testNothing()
{
}
/* TODO
public void testCredentialParsing() throws Exception
{
SecurityListener resolver = new SecurityListener();
Buffer value = new ByteArrayBuffer("basic a=b".getBytes());
assertEquals( "basic", resolver.scrapeAuthenticationType( value.toString() ) );
assertEquals( 1, resolver.scrapeAuthenticationDetails( value.toString() ).size() );
value = new ByteArrayBuffer("digest a=boo, c=\"doo\" , egg=foo".getBytes());
assertEquals( "digest", resolver.scrapeAuthenticationType( value.toString() ) );
Map<String,String> testMap = resolver.scrapeAuthenticationDetails( value.toString() );
assertEquals( 3, testMap.size() );
assertEquals( "boo", testMap.get("a") );
assertEquals( "doo", testMap.get("c") );
assertEquals( "foo", testMap.get("egg") );
}
*/
}

View File

@ -1 +0,0 @@
<html/>

View File

@ -1,22 +0,0 @@
#
# This file defines users passwords and roles for a HashUserRealm
#
# The format is
# <username>: <password>[,<rolename> ...]
#
# Passwords may be clear text, obfuscated or checksummed. The class
# org.eclipse.util.Password should be used to generate obfuscated
# passwords or password checksums
#
# If DIGEST Authentication is used, the password must be in a recoverable
# format, either plain text or OBF:.
#
# if using digest authentication, do not MD5-hash the password
jetty: jetty,user
admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin,user
other: OBF:1xmk1w261u9r1w1c1xmq,user
plain: plain,user
user: password,user
# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
digest: MD5:6e120743ad67abfbc385bc2bb754e297,user