Merge remote-tracking branch 'origin/master' into jetty-8
This commit is contained in:
commit
1fbec51c8a
11
VERSION.txt
11
VERSION.txt
|
@ -43,6 +43,17 @@ jetty-8.1.0.RC0 - 30 November 2011
|
|||
+ 364283 can't parse the servlet multipart-config for the web.xml
|
||||
+ 364430 Support web.xml enabled state for servlets
|
||||
|
||||
jetty-7.6.0.RC3 - 05 January 2012
|
||||
+ 367433 added tests to investigate
|
||||
+ 367435 improved D00 test harness
|
||||
+ 367485 HttpExchange canceled before response do not release connection.
|
||||
+ 367502 WebSocket connections should be closed when application context is
|
||||
stopped.
|
||||
+ 367591 corrected configuration.xml version to 7.6
|
||||
+ 367635 Added support for start.d directory
|
||||
+ 637638 limit number of form parameters to avoid DOS
|
||||
+ JETTY-1467 close half closed when idle
|
||||
|
||||
jetty-7.6.0.RC2 - 22 December 2011
|
||||
+ 364638 HttpParser closes if data received while seeking EOF. Tests fixed to
|
||||
cope
|
||||
|
|
|
@ -180,20 +180,23 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
|
|||
|
||||
String method=_exchange.getMethod();
|
||||
String uri = _exchange.getRequestURI();
|
||||
if (_destination.isProxied() && !HttpMethods.CONNECT.equals(method) && uri.startsWith("/"))
|
||||
if (_destination.isProxied())
|
||||
{
|
||||
boolean secure = _destination.isSecure();
|
||||
String host = _destination.getAddress().getHost();
|
||||
int port = _destination.getAddress().getPort();
|
||||
StringBuilder absoluteURI = new StringBuilder();
|
||||
absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.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();
|
||||
if (!HttpMethods.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 ? HttpSchemes.HTTPS : HttpSchemes.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);
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -111,6 +111,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
@ -125,12 +126,14 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
||||
jetty.removeContext("foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
// FIXME: hot undeploy with removal not working! - jetty.assertNoWebAppContexts();
|
||||
|
@ -151,6 +154,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
@ -165,6 +169,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
|
||||
// This should result in the existing foo.war being replaced with the new foo.war
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
||||
// Test that webapp response contains "-2"
|
||||
|
|
|
@ -31,6 +31,14 @@
|
|||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<verbose>false</verbose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-http</artifactId>
|
||||
<name>Jetty :: Http Utility</name>
|
||||
<properties>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<name>Jetty :: IO Utility</name>
|
||||
<properties>
|
||||
|
|
|
@ -42,36 +42,38 @@ import org.eclipse.jetty.server.Authentication.User;
|
|||
public class JaspiAuthenticator implements Authenticator
|
||||
{
|
||||
private final ServerAuthConfig _authConfig;
|
||||
|
||||
private final Map _authProperties;
|
||||
|
||||
private final ServletCallbackHandler _callbackHandler;
|
||||
|
||||
private final Subject _serviceSubject;
|
||||
|
||||
private final boolean _allowLazyAuthentication;
|
||||
|
||||
private final IdentityService _identityService;
|
||||
|
||||
private final DeferredAuthentication _deferred;
|
||||
|
||||
public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler,
|
||||
Subject serviceSubject, boolean allowLazyAuthentication, IdentityService identityService)
|
||||
public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, Subject serviceSubject,
|
||||
boolean allowLazyAuthentication, IdentityService identityService)
|
||||
{
|
||||
// TODO maybe pass this in via setConfiguration ?
|
||||
if (callbackHandler == null)
|
||||
throw new NullPointerException("No CallbackHandler");
|
||||
if (authConfig == null)
|
||||
throw new NullPointerException("No AuthConfig");
|
||||
if (callbackHandler == null) throw new NullPointerException("No CallbackHandler");
|
||||
if (authConfig == null) throw new NullPointerException("No AuthConfig");
|
||||
this._authConfig = authConfig;
|
||||
this._authProperties = authProperties;
|
||||
this._callbackHandler = callbackHandler;
|
||||
this._serviceSubject = serviceSubject;
|
||||
this._allowLazyAuthentication = allowLazyAuthentication;
|
||||
this._identityService = identityService;
|
||||
this._deferred=new DeferredAuthentication(this);
|
||||
this._deferred = new DeferredAuthentication(this);
|
||||
}
|
||||
|
||||
|
||||
public void setConfiguration(AuthConfiguration configuration)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getAuthMethod()
|
||||
{
|
||||
return "JASPI";
|
||||
|
@ -79,56 +81,71 @@ public class JaspiAuthenticator implements Authenticator
|
|||
|
||||
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
|
||||
{
|
||||
if (_allowLazyAuthentication && !mandatory)
|
||||
return _deferred;
|
||||
|
||||
System.err.println("\nJaspiAuthenticator.validateRequest, uri=" + ((javax.servlet.http.HttpServletRequest) request).getRequestURI()
|
||||
+ " lazy="
|
||||
+ _allowLazyAuthentication
|
||||
+ " mandatory="
|
||||
+ mandatory);
|
||||
new Throwable().printStackTrace();
|
||||
|
||||
JaspiMessageInfo info = new JaspiMessageInfo(request, response, mandatory);
|
||||
request.setAttribute("org.eclipse.jetty.security.jaspi.info",info);
|
||||
return validateRequest(info);
|
||||
request.setAttribute("org.eclipse.jetty.security.jaspi.info", info);
|
||||
|
||||
Authentication a = validateRequest(info);
|
||||
|
||||
//if its not mandatory to authenticate, and the authenticator returned UNAUTHENTICATED, we treat it as authentication deferred
|
||||
if (_allowLazyAuthentication && !info.isAuthMandatory() && a == Authentication.UNAUTHENTICATED)
|
||||
a =_deferred;
|
||||
|
||||
System.err.println("JaspiAuthenticator.validateRequest returning "+a);
|
||||
return a;
|
||||
}
|
||||
|
||||
// most likely validatedUser is not needed here.
|
||||
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
|
||||
{
|
||||
JaspiMessageInfo info = (JaspiMessageInfo)req.getAttribute("org.eclipse.jetty.security.jaspi.info");
|
||||
if (info==null) throw new NullPointerException("MeesageInfo from request missing: " + req);
|
||||
return secureResponse(info,validatedUser);
|
||||
System.err.println("JaspiAuthenticator.secureResponse uri=" + ((javax.servlet.http.HttpServletRequest) req).getRequestURI());
|
||||
|
||||
JaspiMessageInfo info = (JaspiMessageInfo) req.getAttribute("org.eclipse.jetty.security.jaspi.info");
|
||||
if (info == null) throw new NullPointerException("MessageInfo from request missing: " + req);
|
||||
return secureResponse(info, validatedUser);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Authentication validateRequest(JaspiMessageInfo messageInfo) throws ServerAuthException
|
||||
{
|
||||
try
|
||||
{
|
||||
System.err.println("jaspAuthenticator.validateRequest(info)");
|
||||
String authContextId = _authConfig.getAuthContextID(messageInfo);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
|
||||
Subject clientSubject = new Subject();
|
||||
|
||||
AuthStatus authStatus = authContext.validateRequest(messageInfo,clientSubject,_serviceSubject);
|
||||
// String authMethod = (String)messageInfo.getMap().get(JaspiMessageInfo.AUTH_METHOD_KEY);
|
||||
AuthStatus authStatus = authContext.validateRequest(messageInfo, clientSubject, _serviceSubject);
|
||||
// String authMethod =
|
||||
// (String)messageInfo.getMap().get(JaspiMessageInfo.AUTH_METHOD_KEY);
|
||||
|
||||
if (authStatus == AuthStatus.SEND_CONTINUE) return Authentication.SEND_CONTINUE;
|
||||
if (authStatus == AuthStatus.SEND_FAILURE) return Authentication.SEND_FAILURE;
|
||||
|
||||
if (authStatus == AuthStatus.SEND_CONTINUE)
|
||||
return Authentication.SEND_CONTINUE;
|
||||
if (authStatus == AuthStatus.SEND_FAILURE)
|
||||
return Authentication.SEND_FAILURE;
|
||||
|
||||
if (authStatus == AuthStatus.SUCCESS)
|
||||
{
|
||||
Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
|
||||
Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
|
||||
UserIdentity userIdentity;
|
||||
if (ids.size() > 0)
|
||||
{
|
||||
userIdentity = ids.iterator().next();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
CallerPrincipalCallback principalCallback = _callbackHandler.getThreadCallerPrincipalCallback();
|
||||
if (principalCallback == null)
|
||||
{
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
}
|
||||
if (principalCallback == null) { return Authentication.UNAUTHENTICATED; }
|
||||
Principal principal = principalCallback.getPrincipal();
|
||||
if (principal == null) {
|
||||
if (principal == null)
|
||||
{
|
||||
String principalName = principalCallback.getName();
|
||||
Set<Principal> principals = principalCallback.getSubject().getPrincipals();
|
||||
for (Principal p: principals)
|
||||
for (Principal p : principals)
|
||||
{
|
||||
if (p.getName().equals(principalName))
|
||||
{
|
||||
|
@ -136,10 +153,7 @@ public class JaspiAuthenticator implements Authenticator
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (principal == null)
|
||||
{
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
}
|
||||
if (principal == null) { return Authentication.UNAUTHENTICATED; }
|
||||
}
|
||||
GroupPrincipalCallback groupPrincipalCallback = _callbackHandler.getThreadGroupPrincipalCallback();
|
||||
String[] groups = groupPrincipalCallback == null ? null : groupPrincipalCallback.getGroups();
|
||||
|
@ -149,10 +163,10 @@ public class JaspiAuthenticator implements Authenticator
|
|||
}
|
||||
if (authStatus == AuthStatus.SEND_SUCCESS)
|
||||
{
|
||||
//we are processing a message in a secureResponse dialog.
|
||||
// we are processing a message in a secureResponse dialog.
|
||||
return Authentication.SEND_SUCCESS;
|
||||
}
|
||||
//should not happen
|
||||
// should not happen
|
||||
throw new NullPointerException("No AuthStatus returned");
|
||||
}
|
||||
catch (AuthException e)
|
||||
|
@ -166,13 +180,16 @@ public class JaspiAuthenticator implements Authenticator
|
|||
try
|
||||
{
|
||||
String authContextId = _authConfig.getAuthContextID(messageInfo);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties);
|
||||
// TODO authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
|
||||
AuthStatus status = authContext.secureResponse(messageInfo,_serviceSubject);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
|
||||
// TODO
|
||||
// authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
|
||||
AuthStatus status = authContext.secureResponse(messageInfo, _serviceSubject);
|
||||
return (AuthStatus.SEND_SUCCESS.equals(status));
|
||||
}
|
||||
catch (AuthException e)
|
||||
{
|
||||
System.err.println("Error in JaspiAuthenticator.secureResponse");
|
||||
e.printStackTrace();
|
||||
throw new ServerAuthException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,9 +98,13 @@ public class JaspiAuthenticatorFactory extends DefaultAuthenticatorFactory
|
|||
Subject serviceSubject=findServiceSubject(server);
|
||||
String serverName=findServerName(server,serviceSubject);
|
||||
|
||||
System.err.println("authconfigfactory="+authConfigFactory+" serviceSubject="+serviceSubject+" serverName="+serverName);
|
||||
|
||||
String appContext = serverName + " " + context.getContextPath();
|
||||
|
||||
System.err.println("appcontext="+appContext);
|
||||
AuthConfigProvider authConfigProvider = authConfigFactory.getConfigProvider(MESSAGE_LAYER,appContext,listener);
|
||||
System.err.println("authconfigProvider="+authConfigProvider);
|
||||
if (authConfigProvider != null)
|
||||
{
|
||||
ServletCallbackHandler servletCallbackHandler = new ServletCallbackHandler(loginService);
|
||||
|
|
|
@ -90,8 +90,9 @@ public class ServletCallbackHandler implements CallbackHandler
|
|||
|
||||
if (user!=null)
|
||||
{
|
||||
loginCallback.setUserPrincipal(user.getUserPrincipal());
|
||||
credentialValidationCallback.getSubject().getPrivateCredentials().add(loginCallback);
|
||||
credentialValidationCallback.setResult(true);
|
||||
|
||||
credentialValidationCallback.getSubject().getPrincipals().addAll(user.getSubject().getPrincipals());
|
||||
credentialValidationCallback.getSubject().getPrivateCredentials().add(user);
|
||||
}
|
||||
|
|
|
@ -90,12 +90,12 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext
|
|||
public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException
|
||||
{
|
||||
// servlets do not need secured responses
|
||||
return AuthStatus.SUCCESS;
|
||||
return AuthStatus.SEND_SUCCESS;
|
||||
}
|
||||
|
||||
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException
|
||||
{
|
||||
return AuthStatus.FAILURE;
|
||||
return AuthStatus.SEND_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,6 +131,7 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext
|
|||
if (credValidationCallback.getResult())
|
||||
{
|
||||
Set<LoginCallbackImpl> loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class);
|
||||
System.err.println("LoginCallbackImpls.isEmpty="+loginCallbacks.isEmpty());
|
||||
if (!loginCallbacks.isEmpty())
|
||||
{
|
||||
LoginCallbackImpl loginCallback = loginCallbacks.iterator().next();
|
||||
|
|
|
@ -36,7 +36,9 @@ import javax.servlet.http.HttpSessionBindingListener;
|
|||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.eclipse.jetty.util.security.Password;
|
||||
import org.eclipse.jetty.security.CrossContextPsuedoSession;
|
||||
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
|
||||
import org.eclipse.jetty.security.authentication.LoginCallbackImpl;
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -146,37 +148,50 @@ public class FormAuthModule extends BaseAuthModule
|
|||
@Override
|
||||
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException
|
||||
{
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
|
||||
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
|
||||
HttpSession session = request.getSession(isMandatory(messageInfo));
|
||||
String uri = request.getPathInfo();
|
||||
// not mandatory and not authenticated
|
||||
if (session == null || isLoginOrErrorPage(uri)) return AuthStatus.SUCCESS;
|
||||
String uri = request.getRequestURI();
|
||||
if (uri==null)
|
||||
uri=URIUtil.SLASH;
|
||||
|
||||
boolean mandatory = isMandatory(messageInfo);
|
||||
mandatory |= isJSecurityCheck(uri);
|
||||
HttpSession session = request.getSession(mandatory);
|
||||
|
||||
System.err.println("FormAuthModule.validateRequest(info,subject,serviceSubject) for uri="+uri+" mandatory="+mandatory+" isLoginOrError="+isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo())));
|
||||
|
||||
// not mandatory or its the login or login error page don't authenticate
|
||||
if (!mandatory || isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()))) return AuthStatus.SUCCESS;
|
||||
|
||||
try
|
||||
{
|
||||
// Handle a request for authentication.
|
||||
// TODO perhaps j_securitycheck can be uri suffix?
|
||||
if (uri.endsWith(__J_SECURITY_CHECK))
|
||||
if (isJSecurityCheck(uri))
|
||||
{
|
||||
|
||||
final String username = request.getParameter(__J_USERNAME);
|
||||
final String password = request.getParameter(__J_PASSWORD);
|
||||
System.err.println("Try login username="+username+" password="+password);
|
||||
boolean success = tryLogin(messageInfo, clientSubject, response, session, username, new Password(password));
|
||||
if (success)
|
||||
{
|
||||
// Redirect to original request
|
||||
String nuri = (String) session.getAttribute(__J_URI);
|
||||
// Redirect to original request
|
||||
String nuri=null;
|
||||
synchronized(session)
|
||||
{
|
||||
nuri = (String) session.getAttribute(__J_URI);
|
||||
}
|
||||
|
||||
if (nuri == null || nuri.length() == 0)
|
||||
{
|
||||
nuri = request.getContextPath();
|
||||
if (nuri.length() == 0) nuri = URIUtil.SLASH;
|
||||
if (nuri.length() == 0)
|
||||
nuri = URIUtil.SLASH;
|
||||
}
|
||||
session.removeAttribute(__J_URI); // Remove popped return
|
||||
// URI.
|
||||
response.setContentLength(0);
|
||||
|
||||
System.err.println("FormAuthModule succesful login, sending redirect to "+nuri);
|
||||
response.setContentLength(0);
|
||||
response.sendRedirect(response.encodeRedirectURL(nuri));
|
||||
|
||||
return AuthStatus.SEND_CONTINUE;
|
||||
}
|
||||
// not authenticated
|
||||
|
@ -194,95 +209,18 @@ public class FormAuthModule extends BaseAuthModule
|
|||
// that occur?
|
||||
return AuthStatus.SEND_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Check if the session is already authenticated.
|
||||
FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
|
||||
|
||||
if (form_cred != null)
|
||||
{
|
||||
System.err.println("Form cred: form.username="+form_cred._jUserName+" form.pwd="+new String(form_cred._jPassword));
|
||||
|
||||
//TODO: we would like the form auth module to be able to invoke the loginservice.validate() method to check the previously authed user
|
||||
|
||||
boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword)));
|
||||
if (success) { return AuthStatus.SUCCESS; }
|
||||
// CallbackHandler loginCallbackHandler = new
|
||||
// UserPasswordCallbackHandler(form_cred._jUserName,
|
||||
// form_cred._jPassword);
|
||||
// LoginResult loginResult = loginService.login(clientSubject,
|
||||
// loginCallbackHandler);
|
||||
// //TODO what should happen if !isMandatory but credentials
|
||||
// exist and are wrong?
|
||||
// if (loginResult.isSuccess())
|
||||
// {
|
||||
// callbackHandler.handle(new
|
||||
// Callback[]{loginResult.getCallerPrincipalCallback(),
|
||||
// loginResult.getGroupPrincipalCallback()});
|
||||
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
|
||||
// Constraint.__FORM_AUTH);
|
||||
//
|
||||
// form_cred = new FormCredential(form_cred._jUserName,
|
||||
// form_cred._jPassword,
|
||||
// loginResult.getCallerPrincipalCallback().getPrincipal());
|
||||
//
|
||||
// session.setAttribute(__J_AUTHENTICATED, form_cred);
|
||||
// if (ssoSource != null && ssoSource.fetch(request) == null)
|
||||
// {
|
||||
// UserInfo userInfo = new UserInfo(form_cred._jUserName,
|
||||
// form_cred._jPassword);
|
||||
// ssoSource.store(userInfo, response);
|
||||
// }
|
||||
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
|
||||
// Constraint.__FORM_AUTH);
|
||||
// return AuthStatus.SUCCESS;
|
||||
// }
|
||||
|
||||
// // We have a form credential. Has it been distributed?
|
||||
// if (form_cred._userPrincipal==null)
|
||||
// {
|
||||
// // This form_cred appears to have been distributed. Need to
|
||||
// reauth
|
||||
// form_cred.authenticate(realm, request);
|
||||
//
|
||||
// // Sign-on to SSO mechanism
|
||||
// if (form_cred._userPrincipal!=null && realm instanceof
|
||||
// SSORealm)
|
||||
// ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new
|
||||
// Password(form_cred._jPassword));
|
||||
//
|
||||
// }
|
||||
// else if (!realm.reauthenticate(form_cred._userPrincipal))
|
||||
// // Else check that it is still authenticated.
|
||||
// form_cred._userPrincipal=null;
|
||||
//
|
||||
// // If this credential is still authenticated
|
||||
// if (form_cred._userPrincipal!=null)
|
||||
// {
|
||||
// if(LOG.isDebugEnabled())LOG.debug("FORM Authenticated for
|
||||
// "+form_cred._userPrincipal.getName());
|
||||
// request.setAuthType(Constraint.__FORM_AUTH);
|
||||
// //jaspi
|
||||
// // request.setUserPrincipal(form_cred._userPrincipal);
|
||||
// return form_cred._userPrincipal;
|
||||
// }
|
||||
// else
|
||||
// session.setAttribute(__J_AUTHENTICATED,null);
|
||||
// }
|
||||
// else if (realm instanceof SSORealm)
|
||||
// {
|
||||
// // Try a single sign on.
|
||||
// Credential cred =
|
||||
// ((SSORealm)realm).getSingleSignOn(request,response);
|
||||
//
|
||||
// if (request.getUserPrincipal()!=null)
|
||||
// {
|
||||
// form_cred=new FormCredential();
|
||||
// form_cred._userPrincipal=request.getUserPrincipal();
|
||||
// form_cred._jUserName=form_cred._userPrincipal.getName();
|
||||
// if (cred!=null)
|
||||
// form_cred._jPassword=cred.toString();
|
||||
// if(LOG.isDebugEnabled())LOG.debug("SSO for
|
||||
// "+form_cred._userPrincipal);
|
||||
//
|
||||
// request.setAuthType(Constraint.__FORM_AUTH);
|
||||
// session.setAttribute(__J_AUTHENTICATED,form_cred);
|
||||
// return form_cred._userPrincipal;
|
||||
// }
|
||||
}
|
||||
else if (ssoSource != null)
|
||||
{
|
||||
|
@ -293,19 +231,25 @@ public class FormAuthModule extends BaseAuthModule
|
|||
if (success) { return AuthStatus.SUCCESS; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Don't authenticate authform or errorpage
|
||||
if (!isMandatory(messageInfo) || isLoginOrErrorPage(uri))
|
||||
// TODO verify this is correct action
|
||||
return AuthStatus.SUCCESS;
|
||||
// if we can't send challenge
|
||||
if (DeferredAuthentication.isDeferred(response))
|
||||
return AuthStatus.SUCCESS;
|
||||
|
||||
|
||||
// redirect to login page
|
||||
if (request.getQueryString() != null) uri += "?" + request.getQueryString();
|
||||
session.setAttribute(__J_URI, request.getScheme() + "://"
|
||||
+ request.getServerName()
|
||||
+ ":"
|
||||
+ request.getServerPort()
|
||||
+ URIUtil.addPaths(request.getContextPath(), uri));
|
||||
// redirect to login page
|
||||
StringBuffer buf = request.getRequestURL();
|
||||
if (request.getQueryString() != null)
|
||||
buf.append("?").append(request.getQueryString());
|
||||
|
||||
synchronized (session)
|
||||
{
|
||||
session.setAttribute(__J_URI, buf.toString());
|
||||
}
|
||||
|
||||
System.err.println("Redirecting to login page "+_formLoginPage+" and remembering juri="+buf.toString());
|
||||
response.setContentLength(0);
|
||||
response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), _formLoginPage)));
|
||||
return AuthStatus.SEND_CONTINUE;
|
||||
|
@ -320,6 +264,20 @@ public class FormAuthModule extends BaseAuthModule
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isJSecurityCheck(String uri)
|
||||
{
|
||||
int jsc = uri.indexOf(__J_SECURITY_CHECK);
|
||||
|
||||
if (jsc<0)
|
||||
return false;
|
||||
int e=jsc+__J_SECURITY_CHECK.length();
|
||||
if (e==uri.length())
|
||||
return true;
|
||||
char c = uri.charAt(e);
|
||||
return c==';'||c=='#'||c=='/'||c=='?';
|
||||
}
|
||||
|
||||
private boolean tryLogin(MessageInfo messageInfo, Subject clientSubject,
|
||||
HttpServletResponse response, HttpSession session,
|
||||
|
@ -330,10 +288,11 @@ public class FormAuthModule extends BaseAuthModule
|
|||
{
|
||||
char[] pwdChars = password.toString().toCharArray();
|
||||
Set<LoginCallbackImpl> loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class);
|
||||
System.err.println("FormAuthModule, LoginCallbackImpl.isEmpty="+loginCallbacks.isEmpty());
|
||||
if (!loginCallbacks.isEmpty())
|
||||
{
|
||||
LoginCallbackImpl loginCallback = loginCallbacks.iterator().next();
|
||||
FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal());
|
||||
FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject());
|
||||
|
||||
session.setAttribute(__J_AUTHENTICATED, form_cred);
|
||||
}
|
||||
|
@ -347,38 +306,11 @@ public class FormAuthModule extends BaseAuthModule
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
// LoginCallback loginCallback = new LoginCallback(clientSubject,
|
||||
// username, password);
|
||||
// loginService.login(loginCallback);
|
||||
// if (loginCallback.isSuccess())
|
||||
// {
|
||||
// CallerPrincipalCallback callerPrincipalCallback = new
|
||||
// CallerPrincipalCallback(clientSubject,
|
||||
// loginCallback.getUserPrincipal());
|
||||
// GroupPrincipalCallback groupPrincipalCallback = new
|
||||
// GroupPrincipalCallback(clientSubject,
|
||||
// loginCallback.getGroups().toArray(new
|
||||
// String[loginCallback.getGroups().size()]));
|
||||
// callbackHandler.handle(new Callback[] {callerPrincipalCallback,
|
||||
// groupPrincipalCallback});
|
||||
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
|
||||
// Constraint.__FORM_AUTH);
|
||||
// FormCredential form_cred = new FormCredential(username, password,
|
||||
// loginCallback.getUserPrincipal());
|
||||
//
|
||||
// session.setAttribute(__J_AUTHENTICATED, form_cred);
|
||||
// // Sign-on to SSO mechanism
|
||||
// if (ssoSource != null)
|
||||
// {
|
||||
// UserInfo userInfo = new UserInfo(username, password);
|
||||
// ssoSource.store(userInfo, response);
|
||||
// }
|
||||
// }
|
||||
// return loginCallback.isSuccess();
|
||||
}
|
||||
|
||||
public boolean isLoginOrErrorPage(String pathInContext)
|
||||
{
|
||||
System.err.println("ISLOGINORERRORPAGE? "+pathInContext+" error: "+_formErrorPath+" login:"+_formLoginPath);
|
||||
return pathInContext != null && (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
|
||||
}
|
||||
|
||||
|
@ -393,12 +325,15 @@ public class FormAuthModule extends BaseAuthModule
|
|||
char[] _jPassword;
|
||||
|
||||
transient Principal _userPrincipal;
|
||||
|
||||
transient Subject _subject;
|
||||
|
||||
private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal)
|
||||
private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal, Subject subject)
|
||||
{
|
||||
this._jUserName = _jUserName;
|
||||
this._jPassword = _jPassword;
|
||||
this._userPrincipal = _userPrincipal;
|
||||
this._subject = subject;
|
||||
}
|
||||
|
||||
public void valueBound(HttpSessionBindingEvent event)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot-jsp</artifactId>
|
||||
<name>Jetty :: OSGi :: Boot JSP</name>
|
||||
<description>Jetty OSGi Boot JSP bundle</description>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot-warurl</artifactId>
|
||||
<name>Jetty :: OSGi :: Boot :: Warurl</name>
|
||||
<description>Jetty OSGi Boot-Warurl bundle</description>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot</artifactId>
|
||||
<name>Jetty :: OSGi :: Boot</name>
|
||||
<description>Jetty OSGi Boot bundle</description>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-httpservice</artifactId>
|
||||
<name>Jetty :: OSGi :: HttpService</name>
|
||||
<description>Jetty OSGi HttpService bundle</description>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>test-jetty-osgi</artifactId>
|
||||
<name>Jetty :: OSGi :: Test</name>
|
||||
<description>Jetty OSGi Integration test</description>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<artifactId>jetty-project</artifactId>
|
||||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-policy</artifactId>
|
||||
<name>Jetty :: Policy Tool</name>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
@ -318,11 +318,13 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
if (!_loginServiceShared && _loginService instanceof LifeCycle)
|
||||
((LifeCycle)_loginService).start();
|
||||
|
||||
System.err.println("authenticator="+_authenticator+" authenticatorFactory="+_authenticatorFactory+" identityService="+_identityService);
|
||||
if (_authenticator==null && _authenticatorFactory!=null && _identityService!=null)
|
||||
{
|
||||
_authenticator=_authenticatorFactory.getAuthenticator(getServer(),ContextHandler.getCurrentContext(),this, _identityService, _loginService);
|
||||
if (_authenticator!=null)
|
||||
_authMethod=_authenticator.getAuthMethod();
|
||||
System.err.println("Called auth factory, authenticator="+_authenticator);
|
||||
}
|
||||
|
||||
if (_authenticator==null)
|
||||
|
@ -477,7 +479,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
deferred.setIdentityService(_identityService);
|
||||
deferred.setLoginService(_loginService);
|
||||
baseRequest.setAuthentication(authentication);
|
||||
|
||||
System.err.println("uri="+baseRequest.getUri()+" Auth is deferred");
|
||||
try
|
||||
{
|
||||
handler.handle(pathInContext, baseRequest, request, response);
|
||||
|
@ -487,7 +489,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
previousIdentity = deferred.getPreviousAssociation();
|
||||
deferred.setIdentityService(null);
|
||||
}
|
||||
|
||||
System.err.println("Securityhandler calling secureResponse, for Authentication.User");
|
||||
Authentication auth=baseRequest.getAuthentication();
|
||||
if (auth instanceof Authentication.User)
|
||||
{
|
||||
|
|
|
@ -169,7 +169,7 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
* @param response
|
||||
* @return true if this response is from a deferred call to {@link #authenticate(ServletRequest)}
|
||||
*/
|
||||
public boolean isDeferred(HttpServletResponse response)
|
||||
public static boolean isDeferred(HttpServletResponse response)
|
||||
{
|
||||
return response==__deferredResponse;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
static HttpServletResponse __deferredResponse = new HttpServletResponse()
|
||||
final static HttpServletResponse __deferredResponse = new HttpServletResponse()
|
||||
{
|
||||
public void addCookie(Cookie cookie)
|
||||
{
|
||||
|
|
|
@ -216,9 +216,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletRequest#isSuspended()
|
||||
*/
|
||||
public boolean isSuspending()
|
||||
{
|
||||
synchronized(this)
|
||||
|
|
|
@ -126,10 +126,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
}
|
||||
else if (_request.getAsyncContinuation().isAsyncStarted())
|
||||
{
|
||||
// The request is suspended, so even though progress has been made, break the while loop
|
||||
// The request is suspended, so even though progress has been made,
|
||||
// exit the while loop by setting progress to false
|
||||
LOG.debug("suspended {}",this);
|
||||
// TODO: breaking inside finally blocks is bad: rethink how we should exit from here
|
||||
break;
|
||||
progress=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,16 +139,19 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
setCurrentConnection(null);
|
||||
|
||||
// If we are not suspended
|
||||
if (!_request.isAsyncStarted())
|
||||
if (!_request.getAsyncContinuation().isAsyncStarted())
|
||||
{
|
||||
// return buffers
|
||||
_parser.returnBuffers();
|
||||
_generator.returnBuffers();
|
||||
|
||||
// resuming checking for idle
|
||||
}
|
||||
|
||||
// reenable idle checking unless request is suspended
|
||||
if(!_request.getAsyncContinuation().isAsyncStarted())
|
||||
{
|
||||
_asyncEndp.setCheckForIdle(true);
|
||||
}
|
||||
|
||||
|
||||
// Safety net to catch spinning
|
||||
if (some_progress)
|
||||
_total_no_progress=0;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -39,6 +39,9 @@ import static org.junit.matchers.JUnitMatchers.containsString;
|
|||
public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
||||
{
|
||||
protected static final int MAX_IDLE_TIME=250;
|
||||
private int sleepTime = MAX_IDLE_TIME + MAX_IDLE_TIME/5;
|
||||
private int minimumTestRuntime = MAX_IDLE_TIME-MAX_IDLE_TIME/5;
|
||||
private int maximumTestRuntime = MAX_IDLE_TIME*10;
|
||||
|
||||
static
|
||||
{
|
||||
|
@ -68,11 +71,11 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
long start = System.currentTimeMillis();
|
||||
IO.toString(is);
|
||||
|
||||
Thread.sleep(300);
|
||||
Thread.sleep(sleepTime);
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>200);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -101,11 +104,11 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
long start = System.currentTimeMillis();
|
||||
IO.toString(is);
|
||||
|
||||
Thread.sleep(300);
|
||||
Thread.sleep(sleepTime);
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>200);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -126,7 +129,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{}
|
||||
super.handle(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
@ -151,14 +154,14 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
// read the response
|
||||
String result=IO.toString(is);
|
||||
Assert.assertThat("OK",result,containsString("200 OK"));
|
||||
|
||||
|
||||
// check client reads EOF
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
// wait for idle timeout
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
try
|
||||
{
|
||||
|
@ -199,7 +202,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{}
|
||||
super.handle(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
@ -220,10 +223,10 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"\r\n").getBytes("utf-8"));
|
||||
os.write(contentB);
|
||||
os.flush();
|
||||
|
||||
|
||||
// Get the server side endpoint
|
||||
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
|
||||
|
||||
|
||||
// read the response
|
||||
IO.toString(is);
|
||||
|
||||
|
@ -232,7 +235,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
try
|
||||
{
|
||||
|
@ -251,7 +254,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{
|
||||
// expected
|
||||
}
|
||||
|
||||
|
||||
// check the server side is closed
|
||||
Assert.assertFalse(endp.isOpen());
|
||||
}
|
||||
|
@ -266,7 +269,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
InputStream is=client.getInputStream();
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
Thread.sleep(500);
|
||||
Thread.sleep(sleepTime);
|
||||
long start = System.currentTimeMillis();
|
||||
try
|
||||
{
|
||||
|
@ -281,7 +284,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -200,288 +200,12 @@ public class LocalAsyncContextTest
|
|||
return ((LocalConnector)_connector).getResponses(request);
|
||||
}
|
||||
|
||||
private static class SuspendHandler extends HandlerWrapper
|
||||
{
|
||||
private int _read;
|
||||
private long _suspendFor=-1;
|
||||
private long _resumeAfter=-1;
|
||||
private long _completeAfter=-1;
|
||||
private long _suspendFor2=-1;
|
||||
private long _resumeAfter2=-1;
|
||||
private long _completeAfter2=-1;
|
||||
|
||||
public SuspendHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public int getRead()
|
||||
{
|
||||
return _read;
|
||||
}
|
||||
|
||||
public void setRead(int read)
|
||||
{
|
||||
_read = read;
|
||||
}
|
||||
|
||||
public long getSuspendFor()
|
||||
{
|
||||
return _suspendFor;
|
||||
}
|
||||
|
||||
public void setSuspendFor(long suspendFor)
|
||||
{
|
||||
_suspendFor = suspendFor;
|
||||
}
|
||||
|
||||
public long getResumeAfter()
|
||||
{
|
||||
return _resumeAfter;
|
||||
}
|
||||
|
||||
public void setResumeAfter(long resumeAfter)
|
||||
{
|
||||
_resumeAfter = resumeAfter;
|
||||
}
|
||||
|
||||
public long getCompleteAfter()
|
||||
{
|
||||
return _completeAfter;
|
||||
}
|
||||
|
||||
public void setCompleteAfter(long completeAfter)
|
||||
{
|
||||
_completeAfter = completeAfter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the suspendFor2.
|
||||
* @return the suspendFor2
|
||||
*/
|
||||
public long getSuspendFor2()
|
||||
{
|
||||
return _suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the suspendFor2.
|
||||
* @param suspendFor2 the suspendFor2 to set
|
||||
*/
|
||||
public void setSuspendFor2(long suspendFor2)
|
||||
{
|
||||
_suspendFor2 = suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the resumeAfter2.
|
||||
* @return the resumeAfter2
|
||||
*/
|
||||
public long getResumeAfter2()
|
||||
{
|
||||
return _resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the resumeAfter2.
|
||||
* @param resumeAfter2 the resumeAfter2 to set
|
||||
*/
|
||||
public void setResumeAfter2(long resumeAfter2)
|
||||
{
|
||||
_resumeAfter2 = resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the completeAfter2.
|
||||
* @return the completeAfter2
|
||||
*/
|
||||
public long getCompleteAfter2()
|
||||
{
|
||||
return _completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the completeAfter2.
|
||||
* @param completeAfter2 the completeAfter2 to set
|
||||
*/
|
||||
public void setCompleteAfter2(long completeAfter2)
|
||||
{
|
||||
_completeAfter2 = completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
{
|
||||
if (_read>0)
|
||||
{
|
||||
byte[] buf=new byte[_read];
|
||||
request.getInputStream().read(buf);
|
||||
}
|
||||
else if (_read<0)
|
||||
{
|
||||
InputStream in = request.getInputStream();
|
||||
int b=in.read();
|
||||
while(b!=-1)
|
||||
b=in.read();
|
||||
}
|
||||
|
||||
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC");
|
||||
asyncContext.addListener(__asyncListener);
|
||||
asyncContext.addListener(__asyncListener1);
|
||||
if (_suspendFor>0)
|
||||
asyncContext.setTimeout(_suspendFor);
|
||||
|
||||
|
||||
if (_completeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter);
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter);
|
||||
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request.getAttribute("TIMEOUT")!=null)
|
||||
response.getOutputStream().println("TIMEOUT");
|
||||
else
|
||||
response.getOutputStream().println("DISPATCHED");
|
||||
|
||||
if (_suspendFor2>=0)
|
||||
{
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC2");
|
||||
if (_suspendFor2>0)
|
||||
asyncContext.setTimeout(_suspendFor2);
|
||||
_suspendFor2=-1;
|
||||
|
||||
if (_completeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter2);
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter2==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter2);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter2==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AtomicInteger __completed = new AtomicInteger();
|
||||
static AtomicInteger __completed1 = new AtomicInteger();
|
||||
|
||||
private static AsyncListener __asyncListener = new AsyncListener()
|
||||
static AsyncListener __asyncListener = new AsyncListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
|
@ -512,7 +236,7 @@ public class LocalAsyncContextTest
|
|||
|
||||
};
|
||||
|
||||
private static AsyncListener __asyncListener1 = new AsyncListener()
|
||||
static AsyncListener __asyncListener1 = new AsyncListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,6 +40,7 @@ import junit.framework.Assert;
|
|||
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -78,7 +79,7 @@ public class RequestTest
|
|||
_server.stop();
|
||||
_server.join();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParamExtraction() throws Exception
|
||||
{
|
||||
|
@ -101,27 +102,27 @@ public class RequestTest
|
|||
System.err.println(map);
|
||||
assertFalse(map == null);
|
||||
assertTrue(map.isEmpty());
|
||||
|
||||
|
||||
Enumeration names = request.getParameterNames();
|
||||
assertFalse(names.hasMoreElements());
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Send a request with query string with illegal hex code to cause
|
||||
//an exception parsing the params
|
||||
String request="GET /?param=%ZZaaa HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: text/html;charset=utf8\n"+
|
||||
"\n";
|
||||
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBadUtf8ParamExtraction() throws Exception
|
||||
{
|
||||
|
@ -133,20 +134,40 @@ public class RequestTest
|
|||
return value.startsWith("aaa") && value.endsWith("bb");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Send a request with query string with illegal hex code to cause
|
||||
//an exception parsing the params
|
||||
String request="GET /?param=aaa%E7bbb HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: text/html;charset=utf8\n"+
|
||||
"\n";
|
||||
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testInvalidHostHeader() throws Exception
|
||||
{
|
||||
// Use a contextHandler with vhosts to force call to Request.getServerName()
|
||||
ContextHandler handler = new ContextHandler();
|
||||
handler.addVirtualHosts(new String[1]);
|
||||
_server.stop();
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
|
||||
// Request with illegal Host header
|
||||
String request="GET / HTTP/1.1\r\n"+
|
||||
"Host: whatever.com:\r\n"+
|
||||
"Content-Type: text/html;charset=utf8\n"+
|
||||
"\n";
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue("400 Bad Request response expected",responses.startsWith("HTTP/1.1 400"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testContentTypeEncoding() throws Exception
|
||||
{
|
||||
|
@ -196,7 +217,7 @@ public class RequestTest
|
|||
assertTrue(results.get(i++).startsWith("text/html"));
|
||||
assertEquals(" x=z; ",results.get(i++));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHostPort() throws Exception
|
||||
{
|
||||
|
@ -369,7 +390,7 @@ public class RequestTest
|
|||
Reader reader=request.getReader();
|
||||
String in = IO.toString(reader);
|
||||
String param = request.getParameter("param");
|
||||
|
||||
|
||||
byte[] b=("read='"+in+"' param="+param+"\n").getBytes(StringUtil.__UTF8);
|
||||
response.setContentLength(b.length);
|
||||
response.getOutputStream().write(b);
|
||||
|
@ -389,11 +410,11 @@ public class RequestTest
|
|||
"param=wrong\r\n";
|
||||
|
||||
String responses = _connector.getResponses(request);
|
||||
|
||||
|
||||
assertTrue(responses.indexOf("read='param=wrong' param=right")>0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPartialInput() throws Exception
|
||||
{
|
||||
|
@ -754,7 +775,7 @@ public class RequestTest
|
|||
{
|
||||
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize",-1);
|
||||
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormKeys",1000);
|
||||
|
||||
|
||||
// This file is not distributed - as it is dangerous
|
||||
File evil_keys = new File("/tmp/keys_mapping_to_zero_2m");
|
||||
if (!evil_keys.exists())
|
||||
|
@ -762,10 +783,10 @@ public class RequestTest
|
|||
Log.info("testHashDOS skipped");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BufferedReader in = new BufferedReader(new FileReader(evil_keys));
|
||||
StringBuilder buf = new StringBuilder(4000000);
|
||||
|
||||
|
||||
String key=null;
|
||||
buf.append("a=b");
|
||||
while((key=in.readLine())!=null)
|
||||
|
@ -773,7 +794,7 @@ public class RequestTest
|
|||
buf.append("&").append(key).append("=").append("x");
|
||||
}
|
||||
buf.append("&c=d");
|
||||
|
||||
|
||||
_handler._checker = new RequestTester()
|
||||
{
|
||||
public boolean check(HttpServletRequest request,HttpServletResponse response)
|
||||
|
@ -789,15 +810,15 @@ public class RequestTest
|
|||
"Connection: close\r\n"+
|
||||
"\r\n"+
|
||||
buf;
|
||||
|
||||
|
||||
long start=System.currentTimeMillis();
|
||||
String response = _connector.getResponses(request);
|
||||
assertTrue(response.contains("200 OK"));
|
||||
long now=System.currentTimeMillis();
|
||||
assertTrue((now-start)<5000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
interface RequestTester
|
||||
{
|
||||
boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException;
|
||||
|
@ -814,12 +835,12 @@ public class RequestTest
|
|||
|
||||
if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
|
||||
_content=IO.toString(request.getInputStream());
|
||||
|
||||
|
||||
if (_checker!=null && _checker.check(request,response))
|
||||
response.setStatus(200);
|
||||
else
|
||||
response.sendError(500);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,17 +13,96 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
public static void init() throws Exception
|
||||
{
|
||||
SelectChannelConnector connector = new SelectChannelConnector();
|
||||
connector.setMaxIdleTime(MAX_IDLE_TIME); //250 msec max idle
|
||||
connector.setMaxIdleTime(MAX_IDLE_TIME); // 250 msec max idle
|
||||
startServer(connector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterSuspend() throws Exception
|
||||
{
|
||||
SuspendHandler _handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(_handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setResumeAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("DISPATCHED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterTimeout() throws Exception
|
||||
{
|
||||
SuspendHandler _handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(_handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(50);
|
||||
assertTrue(process(null).toUpperCase().contains("TIMEOUT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterComplete() throws Exception
|
||||
{
|
||||
SuspendHandler _handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(_handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setCompleteAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("COMPLETED"));
|
||||
}
|
||||
|
||||
private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException
|
||||
{
|
||||
String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n";
|
||||
|
||||
if (content == null)
|
||||
request += "\r\n";
|
||||
else
|
||||
request += "Content-Length: " + content.length() + "\r\n" + "\r\n" + content;
|
||||
return getResponse(request);
|
||||
}
|
||||
|
||||
private String getResponse(String request) throws UnsupportedEncodingException, IOException, InterruptedException
|
||||
{
|
||||
SelectChannelConnector connector = (SelectChannelConnector)_connector;
|
||||
Socket socket = new Socket((String)null,connector.getLocalPort());
|
||||
socket.getOutputStream().write(request.getBytes("UTF-8"));
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
String response = IO.toString(inputStream);
|
||||
Thread.sleep(500);
|
||||
assertEquals("Socket should be closed and return -1 on reading",-1,socket.getInputStream().read());
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
|
||||
class SuspendHandler extends HandlerWrapper
|
||||
{
|
||||
private int _read;
|
||||
private long _suspendFor=-1;
|
||||
private long _resumeAfter=-1;
|
||||
private long _completeAfter=-1;
|
||||
private long _suspendFor2=-1;
|
||||
private long _resumeAfter2=-1;
|
||||
private long _completeAfter2=-1;
|
||||
|
||||
public SuspendHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public int getRead()
|
||||
{
|
||||
return _read;
|
||||
}
|
||||
|
||||
public void setRead(int read)
|
||||
{
|
||||
_read = read;
|
||||
}
|
||||
|
||||
public long getSuspendFor()
|
||||
{
|
||||
return _suspendFor;
|
||||
}
|
||||
|
||||
public void setSuspendFor(long suspendFor)
|
||||
{
|
||||
_suspendFor = suspendFor;
|
||||
}
|
||||
|
||||
public long getResumeAfter()
|
||||
{
|
||||
return _resumeAfter;
|
||||
}
|
||||
|
||||
public void setResumeAfter(long resumeAfter)
|
||||
{
|
||||
_resumeAfter = resumeAfter;
|
||||
}
|
||||
|
||||
public long getCompleteAfter()
|
||||
{
|
||||
return _completeAfter;
|
||||
}
|
||||
|
||||
public void setCompleteAfter(long completeAfter)
|
||||
{
|
||||
_completeAfter = completeAfter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the suspendFor2.
|
||||
* @return the suspendFor2
|
||||
*/
|
||||
public long getSuspendFor2()
|
||||
{
|
||||
return _suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the suspendFor2.
|
||||
* @param suspendFor2 the suspendFor2 to set
|
||||
*/
|
||||
public void setSuspendFor2(long suspendFor2)
|
||||
{
|
||||
_suspendFor2 = suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the resumeAfter2.
|
||||
* @return the resumeAfter2
|
||||
*/
|
||||
public long getResumeAfter2()
|
||||
{
|
||||
return _resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the resumeAfter2.
|
||||
* @param resumeAfter2 the resumeAfter2 to set
|
||||
*/
|
||||
public void setResumeAfter2(long resumeAfter2)
|
||||
{
|
||||
_resumeAfter2 = resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the completeAfter2.
|
||||
* @return the completeAfter2
|
||||
*/
|
||||
public long getCompleteAfter2()
|
||||
{
|
||||
return _completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the completeAfter2.
|
||||
* @param completeAfter2 the completeAfter2 to set
|
||||
*/
|
||||
public void setCompleteAfter2(long completeAfter2)
|
||||
{
|
||||
_completeAfter2 = completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
{
|
||||
if (_read>0)
|
||||
{
|
||||
byte[] buf=new byte[_read];
|
||||
request.getInputStream().read(buf);
|
||||
}
|
||||
else if (_read<0)
|
||||
{
|
||||
InputStream in = request.getInputStream();
|
||||
int b=in.read();
|
||||
while(b!=-1)
|
||||
b=in.read();
|
||||
}
|
||||
|
||||
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC");
|
||||
asyncContext.addListener(LocalAsyncContextTest.__asyncListener);
|
||||
asyncContext.addListener(LocalAsyncContextTest.__asyncListener1);
|
||||
if (_suspendFor>0)
|
||||
asyncContext.setTimeout(_suspendFor);
|
||||
|
||||
|
||||
if (_completeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter);
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter);
|
||||
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request.getAttribute("TIMEOUT")!=null)
|
||||
response.getOutputStream().println("TIMEOUT");
|
||||
else
|
||||
response.getOutputStream().println("DISPATCHED");
|
||||
|
||||
if (_suspendFor2>=0)
|
||||
{
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC2");
|
||||
if (_suspendFor2>0)
|
||||
asyncContext.setTimeout(_suspendFor2);
|
||||
_suspendFor2=-1;
|
||||
|
||||
if (_completeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter2);
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter2==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter2);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter2==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -57,7 +57,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|||
|
||||
/**
|
||||
* Asynchronous Proxy Servlet.
|
||||
*
|
||||
*
|
||||
* Forward requests to another server either as a standard web proxy (as defined by RFC2616) or as a transparent proxy.
|
||||
* <p>
|
||||
* This servlet needs the jetty-util and jetty-client classes to be available to the web application.
|
||||
|
@ -75,17 +75,15 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|||
* <li>requestBufferSize - the size of the request buffer (d. 12,288)
|
||||
* <li>responseHeaderSize - the size of the response header buffer (d. 6,144)
|
||||
* <li>responseBufferSize - the size of the response buffer (d. 32,768)
|
||||
* <li>HostHeader - Force the host header to a particular value
|
||||
* <li>HostHeader - Force the host header to a particular value
|
||||
* <li>whiteList - comma-separated list of allowed proxy destinations
|
||||
* <li>blackList - comma-separated list of forbidden proxy destinations
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* @see org.eclipse.jetty.server.handler.ConnectHandler
|
||||
*/
|
||||
public class ProxyServlet implements Servlet
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ProxyServlet.class);
|
||||
|
||||
protected Logger _log;
|
||||
protected HttpClient _client;
|
||||
protected String _hostHeader;
|
||||
|
@ -111,22 +109,22 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
|
||||
*/
|
||||
public void init(ServletConfig config) throws ServletException
|
||||
{
|
||||
_config = config;
|
||||
_context = config.getServletContext();
|
||||
|
||||
|
||||
_hostHeader = config.getInitParameter("HostHeader");
|
||||
|
||||
try
|
||||
{
|
||||
_log = createLogger(config);
|
||||
_log = createLogger(config);
|
||||
|
||||
_client = createHttpClient(config);
|
||||
|
||||
|
||||
if (_context != null)
|
||||
{
|
||||
_context.setAttribute(config.getServletName() + ".Logger",_log);
|
||||
|
@ -162,12 +160,12 @@ public class ProxyServlet implements Servlet
|
|||
_log.debug(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create and return a logger based on the ServletConfig for use in the
|
||||
* Create and return a logger based on the ServletConfig for use in the
|
||||
* proxy servlet
|
||||
*
|
||||
*
|
||||
* @param config
|
||||
* @return Logger
|
||||
*/
|
||||
|
@ -175,24 +173,24 @@ public class ProxyServlet implements Servlet
|
|||
{
|
||||
return Log.getLogger("org.eclipse.jetty.servlets." + config.getServletName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create and return an HttpClient based on ServletConfig
|
||||
*
|
||||
* By default this implementation will create an instance of the
|
||||
*
|
||||
* By default this implementation will create an instance of the
|
||||
* HttpClient for use by this proxy servlet.
|
||||
*
|
||||
* @param config
|
||||
* @return HttpClient
|
||||
*
|
||||
* @param config
|
||||
* @return HttpClient
|
||||
* @throws Exception
|
||||
*/
|
||||
protected HttpClient createHttpClient(ServletConfig config) throws Exception
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
|
||||
|
||||
|
||||
String t = config.getInitParameter("maxThreads");
|
||||
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
client.setThreadPool(new QueuedThreadPool(Integer.parseInt(t)));
|
||||
|
@ -201,67 +199,67 @@ public class ProxyServlet implements Servlet
|
|||
{
|
||||
client.setThreadPool(new QueuedThreadPool());
|
||||
}
|
||||
|
||||
((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName());
|
||||
|
||||
((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName());
|
||||
|
||||
t = config.getInitParameter("maxConnections");
|
||||
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
client.setMaxConnectionsPerAddress(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("timeout");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setTimeout(Long.parseLong(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("idleTimeout");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setIdleTimeout(Long.parseLong(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("requestHeaderSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setRequestHeaderSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("requestBufferSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setRequestBufferSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("responseHeaderSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setResponseHeaderSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("responseBufferSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setResponseBufferSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
client.start();
|
||||
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Helper function to process a parameter value containing a list of new entries and initialize the specified host map.
|
||||
*
|
||||
*
|
||||
* @param list
|
||||
* comma-separated list of new entries
|
||||
* @param hostMap
|
||||
|
@ -301,7 +299,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Check the request hostname and path against white- and blacklist.
|
||||
*
|
||||
*
|
||||
* @param host
|
||||
* hostname to check
|
||||
* @param path
|
||||
|
@ -353,7 +351,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#getServletConfig()
|
||||
*/
|
||||
public ServletConfig getServletConfig()
|
||||
|
@ -364,7 +362,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get the hostHeader.
|
||||
*
|
||||
*
|
||||
* @return the hostHeader
|
||||
*/
|
||||
public String getHostHeader()
|
||||
|
@ -375,7 +373,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the hostHeader.
|
||||
*
|
||||
*
|
||||
* @param hostHeader
|
||||
* the hostHeader to set
|
||||
*/
|
||||
|
@ -387,7 +385,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
|
||||
*/
|
||||
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
|
||||
|
@ -412,7 +410,7 @@ public class ProxyServlet implements Servlet
|
|||
response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT); // Need better test that isInitial
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
String uri = request.getRequestURI();
|
||||
if (request.getQueryString() != null)
|
||||
uri += "?" + request.getQueryString();
|
||||
|
@ -430,14 +428,17 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
HttpExchange exchange = new HttpExchange()
|
||||
{
|
||||
@Override
|
||||
protected void onRequestCommitted() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRequestComplete() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseComplete() throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -445,6 +446,7 @@ public class ProxyServlet implements Servlet
|
|||
continuation.complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseContent(Buffer content) throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -452,10 +454,12 @@ public class ProxyServlet implements Servlet
|
|||
content.writeTo(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseHeaderComplete() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -467,6 +471,7 @@ public class ProxyServlet implements Servlet
|
|||
response.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
String s = name.toString().toLowerCase();
|
||||
|
@ -481,11 +486,12 @@ public class ProxyServlet implements Servlet
|
|||
_log.debug(debug + " " + name + "! " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConnectionFailed(Throwable ex)
|
||||
{
|
||||
handleOnConnectionFailed(ex,request,response);
|
||||
|
||||
// it is possible this might trigger before the
|
||||
|
||||
// it is possible this might trigger before the
|
||||
// continuation.suspend()
|
||||
if (!continuation.isInitial())
|
||||
{
|
||||
|
@ -493,16 +499,17 @@ public class ProxyServlet implements Servlet
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Throwable ex)
|
||||
{
|
||||
if (ex instanceof EofException)
|
||||
{
|
||||
LOG.ignore(ex);
|
||||
_log.ignore(ex);
|
||||
return;
|
||||
}
|
||||
handleOnException(ex,request,response);
|
||||
|
||||
// it is possible this might trigger before the
|
||||
|
||||
// it is possible this might trigger before the
|
||||
// continuation.suspend()
|
||||
if (!continuation.isInitial())
|
||||
{
|
||||
|
@ -510,6 +517,7 @@ public class ProxyServlet implements Servlet
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExpire()
|
||||
{
|
||||
handleOnExpire(request,response);
|
||||
|
@ -597,14 +605,14 @@ public class ProxyServlet implements Servlet
|
|||
if (hasContent)
|
||||
exchange.setRequestContentSource(in);
|
||||
|
||||
customizeExchange(exchange, request);
|
||||
|
||||
customizeExchange(exchange, request);
|
||||
|
||||
/*
|
||||
* we need to set the timeout on the continuation to take into
|
||||
* account the timeout of the HttpClient and the HttpExchange
|
||||
*/
|
||||
long ctimeout = (_client.getTimeout() > exchange.getTimeout()) ? _client.getTimeout() : exchange.getTimeout();
|
||||
|
||||
|
||||
// continuation fudge factor of 1000, underlying components
|
||||
// should fail/expire first from exchange
|
||||
if ( ctimeout == 0 )
|
||||
|
@ -612,12 +620,12 @@ public class ProxyServlet implements Servlet
|
|||
continuation.setTimeout(0); // ideally never times out
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
continuation.setTimeout(ctimeout + 1000);
|
||||
}
|
||||
|
||||
|
||||
customizeContinuation(continuation);
|
||||
|
||||
|
||||
continuation.suspend(response);
|
||||
_client.send(exchange);
|
||||
|
||||
|
@ -678,7 +686,7 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#getServletInfo()
|
||||
*/
|
||||
public String getServletInfo()
|
||||
|
@ -689,7 +697,7 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
/**
|
||||
* Extension point for subclasses to customize an exchange. Useful for setting timeouts etc. The default implementation does nothing.
|
||||
*
|
||||
*
|
||||
* @param exchange
|
||||
* @param request
|
||||
*/
|
||||
|
@ -701,7 +709,7 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for subclasses to customize the Continuation after it's initial creation in the service method. Useful for setting timeouts etc. The
|
||||
* default implementation does nothing.
|
||||
*
|
||||
*
|
||||
* @param continuation
|
||||
*/
|
||||
protected void customizeContinuation(Continuation continuation)
|
||||
|
@ -712,7 +720,7 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for custom handling of an HttpExchange's onConnectionFailed method. The default implementation delegates to
|
||||
* {@link #handleOnException(Throwable, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
|
||||
*
|
||||
*
|
||||
* @param ex
|
||||
* @param request
|
||||
* @param response
|
||||
|
@ -725,15 +733,15 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for custom handling of an HttpExchange's onException method. The default implementation sets the response status to
|
||||
* HttpServletResponse.SC_INTERNAL_SERVER_ERROR (503)
|
||||
*
|
||||
*
|
||||
* @param ex
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
protected void handleOnException(Throwable ex, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
LOG.warn(ex.toString());
|
||||
LOG.debug(ex);
|
||||
_log.warn(ex.toString());
|
||||
_log.debug(ex);
|
||||
if (!response.isCommitted())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
|
@ -743,7 +751,7 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for custom handling of an HttpExchange's onExpire method. The default implementation sets the response status to
|
||||
* HttpServletResponse.SC_GATEWAY_TIMEOUT (504)
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
|
@ -757,7 +765,7 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
/**
|
||||
* Transparent Proxy.
|
||||
*
|
||||
*
|
||||
* This convenience extension to ProxyServlet configures the servlet as a transparent proxy. The servlet is configured with init parameters:
|
||||
* <ul>
|
||||
* <li>ProxyTo - a URI like http://host:80/context to which the request is proxied.
|
||||
|
@ -765,7 +773,7 @@ public class ProxyServlet implements Servlet
|
|||
* </ul>
|
||||
* For example, if a request was received at /foo/bar and the ProxyTo was http://host:80/context and the Prefix was /foo, then the request would be proxied
|
||||
* to http://host:80/context/bar
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static class Transparent extends ProxyServlet
|
||||
{
|
||||
|
|
|
@ -123,30 +123,35 @@ public class Main
|
|||
// if no non-option inis, add the start.ini and start.d
|
||||
if (!ini)
|
||||
{
|
||||
List<String> ini_args=new ArrayList<String>();
|
||||
File start_ini = new File(_jettyHome,"start.ini");
|
||||
if (start_ini.exists())
|
||||
ini_args.addAll(loadStartIni(start_ini));
|
||||
|
||||
File start_d = new File(_jettyHome,"start.d");
|
||||
if (start_d.isDirectory())
|
||||
{
|
||||
File[] inis = start_d.listFiles(new FilenameFilter()
|
||||
{
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
return name.toLowerCase().endsWith(".ini");
|
||||
}
|
||||
});
|
||||
Arrays.sort(inis);
|
||||
for (File i : inis)
|
||||
ini_args.addAll(loadStartIni(i));
|
||||
}
|
||||
arguments.addAll(0,ini_args);
|
||||
arguments.addAll(0,parseStartIniFiles());
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
List<String> parseStartIniFiles()
|
||||
{
|
||||
List<String> ini_args=new ArrayList<String>();
|
||||
File start_ini = new File(_jettyHome,"start.ini");
|
||||
if (start_ini.exists())
|
||||
ini_args.addAll(loadStartIni(start_ini));
|
||||
|
||||
File start_d = new File(_jettyHome,"start.d");
|
||||
if (start_d.isDirectory())
|
||||
{
|
||||
File[] inis = start_d.listFiles(new FilenameFilter()
|
||||
{
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
return name.toLowerCase().endsWith(".ini");
|
||||
}
|
||||
});
|
||||
Arrays.sort(inis);
|
||||
for (File i : inis)
|
||||
ini_args.addAll(loadStartIni(i));
|
||||
}
|
||||
return ini_args;
|
||||
}
|
||||
|
||||
public List<String> processCommandLine(List<String> arguments) throws Exception
|
||||
{
|
||||
|
@ -1075,7 +1080,7 @@ public class Main
|
|||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// usageExit(e,ERR_UNKNOWN);
|
||||
usageExit(e,ERR_UNKNOWN);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ Command Line Options:
|
|||
when the start.ini includes -X or -D arguments.
|
||||
|
||||
--exec Run the generated command line (see --dry-run) in
|
||||
a sub processes. This can be used when start.ini
|
||||
a sub process. This can be used when start.ini
|
||||
contains -X or -D arguments, but creates an extra
|
||||
JVM instance.
|
||||
|
||||
|
@ -36,8 +36,10 @@ Command Line Options:
|
|||
|
||||
--ini=<file> Load command line arguments from a file. If
|
||||
no --ini options are specified, then the
|
||||
start.ini file will be read if it exists.
|
||||
A --ini option with no file indicates that
|
||||
start.ini file will be read if it exists in
|
||||
jetty.home. If specified jetty.home/start.ini
|
||||
and additional .ini files in jetty.home/start.d/
|
||||
will NOT be read. A --ini option with no file indicates that
|
||||
start.ini should not be read.
|
||||
|
||||
--pre=<file> Specify a configuration file that is to be processed
|
||||
|
@ -116,10 +118,10 @@ Available Configurations:
|
|||
Defaults:
|
||||
A start.ini file may be used to specify default arguments to start.jar,
|
||||
which are used if no command line arguments are provided and override
|
||||
the defaults in the start.config file. If the directory start.d exists,
|
||||
then multiple *.ini files will be read from that directory in alphabetical
|
||||
order. If --ini options are provided on the command line, then start.ini
|
||||
and start.d will not be read.
|
||||
the defaults in the start.config file. If the directory jetty.home/start.d
|
||||
exists, then multiple *.ini files will be read from that directory in
|
||||
alphabetical order. If --ini options are provided on the command line,
|
||||
then start.ini and start.d will NOT be read.
|
||||
|
||||
The current start.ini arguments are:
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ package org.eclipse.jetty.start;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -39,15 +39,18 @@ public class MainTest
|
|||
|
||||
/**
|
||||
* Test method for {@link org.eclipse.jetty.start.StartIniParser#loadStartIni(java.lang.String)}.
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testLoadStartIni()
|
||||
public void testLoadStartIni() throws IOException
|
||||
{
|
||||
URL startIni = this.getClass().getResource("/jetty.home/start.ini");
|
||||
String startIniFileName = startIni.getFile();
|
||||
List<String> args = Main.loadStartIni(new File(startIniFileName));
|
||||
assertEquals("Expected 5 uncommented lines in start.ini",5,args.size());
|
||||
URL startIni = this.getClass().getResource("/jetty.home/");
|
||||
System.setProperty("jetty.home",startIni.getFile());
|
||||
Main main = new Main();
|
||||
List<String> args = main.parseStartIniFiles();
|
||||
assertEquals("Expected 5 uncommented lines in start.ini",9,args.size());
|
||||
assertEquals("First uncommented line in start.ini doesn't match expected result","OPTIONS=Server,jsp,resources,websocket,ext",args.get(0));
|
||||
assertEquals("Last uncommented line in start.ini doesn't match expected result","etc/jetty-testrealm.xml",args.get(8));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -102,7 +102,10 @@ public class Log
|
|||
while (systemKeyEnum.hasMoreElements())
|
||||
{
|
||||
String key = systemKeyEnum.nextElement();
|
||||
__props.setProperty(key,System.getProperty(key));
|
||||
String val = System.getProperty(key);
|
||||
//protect against application code insertion of non-String values (returned as null)
|
||||
if (val != null)
|
||||
__props.setProperty(key,val);
|
||||
}
|
||||
|
||||
/* Now use the configuration properties to configure the Log statics
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.eclipse.jetty.io.nio.SslConnection;
|
|||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.util.component.AggregateLifeCycle;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
|
@ -67,6 +68,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
private final Queue<WebSocketConnection> connections = new ConcurrentLinkedQueue<WebSocketConnection>();
|
||||
private final SslContextFactory _sslContextFactory = new SslContextFactory();
|
||||
private final ThreadPool _threadPool;
|
||||
private final boolean _shutdownThreadPool;
|
||||
private final WebSocketClientSelector _selector;
|
||||
private MaskGen _maskGen;
|
||||
private WebSocketBuffers _buffers;
|
||||
|
@ -77,7 +79,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
*/
|
||||
public WebSocketClientFactory()
|
||||
{
|
||||
this(new QueuedThreadPool());
|
||||
this(null);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -114,14 +116,27 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
*/
|
||||
public WebSocketClientFactory(ThreadPool threadPool, MaskGen maskGen, int bufferSize)
|
||||
{
|
||||
_threadPool = threadPool;
|
||||
addBean(threadPool);
|
||||
if (threadPool == null)
|
||||
{
|
||||
_threadPool = new QueuedThreadPool();
|
||||
addBean(_threadPool);
|
||||
_shutdownThreadPool = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_threadPool = threadPool;
|
||||
_shutdownThreadPool = false;
|
||||
}
|
||||
|
||||
_buffers = new WebSocketBuffers(bufferSize);
|
||||
addBean(_buffers);
|
||||
|
||||
_maskGen = maskGen;
|
||||
addBean(_maskGen);
|
||||
|
||||
_selector = new WebSocketClientSelector();
|
||||
addBean(_selector);
|
||||
|
||||
addBean(_sslContextFactory);
|
||||
}
|
||||
|
||||
|
@ -208,6 +223,9 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
protected void doStop() throws Exception
|
||||
{
|
||||
closeConnections();
|
||||
super.doStop();
|
||||
if (_shutdownThreadPool && _threadPool instanceof LifeCycle)
|
||||
((LifeCycle)_threadPool).stop();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -121,7 +121,7 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
|
|||
|
||||
private final static byte[] MAGIC;
|
||||
private final List<Extension> _extensions;
|
||||
private final WebSocketParserD13 _parser;
|
||||
private final WebSocketParserRFC6455 _parser;
|
||||
private final WebSocketGeneratorRFC6455 _generator;
|
||||
private final WebSocketGenerator _outbound;
|
||||
private final WebSocket _webSocket;
|
||||
|
@ -197,7 +197,7 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
|
|||
_outbound=(_extensions==null||_extensions.size()==0)?_generator:extensions.get(extensions.size()-1);
|
||||
WebSocketParser.FrameHandler inbound = (_extensions == null || _extensions.size() == 0) ? frameHandler : extensions.get(0);
|
||||
|
||||
_parser = new WebSocketParserD13(buffers, endpoint, inbound,maskgen==null);
|
||||
_parser = new WebSocketParserRFC6455(buffers, endpoint, inbound,maskgen==null);
|
||||
|
||||
_protocol=protocol;
|
||||
|
||||
|
@ -642,7 +642,13 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.getClass().getSimpleName()+"D13@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort();
|
||||
return String.format("%s@%x l(%s:%d)<->r(%s:%d)",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_endp.getLocalAddr(),
|
||||
_endp.getLocalPort(),
|
||||
_endp.getRemoteAddr(),
|
||||
_endp.getRemotePort());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -973,6 +979,6 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
|
||||
return String.format("%s p=%s g=%s", getClass().getSimpleName(), _parser, _generator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,9 +43,9 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* Parser the WebSocket protocol.
|
||||
*
|
||||
*/
|
||||
public class WebSocketParserD13 implements WebSocketParser
|
||||
public class WebSocketParserRFC6455 implements WebSocketParser
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketParserD13.class);
|
||||
private static final Logger LOG = Log.getLogger(WebSocketParserRFC6455.class);
|
||||
|
||||
public enum State {
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class WebSocketParserD13 implements WebSocketParser
|
|||
* @param handler the handler to notify when a parse event occurs
|
||||
* @param shouldBeMasked whether masking should be handled
|
||||
*/
|
||||
public WebSocketParserD13(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
|
||||
public WebSocketParserRFC6455(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
|
||||
{
|
||||
_buffers=buffers;
|
||||
_endp=endp;
|
|
@ -15,8 +15,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -24,7 +22,6 @@ import org.eclipse.jetty.server.Connector;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.eclipse.jetty.websocket.helper.CaptureSocket;
|
||||
import org.eclipse.jetty.websocket.helper.SafariD00;
|
||||
import org.eclipse.jetty.websocket.helper.WebSocketCaptureServlet;
|
||||
|
@ -32,9 +29,11 @@ import org.junit.After;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
public class SafariWebsocketDraft0Test
|
||||
{
|
||||
private Server server;
|
||||
|
@ -76,7 +75,7 @@ public class SafariWebsocketDraft0Test
|
|||
serverUri = new URI(String.format("ws://%s:%d/",host,port));
|
||||
// System.out.printf("Server URI: %s%n",serverUri);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSendTextMessages() throws Exception
|
||||
{
|
||||
|
@ -96,10 +95,11 @@ public class SafariWebsocketDraft0Test
|
|||
|
||||
CaptureSocket socket = servlet.captures.get(0);
|
||||
Assert.assertThat("CaptureSocket",socket,notNullValue());
|
||||
Assert.assertThat("CaptureSocket.isConnected", socket.isConnected(), is(true));
|
||||
Assert.assertThat("CaptureSocket.isConnected", socket.awaitConnected(1000), is(true));
|
||||
|
||||
// Give servlet 500 millisecond to process messages
|
||||
// Give servlet time to process messages
|
||||
threadSleep(1,TimeUnit.SECONDS);
|
||||
|
||||
// Should have captured 5 messages.
|
||||
Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5));
|
||||
}
|
||||
|
@ -109,13 +109,13 @@ public class SafariWebsocketDraft0Test
|
|||
safari.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void threadSleep(int dur, TimeUnit unit) throws InterruptedException
|
||||
{
|
||||
long ms = TimeUnit.MILLISECONDS.convert(dur,unit);
|
||||
Thread.sleep(ms);
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
|
|
|
@ -74,8 +74,10 @@ public class WebSocketClientTest
|
|||
@Test
|
||||
public void testMessageBiggerThanBufferSize() throws Exception
|
||||
{
|
||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
||||
int bufferSize = 512;
|
||||
WebSocketClientFactory factory = new WebSocketClientFactory(new QueuedThreadPool(), new ZeroMaskGen(), bufferSize);
|
||||
WebSocketClientFactory factory = new WebSocketClientFactory(threadPool, new ZeroMaskGen(), bufferSize);
|
||||
threadPool.start();
|
||||
factory.start();
|
||||
WebSocketClient client = new WebSocketClient(factory);
|
||||
|
||||
|
@ -118,6 +120,7 @@ public class WebSocketClientTest
|
|||
Assert.assertTrue(dataLatch.await(1000, TimeUnit.SECONDS));
|
||||
|
||||
factory.stop();
|
||||
threadPool.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -32,6 +30,9 @@ import org.junit.Assert;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
* WebSocketCommTest - to test reported undelivered messages in bug <a
|
||||
* href="https://jira.codehaus.org/browse/JETTY-1463">JETTY-1463</a>
|
||||
|
@ -109,11 +110,11 @@ public class WebSocketCommTest
|
|||
|
||||
CaptureSocket socket = servlet.captures.get(0);
|
||||
Assert.assertThat("CaptureSocket",socket,notNullValue());
|
||||
Assert.assertThat("CaptureSocket.isConnected",socket.isConnected(),is(true));
|
||||
Assert.assertThat("CaptureSocket.isConnected",socket.awaitConnected(1000),is(true));
|
||||
|
||||
// Give servlet 500 millisecond to process messages
|
||||
// Give servlet time to process messages
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
||||
|
||||
// Should have captured 5 messages.
|
||||
Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5));
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
|
@ -28,11 +26,9 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.bio.SocketEndPoint;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -45,7 +41,9 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class WebSocketLoadD13Test
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class WebSocketLoadRFC6455Test
|
||||
{
|
||||
private static Server _server;
|
||||
private static Connector _connector;
|
||||
|
@ -127,7 +125,7 @@ public class WebSocketLoadD13Test
|
|||
{
|
||||
this.outbound = outbound;
|
||||
}
|
||||
|
||||
|
||||
public void onMessage(String data)
|
||||
{
|
||||
try
|
||||
|
@ -155,7 +153,7 @@ public class WebSocketLoadD13Test
|
|||
private final CountDownLatch latch;
|
||||
private final SocketEndPoint _endp;
|
||||
private final WebSocketGeneratorRFC6455 _generator;
|
||||
private final WebSocketParserD13 _parser;
|
||||
private final WebSocketParserRFC6455 _parser;
|
||||
private final WebSocketParser.FrameHandler _handler = new WebSocketParser.FrameHandler()
|
||||
{
|
||||
public void onFrame(byte flags, byte opcode, Buffer buffer)
|
||||
|
@ -168,7 +166,7 @@ public class WebSocketLoadD13Test
|
|||
}
|
||||
};
|
||||
private volatile Buffer _response;
|
||||
|
||||
|
||||
public WebSocketClient(String host, int port, int readTimeout, CountDownLatch latch, int iterations) throws IOException
|
||||
{
|
||||
this.latch = latch;
|
||||
|
@ -177,11 +175,11 @@ public class WebSocketLoadD13Test
|
|||
output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "ISO-8859-1"));
|
||||
input = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));
|
||||
this.iterations = iterations;
|
||||
|
||||
|
||||
_endp=new SocketEndPoint(socket);
|
||||
_generator = new WebSocketGeneratorRFC6455(new WebSocketBuffers(32*1024),_endp,new FixedMaskGen());
|
||||
_parser = new WebSocketParserD13(new WebSocketBuffers(32*1024),_endp,_handler,false);
|
||||
|
||||
_parser = new WebSocketParserRFC6455(new WebSocketBuffers(32*1024),_endp,_handler,false);
|
||||
|
||||
}
|
||||
|
||||
private void open() throws IOException
|
||||
|
@ -216,9 +214,9 @@ public class WebSocketLoadD13Test
|
|||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
_generator.addFrame((byte)0x8,WebSocketConnectionRFC6455.OP_TEXT,data,0,data.length);
|
||||
_generator.flush();
|
||||
|
||||
|
||||
//System.err.println("-> "+message);
|
||||
|
||||
|
||||
_response=null;
|
||||
while(_response==null)
|
||||
_parser.parseNext();
|
|
@ -15,8 +15,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -30,11 +28,9 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -48,6 +44,10 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class WebSocketMessageRFC6455Test
|
||||
{
|
||||
private static Server __server;
|
||||
|
@ -78,7 +78,7 @@ public class WebSocketMessageRFC6455Test
|
|||
}
|
||||
};
|
||||
wsHandler.getWebSocketFactory().setBufferSize(8192);
|
||||
wsHandler.getWebSocketFactory().setMaxIdleTime(1000);
|
||||
wsHandler.getWebSocketFactory().setMaxIdleTime(1000);
|
||||
wsHandler.setHandler(new DefaultHandler());
|
||||
__server.setHandler(wsHandler);
|
||||
__server.start();
|
||||
|
@ -91,13 +91,13 @@ public class WebSocketMessageRFC6455Test
|
|||
__server.join();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testHash()
|
||||
{
|
||||
assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",WebSocketConnectionRFC6455.hashKey("dGhlIHNhbXBsZSBub25jZQ=="));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testServerSendBigStringMessage() throws Exception
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ public class WebSocketMessageRFC6455Test
|
|||
socket.setSoTimeout(1000);
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -127,7 +127,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
// Server sends a big message
|
||||
StringBuilder message = new StringBuilder();
|
||||
String text = "0123456789ABCDEF";
|
||||
|
@ -167,7 +167,7 @@ public class WebSocketMessageRFC6455Test
|
|||
socket.setSoTimeout(1000);
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -175,7 +175,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
assertEquals(0x81,input.read());
|
||||
assertEquals(0x0f,input.read());
|
||||
lookFor("sent on connect",input);
|
||||
|
@ -312,8 +312,8 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
|
||||
|
||||
// Server sends a big message
|
||||
String text = "0123456789ABCDEF ";
|
||||
text=text+text+text+text;
|
||||
|
@ -324,15 +324,15 @@ public class WebSocketMessageRFC6455Test
|
|||
deflater.setInput(data);
|
||||
deflater.finish();
|
||||
byte[] buf=new byte[data.length];
|
||||
|
||||
|
||||
buf[0]=(byte)((byte)0x7e);
|
||||
buf[1]=(byte)(data.length>>8);
|
||||
buf[2]=(byte)(data.length&0xff);
|
||||
|
||||
|
||||
int l=deflater.deflate(buf,3,buf.length-3);
|
||||
|
||||
assertTrue(deflater.finished());
|
||||
|
||||
|
||||
output.write(0xC1);
|
||||
output.write((byte)(0x80|(0xff&(l+3))));
|
||||
output.write(0x00);
|
||||
|
@ -341,41 +341,41 @@ public class WebSocketMessageRFC6455Test
|
|||
output.write(0x00);
|
||||
output.write(buf,0,l+3);
|
||||
output.flush();
|
||||
|
||||
|
||||
assertEquals(0x40+WebSocketConnectionRFC6455.OP_TEXT,input.read());
|
||||
assertEquals(0x20+3,input.read());
|
||||
assertEquals(0x7e,input.read());
|
||||
assertEquals(0x02,input.read());
|
||||
assertEquals(0x20,input.read());
|
||||
|
||||
|
||||
byte[] raw = new byte[32];
|
||||
assertEquals(32,input.read(raw));
|
||||
|
||||
|
||||
Inflater inflater = new Inflater();
|
||||
inflater.setInput(raw);
|
||||
|
||||
|
||||
byte[] result = new byte[544];
|
||||
assertEquals(544,inflater.inflate(result));
|
||||
assertEquals(TypeUtil.toHexString(data,0,544),TypeUtil.toHexString(result));
|
||||
|
||||
|
||||
|
||||
assertEquals((byte)0xC0,(byte)input.read());
|
||||
assertEquals(0x21+3,input.read());
|
||||
assertEquals(0x7e,input.read());
|
||||
assertEquals(0x02,input.read());
|
||||
assertEquals(0x21,input.read());
|
||||
|
||||
|
||||
assertEquals(32,input.read(raw));
|
||||
|
||||
|
||||
inflater.reset();
|
||||
inflater.setInput(raw);
|
||||
result = new byte[545];
|
||||
assertEquals(545,inflater.inflate(result));
|
||||
assertEquals(TypeUtil.toHexString(data,544,545),TypeUtil.toHexString(result));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testServerEcho() throws Exception
|
||||
{
|
||||
|
@ -403,10 +403,10 @@ public class WebSocketMessageRFC6455Test
|
|||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
// Make sure the read times out if there are problems with the implementation
|
||||
socket.setSoTimeout(1000);
|
||||
socket.setSoTimeout(1000);
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -414,12 +414,12 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
assertEquals(0x84,input.read());
|
||||
assertEquals(0x0f,input.read());
|
||||
lookFor("this is an echo",input);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBlockedConsumer() throws Exception
|
||||
{
|
||||
|
@ -436,7 +436,7 @@ public class WebSocketMessageRFC6455Test
|
|||
mesg[5]=(byte)0xff;
|
||||
for (int i=0;i<bytes.length;i++)
|
||||
mesg[6+i]=(byte)(bytes[i]^0xff);
|
||||
|
||||
|
||||
final int count = 100000;
|
||||
|
||||
output.write(
|
||||
|
@ -489,7 +489,7 @@ public class WebSocketMessageRFC6455Test
|
|||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
|
||||
// Send enough messages to fill receive buffer
|
||||
long max=0;
|
||||
long start=System.currentTimeMillis();
|
||||
|
@ -500,7 +500,7 @@ public class WebSocketMessageRFC6455Test
|
|||
{
|
||||
// System.err.println(">>> "+i);
|
||||
output.flush();
|
||||
|
||||
|
||||
long now=System.currentTimeMillis();
|
||||
long duration=now-start;
|
||||
start=now;
|
||||
|
@ -518,13 +518,13 @@ public class WebSocketMessageRFC6455Test
|
|||
assertEquals(count+1,__textCount.get()); // all messages
|
||||
assertTrue(max>2000); // was blocked
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBlockedProducer() throws Exception
|
||||
{
|
||||
final Socket socket = new Socket("localhost", __connector.getLocalPort());
|
||||
OutputStream output = socket.getOutputStream();
|
||||
|
||||
|
||||
final int count = 100000;
|
||||
|
||||
output.write(
|
||||
|
@ -581,8 +581,8 @@ public class WebSocketMessageRFC6455Test
|
|||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
|
||||
|
||||
|
||||
// Send enough messages to fill receive buffer
|
||||
long max=0;
|
||||
long start=System.currentTimeMillis();
|
||||
|
@ -593,7 +593,7 @@ public class WebSocketMessageRFC6455Test
|
|||
if (i%100==0)
|
||||
{
|
||||
output.flush();
|
||||
|
||||
|
||||
long now=System.currentTimeMillis();
|
||||
long duration=now-start;
|
||||
start=now;
|
||||
|
@ -601,10 +601,10 @@ public class WebSocketMessageRFC6455Test
|
|||
max=duration;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while(totalB.get()<(count*(mesg.length()+2)))
|
||||
Thread.sleep(100);
|
||||
|
||||
|
||||
assertEquals(count*(mesg.length()+2),totalB.get()); // all messages
|
||||
assertTrue(max>1000); // was blocked
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ public class WebSocketMessageRFC6455Test
|
|||
output.flush();
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -668,7 +668,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
socket.setSoTimeout(1000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -676,10 +676,10 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
__serverWebSocket.getConnection().setMaxTextMessageSize(10*1024);
|
||||
__serverWebSocket.getConnection().setAllowFrameFragmentation(true);
|
||||
|
||||
|
||||
output.write(0x81);
|
||||
output.write(0x80|0x7E);
|
||||
output.write((byte)((16*1024)>>8));
|
||||
|
@ -692,7 +692,7 @@ public class WebSocketMessageRFC6455Test
|
|||
for (int i=0;i<(16*1024);i++)
|
||||
output.write('X');
|
||||
output.flush();
|
||||
|
||||
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(33,input.read());
|
||||
|
@ -720,7 +720,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
socket.setSoTimeout(1000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -728,9 +728,9 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
__serverWebSocket.getConnection().setMaxTextMessageSize(15);
|
||||
|
||||
|
||||
output.write(0x01);
|
||||
output.write(0x8a);
|
||||
output.write(0xff);
|
||||
|
@ -779,7 +779,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
socket.setSoTimeout(100000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -787,9 +787,9 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
__serverWebSocket.getConnection().setMaxTextMessageSize(15);
|
||||
|
||||
|
||||
output.write(0x01);
|
||||
output.write(0x94);
|
||||
output.write(0xff);
|
||||
|
@ -800,9 +800,9 @@ public class WebSocketMessageRFC6455Test
|
|||
for (int i=0;i<bytes.length;i++)
|
||||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(30,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
|
@ -829,7 +829,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
socket.setSoTimeout(1000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -838,7 +838,7 @@ public class WebSocketMessageRFC6455Test
|
|||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
__serverWebSocket.getConnection().setMaxBinaryMessageSize(1024);
|
||||
|
||||
|
||||
output.write(WebSocketConnectionRFC6455.OP_BINARY);
|
||||
output.write(0x8a);
|
||||
output.write(0xff);
|
||||
|
@ -859,12 +859,12 @@ public class WebSocketMessageRFC6455Test
|
|||
for (int i=0;i<bytes.length;i++)
|
||||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
|
||||
|
||||
assertEquals(0x80+WebSocketConnectionRFC6455.OP_BINARY,input.read());
|
||||
assertEquals(20,input.read());
|
||||
lookFor("01234567890123456789",input);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMaxBinarySize() throws Exception
|
||||
{
|
||||
|
@ -884,7 +884,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
socket.setSoTimeout(100000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -892,9 +892,9 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
__serverWebSocket.getConnection().setMaxBinaryMessageSize(15);
|
||||
|
||||
|
||||
output.write(0x02);
|
||||
output.write(0x8a);
|
||||
output.write(0xff);
|
||||
|
@ -916,20 +916,20 @@ public class WebSocketMessageRFC6455Test
|
|||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
|
||||
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(19,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,code);
|
||||
lookFor("Message size > 15",input);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testCloseIn() throws Exception
|
||||
{
|
||||
int[][] tests =
|
||||
int[][] tests =
|
||||
{
|
||||
{-1,0,-1},
|
||||
{-1,0,-1},
|
||||
|
@ -960,7 +960,7 @@ public class WebSocketMessageRFC6455Test
|
|||
"",
|
||||
"mesg"
|
||||
};
|
||||
|
||||
|
||||
String[] resp =
|
||||
{
|
||||
"",
|
||||
|
@ -1007,14 +1007,14 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
int code=tests[t][0];
|
||||
String m=mesg[t];
|
||||
|
||||
|
||||
output.write(0x88);
|
||||
output.write(0x80 + (code<=0?0:(2+m.length())));
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
output.write(0x00);
|
||||
|
||||
|
||||
if (code>0)
|
||||
{
|
||||
output.write(code/0x100);
|
||||
|
@ -1022,12 +1022,12 @@ public class WebSocketMessageRFC6455Test
|
|||
output.write(m.getBytes());
|
||||
}
|
||||
output.flush();
|
||||
|
||||
|
||||
__serverWebSocket.awaitDisconnected(1000);
|
||||
|
||||
byte[] buf = new byte[128];
|
||||
int len = input.read(buf);
|
||||
|
||||
|
||||
assertEquals(tst,2+tests[t][1],len);
|
||||
assertEquals(tst,(byte)0x88,buf[0]);
|
||||
|
||||
|
@ -1035,7 +1035,7 @@ public class WebSocketMessageRFC6455Test
|
|||
{
|
||||
code=(0xff&buf[2])*0x100+(0xff&buf[3]);
|
||||
assertEquals(tst,tests[t][2],code);
|
||||
|
||||
|
||||
if (len>4)
|
||||
{
|
||||
m = new String(buf,4,len-4,"UTF-8");
|
||||
|
@ -1044,19 +1044,19 @@ public class WebSocketMessageRFC6455Test
|
|||
}
|
||||
else
|
||||
assertEquals(tst,tests[t][2],-1);
|
||||
|
||||
|
||||
|
||||
len = input.read(buf);
|
||||
assertEquals(tst,-1,len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testCloseOut() throws Exception
|
||||
{
|
||||
int[][] tests =
|
||||
int[][] tests =
|
||||
{
|
||||
{-1,0,-1},
|
||||
{-1,0,-1},
|
||||
|
@ -1127,7 +1127,7 @@ public class WebSocketMessageRFC6455Test
|
|||
{
|
||||
int code=(0xff&buf[2])*0x100+(0xff&buf[3]);
|
||||
assertEquals(tst,tests[t][2],code);
|
||||
|
||||
|
||||
if (len>4)
|
||||
{
|
||||
String m = new String(buf,4,len-4,"UTF-8");
|
||||
|
@ -1136,7 +1136,7 @@ public class WebSocketMessageRFC6455Test
|
|||
}
|
||||
else
|
||||
assertEquals(tst,tests[t][2],-1);
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
output.write(0x88);
|
||||
|
@ -1152,12 +1152,12 @@ public class WebSocketMessageRFC6455Test
|
|||
System.err.println("socket "+socket);
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
len = input.read(buf);
|
||||
assertEquals(tst,-1,len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testNotUTF8() throws Exception
|
||||
|
@ -1225,7 +1225,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
socket.setSoTimeout(100000);
|
||||
InputStream input = socket.getInputStream();
|
||||
|
||||
|
||||
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
|
||||
skipTo("Sec-WebSocket-Accept: ",input);
|
||||
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
|
||||
|
@ -1233,9 +1233,9 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
__serverWebSocket.getConnection().setMaxBinaryMessageSize(15);
|
||||
|
||||
|
||||
output.write(0x02);
|
||||
output.write(0x94);
|
||||
output.write(0xff);
|
||||
|
@ -1246,7 +1246,7 @@ public class WebSocketMessageRFC6455Test
|
|||
for (int i=0;i<bytes.length;i++)
|
||||
output.write(bytes[i]^0xff);
|
||||
output.flush();
|
||||
|
||||
|
||||
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
|
||||
assertEquals(19,input.read());
|
||||
int code=(0xff&input.read())*0x100+(0xff&input.read());
|
||||
|
@ -1283,7 +1283,7 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
assertEquals(0x81,input.read());
|
||||
assertEquals(0x0f,input.read());
|
||||
lookFor("sent on connect",input);
|
||||
|
@ -1302,8 +1302,8 @@ public class WebSocketMessageRFC6455Test
|
|||
output.write(0xff);
|
||||
output.write(0xff);
|
||||
output.flush();
|
||||
|
||||
|
||||
|
||||
|
||||
assertTrue(__serverWebSocket.awaitDisconnected(5000));
|
||||
try
|
||||
{
|
||||
|
@ -1346,12 +1346,12 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
assertEquals(0x81,input.read());
|
||||
assertEquals(0x0f,input.read());
|
||||
lookFor("sent on connect",input);
|
||||
socket.close();
|
||||
|
||||
|
||||
assertTrue(__serverWebSocket.awaitDisconnected(500));
|
||||
|
||||
try
|
||||
|
@ -1362,7 +1362,7 @@ public class WebSocketMessageRFC6455Test
|
|||
catch(IOException e)
|
||||
{
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1395,19 +1395,19 @@ public class WebSocketMessageRFC6455Test
|
|||
|
||||
assertTrue(__serverWebSocket.awaitConnected(1000));
|
||||
assertNotNull(__serverWebSocket.connection);
|
||||
|
||||
|
||||
assertEquals(0x81,input.read());
|
||||
assertEquals(0x0f,input.read());
|
||||
lookFor("sent on connect",input);
|
||||
|
||||
|
||||
socket.shutdownOutput();
|
||||
|
||||
|
||||
assertTrue(__serverWebSocket.awaitDisconnected(500));
|
||||
|
||||
assertEquals(0x88,input.read());
|
||||
assertEquals(0x00,input.read());
|
||||
assertEquals(-1,input.read());
|
||||
|
||||
|
||||
// look for broken pipe
|
||||
try
|
||||
{
|
||||
|
@ -1420,24 +1420,24 @@ public class WebSocketMessageRFC6455Test
|
|||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testParserAndGenerator() throws Exception
|
||||
{
|
||||
String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
|
||||
final AtomicReference<String> received = new AtomicReference<String>();
|
||||
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096);
|
||||
|
||||
|
||||
WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,null);
|
||||
|
||||
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length);
|
||||
|
||||
|
||||
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
|
||||
|
||||
WebSocketParserD13 parser = new WebSocketParserD13(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
|
||||
|
||||
WebSocketParserRFC6455 parser = new WebSocketParserRFC6455(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
|
||||
{
|
||||
public void onFrame(byte flags, byte opcode, Buffer buffer)
|
||||
{
|
||||
|
@ -1449,12 +1449,12 @@ public class WebSocketMessageRFC6455Test
|
|||
}
|
||||
|
||||
},false);
|
||||
|
||||
|
||||
parser.parseNext();
|
||||
|
||||
|
||||
assertEquals(message,received.get());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParserAndGeneratorMasked() throws Exception
|
||||
{
|
||||
|
@ -1463,14 +1463,14 @@ public class WebSocketMessageRFC6455Test
|
|||
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096);
|
||||
|
||||
MaskGen maskGen = new RandomMaskGen();
|
||||
|
||||
|
||||
WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,maskGen);
|
||||
byte[] data = message.getBytes(StringUtil.__UTF8);
|
||||
gen.addFrame((byte)0x8,(byte)0x1,data,0,data.length);
|
||||
|
||||
|
||||
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
|
||||
|
||||
WebSocketParserD13 parser = new WebSocketParserD13(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
|
||||
|
||||
WebSocketParserRFC6455 parser = new WebSocketParserRFC6455(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
|
||||
{
|
||||
public void onFrame(byte flags, byte opcode, Buffer buffer)
|
||||
{
|
||||
|
@ -1481,13 +1481,13 @@ public class WebSocketMessageRFC6455Test
|
|||
{
|
||||
}
|
||||
},true);
|
||||
|
||||
|
||||
parser.parseNext();
|
||||
|
||||
|
||||
assertEquals(message,received.get());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void lookFor(String string,InputStream in)
|
||||
throws IOException
|
||||
{
|
||||
|
@ -1535,7 +1535,7 @@ public class WebSocketMessageRFC6455Test
|
|||
state=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class TestWebSocket implements WebSocket.OnFrame, WebSocket.OnBinaryMessage, WebSocket.OnTextMessage
|
||||
{
|
||||
|
@ -1556,7 +1556,7 @@ public class WebSocketMessageRFC6455Test
|
|||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
||||
public void onOpen(Connection connection)
|
||||
{
|
||||
if (_onConnect)
|
||||
|
@ -1582,14 +1582,14 @@ public class WebSocketMessageRFC6455Test
|
|||
{
|
||||
return disconnected.await(time, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
public void onClose(int code,String message)
|
||||
{
|
||||
disconnected.countDown();
|
||||
}
|
||||
|
||||
public boolean onFrame(byte flags, byte opcode, byte[] data, int offset, int length)
|
||||
{
|
||||
{
|
||||
if (_echo)
|
||||
{
|
||||
switch(opcode)
|
||||
|
@ -1598,7 +1598,7 @@ public class WebSocketMessageRFC6455Test
|
|||
case WebSocketConnectionRFC6455.OP_PING:
|
||||
case WebSocketConnectionRFC6455.OP_PONG:
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
try
|
||||
{
|
||||
|
@ -1642,7 +1642,7 @@ public class WebSocketMessageRFC6455Test
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_aggregate)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -35,6 +35,8 @@ public class WebSocketOverSSLTest
|
|||
{
|
||||
private Server _server;
|
||||
private int _port;
|
||||
private QueuedThreadPool _threadPool;
|
||||
private WebSocketClientFactory _wsFactory;
|
||||
private WebSocket.Connection _connection;
|
||||
|
||||
private void startServer(final WebSocket webSocket) throws Exception
|
||||
|
@ -61,13 +63,18 @@ public class WebSocketOverSSLTest
|
|||
{
|
||||
Assert.assertTrue(_server.isStarted());
|
||||
|
||||
WebSocketClientFactory factory = new WebSocketClientFactory(new QueuedThreadPool(), new ZeroMaskGen());
|
||||
SslContextFactory cf = factory.getSslContextFactory();
|
||||
_threadPool = new QueuedThreadPool();
|
||||
_threadPool.setName("wsc-" + _threadPool.getName());
|
||||
_threadPool.start();
|
||||
|
||||
_wsFactory = new WebSocketClientFactory(_threadPool, new ZeroMaskGen());
|
||||
SslContextFactory cf = _wsFactory.getSslContextFactory();
|
||||
cf.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
|
||||
cf.setKeyStorePassword("storepwd");
|
||||
cf.setKeyManagerPassword("keypwd");
|
||||
factory.start();
|
||||
WebSocketClient client = new WebSocketClient(factory);
|
||||
_wsFactory.start();
|
||||
|
||||
WebSocketClient client = new WebSocketClient(_wsFactory);
|
||||
_connection = client.open(new URI("wss://localhost:" + _port), webSocket).get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
@ -76,6 +83,13 @@ public class WebSocketOverSSLTest
|
|||
{
|
||||
if (_connection != null)
|
||||
_connection.close();
|
||||
|
||||
if (_wsFactory != null)
|
||||
_wsFactory.stop();
|
||||
|
||||
if (_threadPool != null)
|
||||
_threadPool.stop();
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.stop();
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -30,12 +28,16 @@ import org.eclipse.jetty.util.Utf8StringBuilder;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class WebSocketParserRFC6455Test
|
||||
{
|
||||
private ByteArrayEndPoint _endPoint;
|
||||
private MaskedByteArrayBuffer _in;
|
||||
private Handler _handler;
|
||||
private WebSocketParserD13 _parser;
|
||||
private WebSocketParserRFC6455 _parser;
|
||||
private byte[] _mask = new byte[] {(byte)0x00,(byte)0xF0,(byte)0x0F,(byte)0xFF};
|
||||
private int _m;
|
||||
|
||||
|
@ -45,7 +47,7 @@ public class WebSocketParserRFC6455Test
|
|||
{
|
||||
super(4096);
|
||||
}
|
||||
|
||||
|
||||
public void sendMask()
|
||||
{
|
||||
super.poke(putIndex(),_mask,0,4);
|
||||
|
@ -63,7 +65,7 @@ public class WebSocketParserRFC6455Test
|
|||
{
|
||||
super.put(b);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void put(byte b)
|
||||
{
|
||||
|
@ -87,10 +89,10 @@ public class WebSocketParserRFC6455Test
|
|||
{
|
||||
return put(b,0,b.length);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
|
@ -98,10 +100,10 @@ public class WebSocketParserRFC6455Test
|
|||
_endPoint = new ByteArrayEndPoint();
|
||||
_endPoint.setNonBlocking(true);
|
||||
_handler = new Handler();
|
||||
_parser=new WebSocketParserD13(buffers, _endPoint,_handler,true);
|
||||
_parser=new WebSocketParserRFC6455(buffers, _endPoint,_handler,true);
|
||||
_parser.setFakeFragments(false);
|
||||
_in = new MaskedByteArrayBuffer();
|
||||
|
||||
|
||||
_endPoint.setIn(_in);
|
||||
}
|
||||
|
||||
|
@ -127,7 +129,7 @@ public class WebSocketParserRFC6455Test
|
|||
_parser.returnBuffer();
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testShortText() throws Exception
|
||||
{
|
||||
|
@ -147,7 +149,7 @@ public class WebSocketParserRFC6455Test
|
|||
_parser.returnBuffer();
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testShortUtf8() throws Exception
|
||||
{
|
||||
|
@ -169,7 +171,7 @@ public class WebSocketParserRFC6455Test
|
|||
assertTrue(_parser.isBufferEmpty());
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMediumText() throws Exception
|
||||
{
|
||||
|
@ -177,9 +179,9 @@ public class WebSocketParserRFC6455Test
|
|||
for (int i=0;i<4;i++)
|
||||
string = string+string;
|
||||
string += ". The end.";
|
||||
|
||||
|
||||
byte[] bytes = string.getBytes(StringUtil.__UTF8);
|
||||
|
||||
|
||||
_in.putUnmasked((byte)0x81);
|
||||
_in.putUnmasked((byte)(0x80|0x7E));
|
||||
_in.putUnmasked((byte)(bytes.length>>8));
|
||||
|
@ -197,21 +199,21 @@ public class WebSocketParserRFC6455Test
|
|||
assertTrue(_parser.isBufferEmpty());
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLongText() throws Exception
|
||||
{
|
||||
WebSocketBuffers buffers = new WebSocketBuffers(0x20000);
|
||||
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
|
||||
WebSocketParserD13 parser=new WebSocketParserD13(buffers, endPoint,_handler,false);
|
||||
WebSocketParserRFC6455 parser=new WebSocketParserRFC6455(buffers, endPoint,_handler,false);
|
||||
ByteArrayBuffer in = new ByteArrayBuffer(0x20000);
|
||||
endPoint.setIn(in);
|
||||
|
||||
|
||||
String string = "Hell\uFF4f Big W\uFF4Frld ";
|
||||
for (int i=0;i<12;i++)
|
||||
string = string+string;
|
||||
string += ". The end.";
|
||||
|
||||
|
||||
byte[] bytes = string.getBytes("UTF-8");
|
||||
|
||||
_in.sendMask();
|
||||
|
@ -269,7 +271,7 @@ public class WebSocketParserRFC6455Test
|
|||
{
|
||||
// Buffers are only 1024, so this frame is too large
|
||||
_parser.setFakeFragments(false);
|
||||
|
||||
|
||||
_in.putUnmasked((byte)0x81);
|
||||
_in.putUnmasked((byte)(0x80|0x7E));
|
||||
_in.putUnmasked((byte)(2048>>8));
|
||||
|
@ -280,8 +282,8 @@ public class WebSocketParserRFC6455Test
|
|||
|
||||
assertTrue(progress>0);
|
||||
assertEquals(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,_handler._code);
|
||||
|
||||
|
||||
|
||||
|
||||
for (int i=0;i<2048;i++)
|
||||
_in.put((byte)'a');
|
||||
progress =_parser.parseNext();
|
||||
|
@ -289,7 +291,7 @@ public class WebSocketParserRFC6455Test
|
|||
assertTrue(progress>0);
|
||||
assertEquals(0,_handler._data.size());
|
||||
assertEquals(0,_handler._utf8.length());
|
||||
|
||||
|
||||
_handler._code=0;
|
||||
|
||||
_in.putUnmasked((byte)0x81);
|
||||
|
@ -310,7 +312,7 @@ public class WebSocketParserRFC6455Test
|
|||
{
|
||||
// Buffers are only 1024, so this frame will be fake fragmented
|
||||
_parser.setFakeFragments(true);
|
||||
|
||||
|
||||
_in.putUnmasked((byte)0x81);
|
||||
_in.putUnmasked((byte)(0x80|0x7E));
|
||||
_in.putUnmasked((byte)(2048>>8));
|
||||
|
@ -318,7 +320,7 @@ public class WebSocketParserRFC6455Test
|
|||
_in.sendMask();
|
||||
for (int i=0;i<2048;i++)
|
||||
_in.put((byte)('a'+i%26));
|
||||
|
||||
|
||||
int progress =_parser.parseNext();
|
||||
assertTrue(progress>0);
|
||||
|
||||
|
@ -355,21 +357,21 @@ public class WebSocketParserRFC6455Test
|
|||
_parser.returnBuffer();
|
||||
assertTrue(_parser.isBufferEmpty());
|
||||
assertTrue(_parser.getBuffer()==null);
|
||||
|
||||
|
||||
_in.clear();
|
||||
_in.put(bytes);
|
||||
_endPoint.setIn(_in);
|
||||
progress =_parser.parseNext();
|
||||
assertTrue(progress>0);
|
||||
|
||||
|
||||
_endPoint.shutdownInput();
|
||||
|
||||
|
||||
progress =_parser.parseNext();
|
||||
assertEquals(-1,progress);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private class Handler implements WebSocketParser.FrameHandler
|
||||
{
|
||||
Utf8StringBuilder _utf8 = new Utf8StringBuilder();
|
||||
|
|
|
@ -17,12 +17,14 @@ package org.eclipse.jetty.websocket.helper;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.websocket.WebSocket;
|
||||
|
||||
public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage
|
||||
public class CaptureSocket implements WebSocket.OnTextMessage
|
||||
{
|
||||
private Connection conn;
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
public List<String> messages;
|
||||
|
||||
public CaptureSocket()
|
||||
|
@ -30,13 +32,9 @@ public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage
|
|||
messages = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public boolean isConnected()
|
||||
public boolean awaitConnected(long timeout) throws InterruptedException
|
||||
{
|
||||
if (conn == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return conn.isOpen();
|
||||
return latch.await(timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void onMessage(String data)
|
||||
|
@ -47,11 +45,10 @@ public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage
|
|||
|
||||
public void onOpen(Connection connection)
|
||||
{
|
||||
this.conn = connection;
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
public void onClose(int closeCode, String message)
|
||||
{
|
||||
this.conn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket.helper;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -32,6 +30,8 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
|
|||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.Assert;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class SafariD00
|
||||
{
|
||||
private URI uri;
|
||||
|
@ -48,7 +48,7 @@ public class SafariD00
|
|||
|
||||
/**
|
||||
* Open the Socket to the destination endpoint and
|
||||
*
|
||||
*
|
||||
* @return the open java Socket.
|
||||
* @throws IOException
|
||||
*/
|
||||
|
@ -65,7 +65,7 @@ public class SafariD00
|
|||
|
||||
/**
|
||||
* Issue an Http websocket (Draft-0) upgrade request using the Safari particulars.
|
||||
*
|
||||
*
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
public void issueHandshake() throws IOException
|
||||
|
@ -96,6 +96,8 @@ public class SafariD00
|
|||
InputStreamReader reader = new InputStreamReader(in);
|
||||
BufferedReader br = new BufferedReader(reader);
|
||||
|
||||
socket.setSoTimeout(5000);
|
||||
|
||||
boolean foundEnd = false;
|
||||
String line;
|
||||
while (!foundEnd)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>test-jetty-webapp</artifactId>
|
||||
<name>Test :: Jetty Test Webapp</name>
|
||||
<packaging>war</packaging>
|
||||
|
|
Loading…
Reference in New Issue