Merged branch 'jetty-9.4.x' into 'master'.
This commit is contained in:
commit
b7b3dfdc77
|
@ -46,7 +46,6 @@ import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
|||
import org.eclipse.jetty.jmx.MBeanContainer;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -56,7 +55,6 @@ import org.eclipse.jetty.servlet.DefaultServlet;
|
|||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlets.PushCacheFilter;
|
||||
import org.eclipse.jetty.servlets.PushSessionCacheFilter;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
|
||||
|
@ -109,7 +107,6 @@ public class Http2Server
|
|||
// HTTP/2 Connection Factory
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(https_config);
|
||||
|
||||
NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(http.getDefaultProtocol());
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
package org.eclipse.jetty.alpn.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
@ -29,27 +31,58 @@ import org.eclipse.jetty.io.ClientConnectionFactory;
|
|||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.NegotiatingClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor;
|
||||
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
|
||||
import org.eclipse.jetty.io.ssl.SslHandshakeListener;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
|
||||
public class ALPNClientConnectionFactory extends NegotiatingClientConnectionFactory
|
||||
public class ALPNClientConnectionFactory extends NegotiatingClientConnectionFactory implements SslHandshakeListener
|
||||
{
|
||||
private final SslHandshakeListener alpnListener = new ALPNListener();
|
||||
private final Executor executor;
|
||||
private final List<String> protocols;
|
||||
private final ALPNProcessor.Client alpnProcessor;
|
||||
|
||||
public ALPNClientConnectionFactory(Executor executor, ClientConnectionFactory connectionFactory, List<String> protocols)
|
||||
{
|
||||
super(connectionFactory);
|
||||
this.executor = executor;
|
||||
this.protocols = protocols;
|
||||
if (protocols.isEmpty())
|
||||
throw new IllegalArgumentException("ALPN protocol list cannot be empty");
|
||||
this.executor = executor;
|
||||
this.protocols = protocols;
|
||||
Iterator<ALPNProcessor.Client> processors = ServiceLoader.load(ALPNProcessor.Client.class).iterator();
|
||||
alpnProcessor = processors.hasNext() ? processors.next() : ALPNProcessor.Client.NOOP;
|
||||
}
|
||||
|
||||
public ALPNProcessor.Client getALPNProcessor()
|
||||
{
|
||||
return alpnProcessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
|
||||
{
|
||||
SSLEngine sslEngine = (SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY);
|
||||
getALPNProcessor().configure(sslEngine, protocols);
|
||||
ContainerLifeCycle connector = (ContainerLifeCycle)context.get(ClientConnectionFactory.CONNECTOR_CONTEXT_KEY);
|
||||
// Method addBean() has set semantic, so the listener is added only once.
|
||||
connector.addBean(alpnListener);
|
||||
ALPNClientConnection connection = new ALPNClientConnection(endPoint, executor, getClientConnectionFactory(),
|
||||
(SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY), context, protocols);
|
||||
sslEngine, context, protocols);
|
||||
return customize(connection, context);
|
||||
}
|
||||
|
||||
private class ALPNListener implements SslHandshakeListener
|
||||
{
|
||||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
getALPNProcessor().process(event.getSSLEngine());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeFailed(Event event, Throwable failure)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-java-client</artifactId>
|
||||
<name>Jetty :: ALPN :: JDK9 Client Implementation</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.alpn.java.client</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.9</source>
|
||||
<target>1.9</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.alpn.java.client;
|
||||
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
|
||||
import org.eclipse.jetty.alpn.ALPN;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor;
|
||||
|
||||
public class JDK9ClientALPNProcessor implements ALPNProcessor.Client
|
||||
{
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine, List<String> protocols)
|
||||
{
|
||||
SSLParameters sslParameters = sslEngine.getSSLParameters();
|
||||
sslParameters.setApplicationProtocols(protocols.toArray(new String[0]));
|
||||
sslEngine.setSSLParameters(sslParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(SSLEngine sslEngine)
|
||||
{
|
||||
try
|
||||
{
|
||||
ALPN.ClientProvider provider = (ALPN.ClientProvider)ALPN.get(sslEngine);
|
||||
provider.selected(sslEngine.getApplicationProtocol());
|
||||
}
|
||||
catch (SSLException x)
|
||||
{
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.alpn.java.client.JDK9ClientALPNProcessor
|
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.alpn.java.client;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.client.HTTP2Client;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.Jetty;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
public class JDK9HTTP2Client
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
HTTP2Client client = new HTTP2Client();
|
||||
SslContextFactory sslContextFactory = new SslContextFactory(true);
|
||||
client.addBean(sslContextFactory);
|
||||
client.start();
|
||||
|
||||
String host = "localhost";
|
||||
int port = 8443;
|
||||
|
||||
FuturePromise<Session> sessionPromise = new FuturePromise<>();
|
||||
client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise);
|
||||
Session session = sessionPromise.get(555, TimeUnit.SECONDS);
|
||||
|
||||
HttpFields requestFields = new HttpFields();
|
||||
requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
|
||||
MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields);
|
||||
HeadersFrame headersFrame = new HeadersFrame(metaData, null, true);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onHeaders(Stream stream, HeadersFrame frame)
|
||||
{
|
||||
System.err.println(frame);
|
||||
if (frame.isEndStream())
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onData(Stream stream, DataFrame frame, Callback callback)
|
||||
{
|
||||
System.err.println(frame);
|
||||
callback.succeeded();
|
||||
if (frame.isEndStream())
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
latch.await(5, TimeUnit.SECONDS);
|
||||
|
||||
client.stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-parent</artifactId>
|
||||
<version>9.4.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-alpn-java-server</artifactId>
|
||||
<name>Jetty :: ALPN :: JDK9 Server Implementation</name>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.alpn.java.server</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.9</source>
|
||||
<target>1.9</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.alpn.java.server;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
import org.eclipse.jetty.alpn.ALPN;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor;
|
||||
|
||||
public class JDK9ServerALPNProcessor implements ALPNProcessor.Server
|
||||
{
|
||||
@Override
|
||||
public void configure(SSLEngine sslEngine)
|
||||
{
|
||||
sslEngine.setHandshakeApplicationProtocolSelector(this::process);
|
||||
}
|
||||
|
||||
private String process(SSLEngine sslEngine, List<String> protocols)
|
||||
{
|
||||
try
|
||||
{
|
||||
ALPN.ServerProvider provider = (ALPN.ServerProvider)ALPN.get(sslEngine);
|
||||
return provider.select(protocols);
|
||||
}
|
||||
catch (SSLException x)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.alpn.java.server.JDK9ServerALPNProcessor
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.alpn.java.server;
|
||||
|
||||
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
|
||||
import org.eclipse.jetty.http2.HTTP2Cipher;
|
||||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
/**
|
||||
* Test server that verifies that the JDK 9 ALPN mechanism works.
|
||||
*/
|
||||
public class JDK9HTTP2Server
|
||||
{
|
||||
public static void main(String... args) throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
|
||||
HttpConfiguration httpsConfig = new HttpConfiguration();
|
||||
httpsConfig.setSecureScheme("https");
|
||||
httpsConfig.setSecurePort(8443);
|
||||
httpsConfig.setSendXPoweredBy(true);
|
||||
httpsConfig.setSendServerVersion(true);
|
||||
httpsConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
|
||||
sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
|
||||
sslContextFactory.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");
|
||||
sslContextFactory.setCipherComparator(HTTP2Cipher.COMPARATOR);
|
||||
|
||||
HttpConnectionFactory http = new HttpConnectionFactory(httpsConfig);
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(http.getProtocol());
|
||||
SslConnectionFactory ssl = new SslConnectionFactory(sslContextFactory, alpn.getProtocol());
|
||||
|
||||
ServerConnector http2Connector = new ServerConnector(server, ssl, alpn, h2, http);
|
||||
http2Connector.setPort(8443);
|
||||
server.addConnector(http2Connector);
|
||||
|
||||
server.start();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
Binary file not shown.
|
@ -0,0 +1,28 @@
|
|||
[description]
|
||||
Provides ALPN support for JDK 8, modifying the sun.security.ssl
|
||||
classes and adding them to the JVM boot classpath.
|
||||
This modification has a tight dependency on specific recent updates of
|
||||
Java 1.7 and Java 1.8 (Java versions prior to 1.7u40 are not supported).
|
||||
This module will use an appropriate alpn-boot jar for your
|
||||
specific version of Java.
|
||||
# IMPORTANT: Versions of Java that exist after this module was created are
|
||||
# not guaranteed to work with existing alpn-boot jars, and might
|
||||
# need a new alpn-boot to be created / tested / deployed by the
|
||||
# Jetty project in order to provide support for these future
|
||||
# Java versions.
|
||||
#
|
||||
# All versions of the alpn-boot can be found at
|
||||
# http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/
|
||||
|
||||
[depend]
|
||||
alpn-impl/alpn-${java.version}
|
||||
|
||||
[files]
|
||||
lib/
|
||||
lib/alpn/
|
||||
|
||||
[license]
|
||||
ALPN is a hosted at github under the GPL v2 with ClassPath Exception.
|
||||
ALPN replaces/modifies OpenJDK classes in the sun.security.ssl package.
|
||||
http://github.com/jetty-project/jetty-alpn
|
||||
http://openjdk.java.net/legal/gplv2+ce.html
|
|
@ -0,0 +1,6 @@
|
|||
[description]
|
||||
Provides support for ALPN based on JDK 9 APIs.
|
||||
|
||||
[lib]
|
||||
lib/jetty-alpn-java-server-${jetty.version}.jar
|
||||
lib/alpn-api-*.jar
|
|
@ -1,23 +1,9 @@
|
|||
[description]
|
||||
Enables the ALPN extension to TLS(SSL) by adding modified classes to
|
||||
the JVM bootpath.
|
||||
This modification has a tight dependency on specific recent updates of
|
||||
Java 1.7 and Java 1.8 (Java versions prior to 1.7u40 are not supported).
|
||||
The alpn module will use an appropriate alpn-boot jar for your
|
||||
specific version of Java.
|
||||
#
|
||||
# IMPORTANT: Versions of Java that exist after this module was created are
|
||||
# not guaranteed to work with existing alpn-boot jars, and might
|
||||
# need a new alpn-boot to be created / tested / deployed by the
|
||||
# Jetty project in order to provide support for these future
|
||||
# Java versions.
|
||||
#
|
||||
# All versions of alpn-boot can be found at
|
||||
# http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/
|
||||
Enables the ALPN (Application Layer Protocol Negotiation) TLS extension.
|
||||
|
||||
[depend]
|
||||
ssl
|
||||
alpn-impl/alpn-${java.version}
|
||||
alpn-impl/alpn-${java.version.platform}
|
||||
|
||||
[lib]
|
||||
lib/jetty-alpn-client-${jetty.version}.jar
|
||||
|
@ -26,15 +12,11 @@ lib/jetty-alpn-server-${jetty.version}.jar
|
|||
[xml]
|
||||
etc/jetty-alpn.xml
|
||||
|
||||
[files]
|
||||
lib/
|
||||
lib/alpn/
|
||||
|
||||
[ini-template]
|
||||
## Overrides the order protocols are chosen by the server.
|
||||
## The default order is that specified by the order of the
|
||||
## modules declared in start.ini.
|
||||
# jetty.alpn.protocols=h2-16,http/1.1
|
||||
# jetty.alpn.protocols=h2,http/1.1
|
||||
|
||||
## Specifies what protocol to use when negotiation fails.
|
||||
# jetty.alpn.defaultProtocol=http/1.1
|
||||
|
@ -42,8 +24,3 @@ lib/alpn/
|
|||
## ALPN debug logging on System.err
|
||||
# jetty.alpn.debug=false
|
||||
|
||||
[license]
|
||||
ALPN is a hosted at github under the GPL v2 with ClassPath Exception.
|
||||
ALPN replaces/modifies OpenJDK classes in the java.sun.security.ssl package.
|
||||
http://github.com/jetty-project/jetty-alpn
|
||||
http://openjdk.java.net/legal/gplv2+ce.html
|
||||
|
|
|
@ -18,22 +18,22 @@
|
|||
|
||||
package org.eclipse.jetty.alpn.server;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.alpn.ALPN;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.ssl.ALPNProcessor;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFactory
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ALPNServerConnectionFactory.class);
|
||||
private final ALPNProcessor.Server alpnProcessor;
|
||||
|
||||
public ALPNServerConnectionFactory(String protocols)
|
||||
{
|
||||
|
@ -43,25 +43,20 @@ public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFact
|
|||
public ALPNServerConnectionFactory(@Name("protocols") String... protocols)
|
||||
{
|
||||
super("alpn", protocols);
|
||||
try
|
||||
{
|
||||
ClassLoader alpnClassLoader = ALPN.class.getClassLoader();
|
||||
if (alpnClassLoader != null)
|
||||
{
|
||||
LOG.warn("ALPN must be in the boot classloader, not in: " + alpnClassLoader);
|
||||
throw new IllegalStateException("ALPN must be in the boot classloader");
|
||||
}
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
LOG.warn("ALPN not available", x);
|
||||
throw new IllegalStateException("ALPN not available", x);
|
||||
}
|
||||
checkProtocolNegotiationAvailable();
|
||||
Iterator<ALPNProcessor.Server> processors = ServiceLoader.load(ALPNProcessor.Server.class).iterator();
|
||||
alpnProcessor = processors.hasNext() ? processors.next() : ALPNProcessor.Server.NOOP;
|
||||
}
|
||||
|
||||
public ALPNProcessor.Server getALPNProcessor()
|
||||
{
|
||||
return alpnProcessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
|
||||
{
|
||||
getALPNProcessor().configure(engine);
|
||||
return new ALPNServerConnection(connector, endPoint, engine, protocols, defaultProtocol);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
|
@ -12,4 +14,16 @@
|
|||
<module>jetty-alpn-server</module>
|
||||
<module>jetty-alpn-client</module>
|
||||
</modules>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jdk9</id>
|
||||
<activation>
|
||||
<jdk>[1.9,)</jdk>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>jetty-alpn-java-client</module>
|
||||
<module>jetty-alpn-java-server</module>
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -36,6 +37,7 @@ import org.eclipse.jetty.client.http.HttpDestinationOverHTTP;
|
|||
import org.eclipse.jetty.client.util.ByteBufferContentProvider;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.StacklessLogging;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -266,7 +268,8 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
try
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
IO.copy(request.getInputStream(), response.getOutputStream());
|
||||
if (request.getDispatcherType() != DispatcherType.ERROR)
|
||||
IO.copy(request.getInputStream(), response.getOutputStream());
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
|
@ -282,22 +285,22 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
try
|
||||
{
|
||||
client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.onRequestCommit(request ->
|
||||
{
|
||||
aborted.set(request.abort(cause));
|
||||
latch.countDown();
|
||||
})
|
||||
.content(new ByteBufferContentProvider(ByteBuffer.wrap(new byte[]{0}), ByteBuffer.wrap(new byte[]{1}))
|
||||
{
|
||||
@Override
|
||||
public long getLength()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
})
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
.scheme(scheme)
|
||||
.onRequestCommit(request ->
|
||||
{
|
||||
aborted.set(request.abort(cause));
|
||||
latch.countDown();
|
||||
})
|
||||
.content(new ByteBufferContentProvider(ByteBuffer.wrap(new byte[]{0}), ByteBuffer.wrap(new byte[]{1}))
|
||||
{
|
||||
@Override
|
||||
public long getLength()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
})
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (ExecutionException x)
|
||||
|
@ -312,57 +315,72 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
Assert.assertEquals(0, connectionPool.getConnectionCount());
|
||||
Assert.assertEquals(0, connectionPool.getActiveConnections().size());
|
||||
Assert.assertEquals(0, connectionPool.getIdleConnections().size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbortOnContent() throws Exception
|
||||
{
|
||||
start(new EmptyServerHandler()
|
||||
try (StacklessLogging suppressor = new StacklessLogging(org.eclipse.jetty.server.HttpChannel.class))
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
CountDownLatch serverLatch = new CountDownLatch(1);
|
||||
start(new EmptyServerHandler()
|
||||
{
|
||||
super.handle(target, baseRequest, request, response);
|
||||
IO.copy(request.getInputStream(), response.getOutputStream());
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
super.handle(target, baseRequest, request, response);
|
||||
if (request.getDispatcherType() != DispatcherType.ERROR)
|
||||
IO.copy(request.getInputStream(), response.getOutputStream());
|
||||
}
|
||||
finally
|
||||
{
|
||||
serverLatch.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final Throwable cause = new Exception();
|
||||
final AtomicBoolean aborted = new AtomicBoolean();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
try
|
||||
{
|
||||
client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.onRequestContent((request, content) ->
|
||||
{
|
||||
aborted.set(request.abort(cause));
|
||||
latch.countDown();
|
||||
})
|
||||
.content(new ByteBufferContentProvider(ByteBuffer.wrap(new byte[]{0}), ByteBuffer.wrap(new byte[]{1}))
|
||||
{
|
||||
@Override
|
||||
public long getLength()
|
||||
final Throwable cause = new Exception();
|
||||
final AtomicBoolean aborted = new AtomicBoolean();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
try
|
||||
{
|
||||
client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(scheme)
|
||||
.onRequestContent((request, content) ->
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
})
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (ExecutionException x)
|
||||
{
|
||||
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||
if (aborted.get())
|
||||
Assert.assertSame(cause, x.getCause());
|
||||
}
|
||||
aborted.set(request.abort(cause));
|
||||
latch.countDown();
|
||||
})
|
||||
.content(new ByteBufferContentProvider(ByteBuffer.wrap(new byte[]{0}), ByteBuffer.wrap(new byte[]{1}))
|
||||
{
|
||||
@Override
|
||||
public long getLength()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
})
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (ExecutionException x)
|
||||
{
|
||||
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||
if (aborted.get())
|
||||
Assert.assertSame(cause, x.getCause());
|
||||
}
|
||||
|
||||
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, "localhost", connector.getLocalPort());
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Assert.assertEquals(0, connectionPool.getConnectionCount());
|
||||
Assert.assertEquals(0, connectionPool.getActiveConnections().size());
|
||||
Assert.assertEquals(0, connectionPool.getIdleConnections().size());
|
||||
Assert.assertTrue(serverLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination(scheme, "localhost", connector.getLocalPort());
|
||||
DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool();
|
||||
Assert.assertEquals(0, connectionPool.getConnectionCount());
|
||||
Assert.assertEquals(0, connectionPool.getActiveConnections().size());
|
||||
Assert.assertEquals(0, connectionPool.getIdleConnections().size());
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InterruptedException.class)
|
||||
|
@ -377,7 +395,8 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
try
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
TimeUnit.MILLISECONDS.sleep(2 * delay);
|
||||
if (request.getDispatcherType() != DispatcherType.ERROR)
|
||||
TimeUnit.MILLISECONDS.sleep(2 * delay);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
|
@ -391,22 +410,18 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
.scheme(scheme);
|
||||
|
||||
final Thread thread = Thread.currentThread();
|
||||
new Thread()
|
||||
new Thread(() ->
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(delay);
|
||||
thread.interrupt();
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
TimeUnit.MILLISECONDS.sleep(delay);
|
||||
thread.interrupt();
|
||||
}
|
||||
}.start();
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
}).start();
|
||||
|
||||
request.send();
|
||||
}
|
||||
|
@ -423,7 +438,8 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
try
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
TimeUnit.MILLISECONDS.sleep(2 * delay);
|
||||
if (request.getDispatcherType() != DispatcherType.ERROR)
|
||||
TimeUnit.MILLISECONDS.sleep(2 * delay);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
|
@ -439,23 +455,19 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
final Throwable cause = new Exception();
|
||||
final AtomicBoolean aborted = new AtomicBoolean();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
new Thread()
|
||||
new Thread(() ->
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
TimeUnit.MILLISECONDS.sleep(delay);
|
||||
aborted.set(request.abort(cause));
|
||||
latch.countDown();
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
TimeUnit.MILLISECONDS.sleep(delay);
|
||||
aborted.set(request.abort(cause));
|
||||
latch.countDown();
|
||||
}
|
||||
}.start();
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
}).start();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -487,7 +499,8 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
|
|||
try
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
TimeUnit.MILLISECONDS.sleep(2 * delay);
|
||||
if (request.getDispatcherType() != DispatcherType.ERROR)
|
||||
TimeUnit.MILLISECONDS.sleep(2 * delay);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>10.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
<name>Jetty :: Distribution Assemblies</name>
|
||||
<url>http://www.eclipse.org/jetty</url>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<assembly-directory>${basedir}/target/distribution</assembly-directory>
|
||||
<home-directory>${basedir}/target/home</home-directory>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!--
|
||||
|
@ -74,7 +77,7 @@
|
|||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>removeKeystore</id>
|
||||
<id>removeKeystore</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
|
@ -393,6 +396,7 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
|
|
@ -49,7 +49,7 @@ This is a permanent redirection, which also preserves `pathinfo` and query strin
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.server.handler.MovedContextHandler">
|
||||
<Set name="contextPath">/foo</Set>
|
||||
|
|
|
@ -63,11 +63,11 @@ Here's how you would configure the virtual hosts with a link:#deployable-descrip
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/blah</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/webapps/blah.war</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>blah.war</Set>
|
||||
<Set name="virtualHosts">
|
||||
<Array type="java.lang.String">
|
||||
<Item>333.444.555.666</Item>
|
||||
|
@ -103,11 +103,11 @@ For `blah` webapp:
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/blah</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/webapps/blah.war</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/blah.war</Set>
|
||||
<Set name="virtualHosts">
|
||||
<Array type="java.lang.String">
|
||||
<Item>www.blah.com</Item>
|
||||
|
@ -129,11 +129,11 @@ For `other` webapp:
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/other</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/webapps/other.war</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/other.war</Set>
|
||||
<Set name="virtualHosts">
|
||||
<Array type="java.lang.String">
|
||||
<Item>www.other.com</Item>
|
||||
|
@ -178,11 +178,11 @@ For foo webapp:
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/webapps/foo.war</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/foo.war</Set>
|
||||
<Set name="virtualHosts">
|
||||
<Array type="java.lang.String">
|
||||
<Item>www.blah.com</Item>
|
||||
|
@ -198,11 +198,11 @@ For bar webapp:
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/webapps/bar.war</Set>
|
||||
<Set name="war"><Property name="jetty.webapps"/>/bar.war</Set>
|
||||
<Set name="virtualHosts">
|
||||
<Array type="java.lang.String">
|
||||
<Item>www.other.com</Item>
|
||||
|
|
|
@ -44,7 +44,7 @@ For example, here is a descriptor file that deploys the file `/opt/myapp/myapp.w
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/wiki</Set>
|
||||
|
@ -58,7 +58,7 @@ For example, if the system property is set to `myapp.home=/opt/myapp`, the previ
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/wiki</Set>
|
||||
|
@ -86,7 +86,7 @@ This can help make it clear that users should not make changes to the temporary
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/wiki</Set>
|
||||
|
@ -102,7 +102,7 @@ However, since the `web.xml` for the web application is processed after the depl
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/wiki</Set>
|
||||
|
@ -123,7 +123,7 @@ This feature is useful when adding parameters or additional Servlet mappings wit
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/wiki</Set>
|
||||
|
@ -138,7 +138,7 @@ If the `web.xml` does not include a reference to this data source, an override d
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/wiki</Set>
|
||||
|
|
|
@ -82,7 +82,7 @@ In the standard Jetty Distribution, this is configured in the `${jetty.home}/etc
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<Call name="addBean">
|
||||
|
|
|
@ -133,7 +133,7 @@ Let's see an example of how we would add in the Configurations for both JNDI _an
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
|
||||
|
@ -165,7 +165,7 @@ They will then be applied to each `WebAppContext` deployed by the deployer:
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
|
@ -209,7 +209,7 @@ This example uses an xml file, in fact it is the `$JETTY_HOME/etc/jetty-plus.xml
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
|
@ -259,7 +259,7 @@ Here's an example from a context xml file (although as always, you could have ac
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
|
||||
|
@ -285,7 +285,7 @@ Here's an example in a xml file of a pattern that matches any jar that starts wi
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ Create a file called `scratch.xml` in the `${jetty.base}/webapps` directory and
|
|||
----
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
|
||||
<Set name="contextPath">/scratch</Set>
|
||||
<Set name="handler">
|
||||
|
|
|
@ -347,7 +347,7 @@ Here's an example of the contents of a `META-INF/jetty-webapp-context.xml` file:
|
|||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="defaultsDescriptor"><Property name="bundle.root"/>META-INF/webdefault.xml</Set>
|
||||
|
@ -789,7 +789,7 @@ To set the pattern, you will need to provide your own etc files - see the sectio
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
|
|
|
@ -145,7 +145,7 @@ The deployer discovers and hot deploys context IoC descriptors like the followin
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC
|
||||
"-//Mort Bay Consulting//DTD Configure//EN"
|
||||
"http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
"http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!--
|
||||
Configure a custom context for serving javadoc as static resources
|
||||
|
@ -206,7 +206,7 @@ To set the contextPath from within the WAR file, you can include a `WEB-INF/jett
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC
|
||||
"-//Mort Bay Consulting//DTD Configure//EN"
|
||||
"http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
"http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/contextpath</Set>
|
||||
|
@ -221,7 +221,7 @@ Instead of allowing the WAR file to be discovered by the deployer, an IoC XML fi
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC
|
||||
"-//Mort Bay Consulting//DTD Configure//EN"
|
||||
"http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
"http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/test.war</Set>
|
||||
|
|
|
@ -87,7 +87,7 @@ The first two lines of an XML must reference the DTD to be used to validate the
|
|||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
...
|
||||
----
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.eclipse.jetty.http2.HTTP2Cipher;
|
|||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
|
@ -54,7 +53,6 @@ public class DrupalHTTP2FastCGIProxyServer
|
|||
|
||||
// HTTP2 factory
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(https_config);
|
||||
NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(h2.getProtocol());
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.eclipse.jetty.http2.HTTP2Cipher;
|
|||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
|
@ -61,7 +60,6 @@ public class WordPressHTTP2FastCGIProxyServer
|
|||
|
||||
// HTTP2 factory
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(https_config);
|
||||
NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(h2.getProtocol());
|
||||
|
||||
|
|
|
@ -590,4 +590,21 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jdk9</id>
|
||||
<activation>
|
||||
<jdk>[1.9,)</jdk>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-java-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -156,6 +156,7 @@ public class HttpParser
|
|||
private int _responseStatus;
|
||||
private int _headerBytes;
|
||||
private boolean _host;
|
||||
private boolean _headerComplete;
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
private volatile State _state=State.START;
|
||||
|
@ -730,6 +731,7 @@ public class HttpParser
|
|||
setState(State.END);
|
||||
BufferUtil.clear(buffer);
|
||||
handle=_handler.headerComplete()||handle;
|
||||
_headerComplete=true;
|
||||
handle=_handler.messageComplete()||handle;
|
||||
return handle;
|
||||
}
|
||||
|
@ -800,6 +802,7 @@ public class HttpParser
|
|||
setState(State.END);
|
||||
BufferUtil.clear(buffer);
|
||||
handle=_handler.headerComplete()||handle;
|
||||
_headerComplete=true;
|
||||
handle=_handler.messageComplete()||handle;
|
||||
return handle;
|
||||
}
|
||||
|
@ -1057,22 +1060,26 @@ public class HttpParser
|
|||
case EOF_CONTENT:
|
||||
setState(State.EOF_CONTENT);
|
||||
handle=_handler.headerComplete()||handle;
|
||||
_headerComplete=true;
|
||||
return handle;
|
||||
|
||||
case CHUNKED_CONTENT:
|
||||
setState(State.CHUNKED_CONTENT);
|
||||
handle=_handler.headerComplete()||handle;
|
||||
_headerComplete=true;
|
||||
return handle;
|
||||
|
||||
case NO_CONTENT:
|
||||
setState(State.END);
|
||||
handle=_handler.headerComplete()||handle;
|
||||
_headerComplete=true;
|
||||
handle=_handler.messageComplete()||handle;
|
||||
return handle;
|
||||
|
||||
default:
|
||||
setState(State.CONTENT);
|
||||
handle=_handler.headerComplete()||handle;
|
||||
_headerComplete=true;
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
@ -1426,39 +1433,30 @@ public class HttpParser
|
|||
LOG.warn("parse exception: {} in {} for {}",e.toString(),_state,_handler);
|
||||
if (DEBUG)
|
||||
LOG.debug(e);
|
||||
badMessage();
|
||||
|
||||
switch(_state)
|
||||
{
|
||||
case CLOSED:
|
||||
break;
|
||||
case CLOSE:
|
||||
_handler.earlyEOF();
|
||||
break;
|
||||
default:
|
||||
setState(State.CLOSE);
|
||||
_handler.badMessage(400,"Bad Message "+e.toString());
|
||||
}
|
||||
}
|
||||
catch(Exception|Error e)
|
||||
{
|
||||
BufferUtil.clear(buffer);
|
||||
|
||||
LOG.warn("parse exception: "+e.toString()+" for "+_handler,e);
|
||||
|
||||
switch(_state)
|
||||
{
|
||||
case CLOSED:
|
||||
break;
|
||||
case CLOSE:
|
||||
_handler.earlyEOF();
|
||||
break;
|
||||
default:
|
||||
setState(State.CLOSE);
|
||||
_handler.badMessage(400,null);
|
||||
}
|
||||
badMessage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void badMessage()
|
||||
{
|
||||
if (_headerComplete)
|
||||
{
|
||||
_handler.earlyEOF();
|
||||
}
|
||||
else if (_state!=State.CLOSED)
|
||||
{
|
||||
setState(State.CLOSE);
|
||||
_handler.badMessage(400,_requestHandler!=null?"Bad Request":"Bad Response");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean parseContent(ByteBuffer buffer)
|
||||
{
|
||||
|
@ -1677,6 +1675,7 @@ public class HttpParser
|
|||
_contentChunk=null;
|
||||
_headerBytes=0;
|
||||
_host=false;
|
||||
_headerComplete=false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
|
|
@ -49,22 +49,36 @@
|
|||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar
|
||||
</argLine>
|
||||
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>jdk9</id>
|
||||
<activation>
|
||||
<jdk>[1.9,)</jdk>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
<version>${alpn.api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-server</artifactId>
|
||||
|
|
|
@ -51,11 +51,12 @@ import org.eclipse.jetty.http2.api.server.ServerSessionListener;
|
|||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.http2.frames.ResetFrame;
|
||||
import org.eclipse.jetty.server.HttpChannel;
|
||||
import org.eclipse.jetty.server.HttpOutput;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.FutureCallback;
|
||||
import org.eclipse.jetty.util.FuturePromise;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.StacklessLogging;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
|
@ -409,7 +410,7 @@ public class StreamResetTest extends AbstractTest
|
|||
@Test
|
||||
public void testServerExceptionConsumesQueuedData() throws Exception
|
||||
{
|
||||
try (StacklessLogging suppressor = new StacklessLogging(ServletHandler.class))
|
||||
try (StacklessLogging suppressor = new StacklessLogging(HttpChannel.class))
|
||||
{
|
||||
start(new HttpServlet()
|
||||
{
|
||||
|
@ -430,6 +431,8 @@ public class StreamResetTest extends AbstractTest
|
|||
});
|
||||
|
||||
Session client = newClient(new Session.Listener.Adapter());
|
||||
|
||||
Log.getLogger(HttpChannel.class).info("Expecting java.lang.IllegalStateException: explictly_thrown_by_test");
|
||||
MetaData.Request request = newRequest("GET", new HttpFields());
|
||||
HeadersFrame frame = new HeadersFrame(request, null, false);
|
||||
FuturePromise<Stream> promise = new FuturePromise<>();
|
||||
|
|
|
@ -49,8 +49,7 @@
|
|||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar
|
||||
</argLine>
|
||||
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.io.EOFException;
|
|||
* the connection, vs and EOF thrown by some application talking to some other file/socket etc.
|
||||
* The only difference in handling is that Jetty EOFs are logged less verbosely.
|
||||
*/
|
||||
public class EofException extends EOFException
|
||||
public class EofException extends EOFException implements QuietException
|
||||
{
|
||||
public EofException()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.io;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** A Quiet Exception.
|
||||
* <p> Exception classes that extend this interface will be logged
|
||||
* less verbosely.
|
||||
*/
|
||||
public interface QuietException
|
||||
{
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.io.ssl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
public interface ALPNProcessor
|
||||
{
|
||||
public interface Server
|
||||
{
|
||||
public static final ALPNProcessor.Server NOOP = new ALPNProcessor.Server()
|
||||
{
|
||||
};
|
||||
|
||||
public default void configure(SSLEngine sslEngine)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public interface Client
|
||||
{
|
||||
public static final Client NOOP = new Client()
|
||||
{
|
||||
};
|
||||
|
||||
public default void configure(SSLEngine sslEngine, List<String> protocols)
|
||||
{
|
||||
}
|
||||
|
||||
public default void process(SSLEngine sslEngine)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,11 +63,11 @@ public class SslClientConnectionFactory implements ClientConnectionFactory
|
|||
SslConnection sslConnection = newSslConnection(byteBufferPool, executor, endPoint, engine);
|
||||
endPoint.setConnection(sslConnection);
|
||||
|
||||
customize(sslConnection, context);
|
||||
|
||||
EndPoint appEndPoint = sslConnection.getDecryptedEndPoint();
|
||||
appEndPoint.setConnection(connectionFactory.newConnection(appEndPoint, context));
|
||||
|
||||
customize(sslConnection, context);
|
||||
|
||||
return sslConnection;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>10.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-project</artifactId>
|
||||
<name>Jetty :: OSGi</name>
|
||||
<url>http://www.eclipse.org/jetty</url>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<osgi-version>3.6.0.v20100517</osgi-version>
|
||||
<osgi-services-version>3.2.100.v20100503</osgi-services-version>
|
||||
|
@ -18,6 +22,7 @@
|
|||
<logback-version>0.9.29</logback-version>
|
||||
<slf4j-version>1.6.1</slf4j-version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>jetty-osgi-boot</module>
|
||||
<module>jetty-osgi-boot-jsp</module>
|
||||
|
@ -28,8 +33,20 @@
|
|||
<module>test-jetty-osgi-fragment</module>
|
||||
<module>test-jetty-osgi-server</module>
|
||||
<module>jetty-osgi-alpn</module>
|
||||
<module>test-jetty-osgi</module>
|
||||
</modules>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jdk9</id>
|
||||
<activation>
|
||||
<jdk>[1.8,1.9)</jdk>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>test-jetty-osgi</module>
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
|
@ -79,6 +96,7 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -180,4 +198,5 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION;
|
||||
import static javax.servlet.RequestDispatcher.ERROR_STATUS_CODE;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -39,6 +42,7 @@ import org.eclipse.jetty.http.MetaData;
|
|||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ChannelEndPoint;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.QuietException;
|
||||
import org.eclipse.jetty.io.RuntimeIOException;
|
||||
import org.eclipse.jetty.server.HttpChannelState.Action;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
|
@ -50,9 +54,6 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION;
|
||||
import static javax.servlet.RequestDispatcher.ERROR_STATUS_CODE;
|
||||
|
||||
|
||||
/**
|
||||
* HttpChannel represents a single endpoint for HTTP semantic processing.
|
||||
|
@ -484,7 +485,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
if (failure instanceof RuntimeIOException)
|
||||
failure = failure.getCause();
|
||||
|
||||
if (failure instanceof QuietServletException || !getServer().isRunning())
|
||||
if (failure instanceof QuietException || !getServer().isRunning())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(_request.getRequestURI(), failure);
|
||||
|
|
|
@ -216,11 +216,15 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque
|
|||
@Override
|
||||
public void earlyEOF()
|
||||
{
|
||||
_httpConnection.getGenerator().setPersistent(false);
|
||||
// If we have no request yet, just close
|
||||
if (_metadata.getMethod() == null)
|
||||
_httpConnection.close();
|
||||
else if (onEarlyEOF())
|
||||
else if (onEarlyEOF() || _delayedForContent)
|
||||
{
|
||||
_delayedForContent = false;
|
||||
handle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -34,23 +33,25 @@ import org.eclipse.jetty.io.ssl.SslConnection;
|
|||
public abstract class NegotiatingServerConnectionFactory extends AbstractConnectionFactory
|
||||
{
|
||||
public static void checkProtocolNegotiationAvailable()
|
||||
{
|
||||
if (!isAvailableInBootClassPath("org.eclipse.jetty.alpn.ALPN"))
|
||||
throw new IllegalStateException("No ALPN classes available");
|
||||
}
|
||||
|
||||
private static boolean isAvailableInBootClassPath(String className)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> klass = ClassLoader.getSystemClassLoader().loadClass(className);
|
||||
if (klass.getClassLoader() != null)
|
||||
throw new IllegalStateException(className + " must be on JVM boot classpath");
|
||||
return true;
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
String alpnClassName = "org.eclipse.jetty.alpn.ALPN";
|
||||
if (javaVersion.startsWith("1."))
|
||||
{
|
||||
Class<?> klass = ClassLoader.getSystemClassLoader().loadClass(alpnClassName);
|
||||
if (klass.getClassLoader() != null)
|
||||
throw new IllegalStateException(alpnClassName + " must be on JVM boot classpath");
|
||||
}
|
||||
else
|
||||
{
|
||||
NegotiatingServerConnectionFactory.class.getClassLoader().loadClass(alpnClassName);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException x)
|
||||
{
|
||||
return false;
|
||||
throw new IllegalStateException("No ALPN classes available");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.eclipse.jetty.server;
|
|||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.eclipse.jetty.io.QuietException;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** A ServletException that is logged less verbosely than
|
||||
|
@ -29,7 +31,7 @@ import javax.servlet.ServletException;
|
|||
* than a stack trace.
|
||||
* </p>
|
||||
*/
|
||||
public class QuietServletException extends ServletException
|
||||
public class QuietServletException extends ServletException implements QuietException
|
||||
{
|
||||
public QuietServletException()
|
||||
{
|
||||
|
|
|
@ -399,7 +399,20 @@ public class ResourceService
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("welcome={}",welcome);
|
||||
if (_redirectWelcome)
|
||||
|
||||
RequestDispatcher dispatcher=_redirectWelcome?null:request.getRequestDispatcher(welcome);
|
||||
if (dispatcher!=null)
|
||||
{
|
||||
// Forward to the index
|
||||
if (included)
|
||||
dispatcher.include(request,response);
|
||||
else
|
||||
{
|
||||
request.setAttribute("org.eclipse.jetty.server.welcome",welcome);
|
||||
dispatcher.forward(request,response);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Redirect to the index
|
||||
response.setContentLength(0);
|
||||
|
@ -409,21 +422,6 @@ public class ResourceService
|
|||
else
|
||||
response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(),welcome)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Forward to the index
|
||||
RequestDispatcher dispatcher=request.getRequestDispatcher(welcome);
|
||||
if (dispatcher!=null)
|
||||
{
|
||||
if (included)
|
||||
dispatcher.include(request,response);
|
||||
else
|
||||
{
|
||||
request.setAttribute("org.eclipse.jetty.server.welcome",welcome);
|
||||
dispatcher.forward(request,response);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -394,6 +394,7 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory,W
|
|||
_resourceService.setCacheControl(new PreEncodedHttpField(HttpHeader.CACHE_CONTROL,cacheControl));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param dirAllowed
|
||||
* If true, directory listings are returned if no welcome file is found. Else 403 Forbidden.
|
||||
|
@ -486,6 +487,7 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory,W
|
|||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param pathInfoOnly
|
||||
* true, only the path info will be applied to the resourceBase
|
||||
|
@ -495,9 +497,12 @@ public class ResourceHandler extends HandlerWrapper implements ResourceFactory,W
|
|||
_resourceService.setPathInfoOnly(pathInfoOnly);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param redirectWelcome
|
||||
* If true, welcome files are redirected rather than forwarded to.
|
||||
* redirection is always used if the ResourceHandler is not scoped by
|
||||
* a ContextHandler
|
||||
*/
|
||||
public void setRedirectWelcome(boolean redirectWelcome)
|
||||
{
|
||||
|
|
|
@ -298,6 +298,7 @@ public class AsyncRequestReadTest
|
|||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
assertThat(in.readLine(),containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(in.readLine(),containsString("Content-Length:"));
|
||||
assertThat(in.readLine(),containsString("Connection: close"));
|
||||
assertThat(in.readLine(),containsString("Server:"));
|
||||
in.readLine();
|
||||
assertThat(in.readLine(),containsString("XXXXXXX"));
|
||||
|
|
|
@ -216,7 +216,10 @@ public class DumpHandler extends AbstractHandler.ErrorDispatchHandler
|
|||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.warn(e);
|
||||
else
|
||||
LOG.warn(e.toString());
|
||||
writer.write(e.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -582,16 +582,18 @@ public class HttpConnectionTest
|
|||
checkContains(response,offset,"12345");
|
||||
|
||||
offset=0;
|
||||
Log.getLogger(DumpHandler.class).info("Expecting java.io.UnsupportedEncodingException");
|
||||
response=connector.getResponse("GET /R1 HTTP/1.1\r\n"+
|
||||
"Host: localhost\r\n"+
|
||||
"Transfer-Encoding: chunked\r\n"+
|
||||
"Content-Type: text/plain; charset=unknown\r\n"+
|
||||
"Connection: close\r\n"+
|
||||
"\r\n"+
|
||||
"5;\r\n"+
|
||||
"12345\r\n"+
|
||||
"0;\r\n" +
|
||||
"\r\n");
|
||||
"Host: localhost\r\n"+
|
||||
"Transfer-Encoding: chunked\r\n"+
|
||||
"Content-Type: text/plain; charset=unknown\r\n"+
|
||||
"Connection: close\r\n"+
|
||||
"\r\n"+
|
||||
"5;\r\n"+
|
||||
"12345\r\n"+
|
||||
"0;\r\n" +
|
||||
"\r\n");
|
||||
|
||||
offset = checkContains(response,offset,"HTTP/1.1 200");
|
||||
offset = checkContains(response,offset,"encoding=unknown");
|
||||
offset = checkContains(response,offset,"/R1");
|
||||
|
|
|
@ -49,6 +49,7 @@ import javax.servlet.ServletOutputStream;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
|
@ -695,6 +696,54 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockingReadBadChunk() throws Exception
|
||||
{
|
||||
configureServer(new ReadHandler());
|
||||
|
||||
try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()))
|
||||
{
|
||||
client.setSoTimeout(600000);
|
||||
OutputStream os = client.getOutputStream();
|
||||
InputStream is = client.getInputStream();
|
||||
|
||||
os.write((
|
||||
"GET /data HTTP/1.1\r\n" +
|
||||
"host: " + _serverURI.getHost() + ":" + _serverURI.getPort() + "\r\n" +
|
||||
"content-type: unknown\r\n" +
|
||||
"transfer-encoding: chunked\r\n" +
|
||||
"\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
Thread.sleep(50);
|
||||
os.write((
|
||||
"a\r\n" +
|
||||
"123456890\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
Thread.sleep(50);
|
||||
os.write((
|
||||
"4\r\n" +
|
||||
"abcd\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
Thread.sleep(50);
|
||||
os.write((
|
||||
"X\r\n" +
|
||||
"abcd\r\n"
|
||||
).getBytes());
|
||||
os.flush();
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(HttpTester.from(is));
|
||||
|
||||
assertThat(response.getStatus(),is(200));
|
||||
assertThat(response.getContent(),containsString("EofException"));
|
||||
assertThat(response.getContent(),containsString("Early EOF"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockingWhileWritingResponseContent() throws Exception
|
||||
{
|
||||
|
|
|
@ -186,7 +186,28 @@ public class HttpServerTestFixture
|
|||
response.getOutputStream().print("Hello world\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected static class ReadHandler extends AbstractHandler
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.setStatus(200);
|
||||
|
||||
try
|
||||
{
|
||||
InputStream in = request.getInputStream();
|
||||
String input= IO.toString(in);
|
||||
response.getWriter().printf("read %d%n",input.length());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
response.getWriter().printf("caught %s%n",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class DataHandler extends AbstractHandler
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
|
||||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import static org.eclipse.jetty.http.HttpHeader.CONTENT_LENGTH;
|
||||
import static org.eclipse.jetty.http.HttpHeader.CONTENT_TYPE;
|
||||
import static org.eclipse.jetty.http.HttpHeader.LAST_MODIFIED;
|
||||
import static org.eclipse.jetty.http.HttpHeader.LOCATION;
|
||||
import static org.eclipse.jetty.http.HttpHeader.SERVER;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
|
@ -28,11 +36,11 @@ import java.io.FileOutputStream;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
|
@ -40,7 +48,6 @@ import org.eclipse.jetty.server.LocalConnector;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.SimpleRequest;
|
||||
import org.eclipse.jetty.toolchain.test.annotation.Slow;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -123,6 +130,7 @@ public class ResourceHandlerTest
|
|||
_resourceHandler = new ResourceHandler();
|
||||
|
||||
_resourceHandler.setResourceBase(MavenTestingUtils.getTargetFile("test-classes/simple").getAbsolutePath());
|
||||
_resourceHandler.setWelcomeFiles(new String[]{"welcome.txt"});
|
||||
|
||||
_contextHandler = new ContextHandler("/resource");
|
||||
_contextHandler.setHandler(_resourceHandler);
|
||||
|
@ -143,59 +151,75 @@ public class ResourceHandlerTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testJettyDirCss() throws Exception
|
||||
public void testJettyDirRedirect() throws Exception
|
||||
{
|
||||
SimpleRequest sr = new SimpleRequest(new URI("http://localhost:" + _connector.getLocalPort()));
|
||||
Assert.assertNotNull(sr.getString("/resource/jetty-dir.css"));
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(302));
|
||||
assertThat(response.get(LOCATION),containsString("/resource/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimple() throws Exception
|
||||
public void testJettyDirListing() throws Exception
|
||||
{
|
||||
SimpleRequest sr = new SimpleRequest(new URI("http://localhost:" + _connector.getLocalPort()));
|
||||
Assert.assertEquals("simple text",sr.getString("/resource/simple.txt"));
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource/ HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(200));
|
||||
assertThat(response.getContent(),containsString("jetty-dir.css"));
|
||||
assertThat(response.getContent(),containsString("<H1>Directory: /resource/"));
|
||||
assertThat(response.getContent(),containsString("big.txt"));
|
||||
assertThat(response.getContent(),containsString("bigger.txt"));
|
||||
assertThat(response.getContent(),containsString("directory"));
|
||||
assertThat(response.getContent(),containsString("simple.txt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeaders() throws Exception
|
||||
{
|
||||
String response = _local.getResponses("GET /resource/simple.txt HTTP/1.0\r\n\r\n");
|
||||
assertThat(response,startsWith("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.containsString("Content-Type: text/plain"));
|
||||
assertThat(response,Matchers.containsString("Last-Modified: "));
|
||||
assertThat(response,Matchers.containsString("Content-Length: 11"));
|
||||
assertThat(response,Matchers.containsString("Server: Jetty"));
|
||||
assertThat(response,Matchers.containsString("simple text"));
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource/simple.txt HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(200));
|
||||
assertThat(response.get(CONTENT_TYPE),equalTo("text/plain"));
|
||||
assertThat(response.get(LAST_MODIFIED),Matchers.notNullValue());
|
||||
assertThat(response.get(CONTENT_LENGTH),equalTo("11"));
|
||||
assertThat(response.get(SERVER),containsString("Jetty"));
|
||||
assertThat(response.getContent(),containsString("simple text"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigFile() throws Exception
|
||||
{
|
||||
_config.setOutputBufferSize(2048);
|
||||
SimpleRequest sr = new SimpleRequest(new URI("http://localhost:" + _connector.getLocalPort()));
|
||||
String response = sr.getString("/resource/big.txt");
|
||||
Assert.assertThat(response,Matchers.startsWith(" 1\tThis is a big file"));
|
||||
Assert.assertThat(response,Matchers.endsWith(" 400\tThis is a big file" + LN));
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource/big.txt HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(200));
|
||||
assertThat(response.getContent(),startsWith(" 1\tThis is a big file"));
|
||||
assertThat(response.getContent(),endsWith(" 400\tThis is a big file" + LN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigFileBigBuffer() throws Exception
|
||||
{
|
||||
_config.setOutputBufferSize(16 * 1024);
|
||||
SimpleRequest sr = new SimpleRequest(new URI("http://localhost:" + _connector.getLocalPort()));
|
||||
String response = sr.getString("/resource/big.txt");
|
||||
Assert.assertThat(response,Matchers.startsWith(" 1\tThis is a big file"));
|
||||
Assert.assertThat(response,Matchers.endsWith(" 400\tThis is a big file" + LN));
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource/big.txt HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(200));
|
||||
assertThat(response.getContent(),startsWith(" 1\tThis is a big file"));
|
||||
assertThat(response.getContent(),endsWith(" 400\tThis is a big file" + LN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigFileLittleBuffer() throws Exception
|
||||
{
|
||||
_config.setOutputBufferSize(8);
|
||||
SimpleRequest sr = new SimpleRequest(new URI("http://localhost:" + _connector.getLocalPort()));
|
||||
String response = sr.getString("/resource/big.txt");
|
||||
Assert.assertThat(response,Matchers.startsWith(" 1\tThis is a big file"));
|
||||
Assert.assertThat(response,Matchers.endsWith(" 400\tThis is a big file" + LN));
|
||||
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource/big.txt HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(200));
|
||||
assertThat(response.getContent(),startsWith(" 1\tThis is a big file"));
|
||||
assertThat(response.getContent(),endsWith(" 400\tThis is a big file" + LN));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -212,6 +236,32 @@ public class ResourceHandlerTest
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWelcome() throws Exception
|
||||
{
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource/directory/ HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(200));
|
||||
assertThat(response.getContent(),containsString("Hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWelcomeRedirect() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
_resourceHandler.setRedirectWelcome(true);
|
||||
HttpTester.Response response = HttpTester.parseResponse(
|
||||
_local.getResponse("GET /resource/directory/ HTTP/1.0\r\n\r\n"));
|
||||
assertThat(response.getStatus(),equalTo(302));
|
||||
assertThat(response.get(LOCATION),containsString("/resource/welcome.txt"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_resourceHandler.setRedirectWelcome(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Slow
|
||||
public void testSlowBiggest() throws Exception
|
||||
|
@ -235,12 +285,10 @@ public class ResourceHandlerTest
|
|||
|
||||
try (Socket socket = new Socket("localhost",_connector.getLocalPort());OutputStream out=socket.getOutputStream();InputStream in=socket.getInputStream())
|
||||
{
|
||||
|
||||
socket.getOutputStream().write("GET /resource/biggest.txt HTTP/1.0\n\n".getBytes());
|
||||
|
||||
byte[] array = new byte[102400];
|
||||
ByteBuffer buffer=null;
|
||||
int i=0;
|
||||
while(true)
|
||||
{
|
||||
Thread.sleep(100);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
content
|
|
@ -0,0 +1 @@
|
|||
Hello
|
|
@ -162,11 +162,8 @@ public class PostServletTest
|
|||
req.append("\r\n");
|
||||
req.append("\r\n");
|
||||
|
||||
try (StacklessLogging scope = new StacklessLogging(ServletHandler.class))
|
||||
{
|
||||
String resp = connector.getResponses(req.toString());
|
||||
assertThat(resp,is("")); // Aborted before response committed
|
||||
}
|
||||
String resp = connector.getResponse(req.toString());
|
||||
assertThat(resp,startsWith("HTTP/1.1 200 OK")); // exception eaten by handler
|
||||
assertTrue(complete.await(5,TimeUnit.SECONDS));
|
||||
assertThat(ex0.get(),not(nullValue()));
|
||||
assertThat(ex1.get(),not(nullValue()));
|
||||
|
@ -181,31 +178,26 @@ public class PostServletTest
|
|||
req.append("Transfer-Encoding: chunked\r\n");
|
||||
req.append("\r\n");
|
||||
|
||||
try (StacklessLogging scope = new StacklessLogging(ServletHandler.class))
|
||||
{
|
||||
LocalConnector.LocalEndPoint endp=connector.executeRequest(req.toString());
|
||||
Thread.sleep(1000);
|
||||
assertFalse(posted.get());
|
||||
LocalConnector.LocalEndPoint endp=connector.executeRequest(req.toString());
|
||||
Thread.sleep(1000);
|
||||
assertFalse(posted.get());
|
||||
|
||||
req.setLength(0);
|
||||
// intentionally bad (not a valid chunked char here)
|
||||
for (int i=1024;i-->0;)
|
||||
req.append("xxxxxxxxxxxx");
|
||||
req.append("\r\n");
|
||||
req.append("\r\n");
|
||||
req.setLength(0);
|
||||
// intentionally bad (not a valid chunked char here)
|
||||
for (int i=1024;i-->0;)
|
||||
req.append("xxxxxxxxxxxx");
|
||||
req.append("\r\n");
|
||||
req.append("\r\n");
|
||||
|
||||
endp.addInput(req.toString());
|
||||
endp.addInput(req.toString());
|
||||
|
||||
endp.waitUntilClosedOrIdleFor(1,TimeUnit.SECONDS);
|
||||
String resp = endp.takeOutputString();
|
||||
endp.waitUntilClosedOrIdleFor(1,TimeUnit.SECONDS);
|
||||
String resp = endp.takeOutputString();
|
||||
|
||||
assertThat("resp", resp, containsString("HTTP/1.1 400 "));
|
||||
|
||||
}
|
||||
|
||||
// null because it was never dispatched!
|
||||
assertThat(ex0.get(),nullValue());
|
||||
assertThat(ex1.get(),nullValue());
|
||||
assertThat(resp,startsWith("HTTP/1.1 200 OK")); // exception eaten by handler
|
||||
assertTrue(complete.await(5,TimeUnit.SECONDS));
|
||||
assertThat(ex0.get(),not(nullValue()));
|
||||
assertThat(ex1.get(),not(nullValue()));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public class DataRateLimitedServletTest
|
|||
context.setContextPath("/context");
|
||||
context.setWelcomeFiles(new String[]{"index.html", "index.jsp", "index.htm"});
|
||||
|
||||
File baseResourceDir = testdir.getEmptyDir();
|
||||
File baseResourceDir = testdir.getEmptyPathDir().toFile();
|
||||
// Use resolved real path for Windows and OSX
|
||||
Path baseResourcePath = baseResourceDir.toPath().toRealPath();
|
||||
|
||||
|
@ -91,7 +91,7 @@ public class DataRateLimitedServletTest
|
|||
@Test
|
||||
public void testStream() throws Exception
|
||||
{
|
||||
File content = testdir.getFile("content.txt");
|
||||
File content = testdir.getPathFile("content.txt").toFile();
|
||||
String[] results=new String[10];
|
||||
try(OutputStream out = new FileOutputStream(content);)
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ public class DataRateLimitedServletTest
|
|||
}
|
||||
|
||||
long start=System.currentTimeMillis();
|
||||
String response = connector.getResponses("GET /context/stream/content.txt HTTP/1.0\r\n\r\n");
|
||||
String response = connector.getResponse("GET /context/stream/content.txt HTTP/1.0\r\n\r\n");
|
||||
long duration=System.currentTimeMillis()-start;
|
||||
|
||||
assertThat("Response",response,containsString("200 OK"));
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.start;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class JavaVersion
|
||||
{
|
||||
private static final Pattern PRE_JDK9 = Pattern.compile("1\\.(\\d)(\\.(\\d+)(_(\\d+))?)?(-.+)?");
|
||||
// Regexp from JEP 223 (http://openjdk.java.net/jeps/223).
|
||||
private static final Pattern JDK9 = Pattern.compile("(\\d+)(\\.(\\d+))?(\\.(\\d+))?((-.+)?(\\+(\\d+)?(-.+)?)?)");
|
||||
|
||||
public static JavaVersion parse(String version)
|
||||
{
|
||||
if (version.startsWith("1."))
|
||||
return parsePreJDK9(version);
|
||||
return parseJDK9(version);
|
||||
}
|
||||
|
||||
private static JavaVersion parsePreJDK9(String version)
|
||||
{
|
||||
Matcher matcher = PRE_JDK9.matcher(version);
|
||||
if (!matcher.matches())
|
||||
throw new IllegalArgumentException("Invalid Java version " + version);
|
||||
int major = 1;
|
||||
int minor = Integer.parseInt(matcher.group(1));
|
||||
String microGroup = matcher.group(3);
|
||||
int micro = microGroup == null || microGroup.isEmpty() ? 0 : Integer.parseInt(microGroup);
|
||||
String updateGroup = matcher.group(5);
|
||||
int update = updateGroup == null || updateGroup.isEmpty() ? 0 : Integer.parseInt(updateGroup);
|
||||
String suffix = matcher.group(6);
|
||||
return new JavaVersion(version, minor, major, minor, micro, update, suffix);
|
||||
}
|
||||
|
||||
private static JavaVersion parseJDK9(String version)
|
||||
{
|
||||
Matcher matcher = JDK9.matcher(version);
|
||||
if (!matcher.matches())
|
||||
throw new IllegalArgumentException("Invalid Java version " + version);
|
||||
int major = Integer.parseInt(matcher.group(1));
|
||||
String minorGroup = matcher.group(3);
|
||||
int minor = minorGroup == null || minorGroup.isEmpty() ? 0 : Integer.parseInt(minorGroup);
|
||||
String microGroup = matcher.group(5);
|
||||
int micro = microGroup == null || microGroup.isEmpty() ? 0 : Integer.parseInt(microGroup);
|
||||
String suffix = matcher.group(6);
|
||||
return new JavaVersion(version, major, major, minor, micro, 0, suffix);
|
||||
}
|
||||
|
||||
private final String version;
|
||||
private final int platform;
|
||||
private final int major;
|
||||
private final int minor;
|
||||
private final int micro;
|
||||
private final int update;
|
||||
private final String suffix;
|
||||
|
||||
private JavaVersion(String version, int platform, int major, int minor, int micro, int update, String suffix)
|
||||
{
|
||||
this.version = version;
|
||||
this.platform = platform;
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
this.micro = micro;
|
||||
this.update = update;
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the string from which this JavaVersion was created
|
||||
*/
|
||||
public String getVersion()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the Java Platform version, such as {@code 8} for JDK 1.8.0_92 and {@code 9} for JDK 9.2.4.</p>
|
||||
*
|
||||
* @return the Java Platform version
|
||||
*/
|
||||
public int getPlatform()
|
||||
{
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the major number version, such as {@code 1} for JDK 1.8.0_92 and {@code 9} for JDK 9.2.4.</p>
|
||||
*
|
||||
* @return the major number version
|
||||
*/
|
||||
public int getMajor()
|
||||
{
|
||||
return major;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the minor number version, such as {@code 8} for JDK 1.8.0_92 and {@code 2} for JDK 9.2.4.</p>
|
||||
*
|
||||
* @return the minor number version
|
||||
*/
|
||||
public int getMinor()
|
||||
{
|
||||
return minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the micro number version, such as {@code 0} for JDK 1.8.0_92 and {@code 4} for JDK 9.2.4.</p>
|
||||
*
|
||||
* @return the micro number version
|
||||
*/
|
||||
public int getMicro()
|
||||
{
|
||||
return micro;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the update number version, such as {@code 92} for JDK 1.8.0_92 and {@code 0} for JDK 9.2.4.</p>
|
||||
*
|
||||
* @return the update number version
|
||||
*/
|
||||
public int getUpdate()
|
||||
{
|
||||
return update;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the remaining string after the version numbers, such as {@code -internal} for
|
||||
* JDK 1.8.0_92-internal and {@code -ea} for JDK 9-ea, or {@code +13} for JDK 9.2.4+13.</p>
|
||||
*
|
||||
* @return the remaining string after the version numbers
|
||||
*/
|
||||
public String getSuffix()
|
||||
{
|
||||
return suffix;
|
||||
}
|
||||
}
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.eclipse.jetty.start.UsageException.ERR_BAD_ARG;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -180,7 +178,6 @@ public class StartArgs
|
|||
private boolean createStartd = false;
|
||||
private boolean updateIni = false;
|
||||
|
||||
|
||||
private boolean exec = false;
|
||||
private String exec_properties;
|
||||
private boolean approveAllLicenses = false;
|
||||
|
@ -438,7 +435,7 @@ public class StartArgs
|
|||
}
|
||||
|
||||
/**
|
||||
* Expand any command line added <code>--lib</code> lib references.
|
||||
* Expand any command line added {@code --lib} lib references.
|
||||
*
|
||||
* @throws IOException
|
||||
* if unable to expand the libraries
|
||||
|
@ -861,7 +858,7 @@ public class StartArgs
|
|||
Path commands = baseHome.getPath(Props.getValue(arg));
|
||||
|
||||
if (!Files.exists(commands) || !Files.isReadable(commands))
|
||||
throw new UsageException(ERR_BAD_ARG,"--commands file must be readable: %s",commands);
|
||||
throw new UsageException(UsageException.ERR_BAD_ARG,"--commands file must be readable: %s",commands);
|
||||
try
|
||||
{
|
||||
TextFile file = new TextFile(commands);
|
||||
|
@ -947,7 +944,7 @@ public class StartArgs
|
|||
{
|
||||
exec_properties = Props.getValue(arg);
|
||||
if (!exec_properties.endsWith(".properties"))
|
||||
throw new UsageException(ERR_BAD_ARG,"--exec-properties filename must have .properties suffix: %s",exec_properties);
|
||||
throw new UsageException(UsageException.ERR_BAD_ARG,"--exec-properties filename must have .properties suffix: %s",exec_properties);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1112,7 +1109,6 @@ public class StartArgs
|
|||
key = key.substring(0,key.length() - 1);
|
||||
if (getProperties().containsKey(key))
|
||||
return;
|
||||
|
||||
}
|
||||
else if (propertySource.containsKey(key))
|
||||
{
|
||||
|
@ -1147,7 +1143,7 @@ public class StartArgs
|
|||
}
|
||||
|
||||
// Anything else is unrecognized
|
||||
throw new UsageException(ERR_BAD_ARG,"Unrecognized argument: \"%s\" in %s",arg,source);
|
||||
throw new UsageException(UsageException.ERR_BAD_ARG,"Unrecognized argument: \"%s\" in %s",arg,source);
|
||||
}
|
||||
|
||||
private void enableModules(String source, List<String> moduleNames)
|
||||
|
@ -1158,7 +1154,7 @@ public class StartArgs
|
|||
List<String> list = sources.get(moduleName);
|
||||
if (list == null)
|
||||
{
|
||||
list = new ArrayList<String>();
|
||||
list = new ArrayList<>();
|
||||
sources.put(moduleName,list);
|
||||
}
|
||||
list.add(source);
|
||||
|
@ -1219,13 +1215,20 @@ public class StartArgs
|
|||
properties.setProperty(key,value,source);
|
||||
if (key.equals("java.version"))
|
||||
{
|
||||
Version ver = new Version(value);
|
||||
|
||||
properties.setProperty("java.version",ver.toShortString(),source);
|
||||
properties.setProperty("java.version.major",Integer.toString(ver.getLegacyMajor()),source);
|
||||
properties.setProperty("java.version.minor",Integer.toString(ver.getMajor()),source);
|
||||
properties.setProperty("java.version.revision",Integer.toString(ver.getRevision()),source);
|
||||
properties.setProperty("java.version.update",Integer.toString(ver.getUpdate()),source);
|
||||
try
|
||||
{
|
||||
JavaVersion ver = JavaVersion.parse(value);
|
||||
properties.setProperty("java.version",ver.getVersion(),source);
|
||||
properties.setProperty("java.version.platform",Integer.toString(ver.getPlatform()),source);
|
||||
properties.setProperty("java.version.major",Integer.toString(ver.getMajor()),source);
|
||||
properties.setProperty("java.version.minor",Integer.toString(ver.getMinor()),source);
|
||||
properties.setProperty("java.version.micro",Integer.toString(ver.getMicro()),source);
|
||||
properties.setProperty("java.version.update",Integer.toString(ver.getUpdate()),source);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
throw new UsageException(UsageException.ERR_BAD_ARG, x.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1249,5 +1252,4 @@ public class StartArgs
|
|||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public class TestBadUseCases
|
|||
List<Object[]> ret = new ArrayList<>();
|
||||
|
||||
ret.add(new Object[]{ "http2",
|
||||
"Missing referenced dependency: alpn-impl/alpn-0.0.0_0",
|
||||
"Invalid Java version",
|
||||
new String[]{"java.version=0.0.0_0"}});
|
||||
|
||||
ret.add(new Object[]{ "versioned-modules-too-new",
|
||||
|
|
|
@ -105,7 +105,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
|||
|
||||
this.scopeDelegate = scope;
|
||||
client = new WebSocketClient(scope,
|
||||
new JsrEventDriverFactory(scope.getPolicy()),
|
||||
new JsrEventDriverFactory(scope),
|
||||
new JsrSessionFactory(this));
|
||||
client.getSslContextFactory().setTrustAll(trustAll);
|
||||
addBean(client);
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.jsr356.endpoints;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
|
||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||
import org.eclipse.jetty.websocket.jsr356.client.JsrClientEndpointImpl;
|
||||
|
||||
public class JsrEventDriverFactory extends EventDriverFactory
|
||||
{
|
||||
public JsrEventDriverFactory(WebSocketPolicy policy)
|
||||
public JsrEventDriverFactory(WebSocketContainerScope containerScope)
|
||||
{
|
||||
super(policy);
|
||||
super(containerScope);
|
||||
|
||||
clearImplementations();
|
||||
// Classes that extend javax.websocket.Endpoint
|
||||
|
|
|
@ -60,9 +60,6 @@ public class OnPartialTest
|
|||
policy.setMaxBinaryMessageBufferSize(1024);
|
||||
policy.setMaxTextMessageBufferSize(1024);
|
||||
|
||||
// Event Driver Factory
|
||||
EventDriverFactory factory = new EventDriverFactory(policy);
|
||||
factory.addImplementation(new JsrServerEndpointImpl());
|
||||
|
||||
// Create EventDriver
|
||||
EventDriverImpl driverImpl = new JsrServerEndpointImpl();
|
||||
|
@ -71,6 +68,9 @@ public class OnPartialTest
|
|||
Assert.assertThat("Endpoint: " + endpoint + " should be annotated with @ServerEndpoint",anno,notNullValue());
|
||||
|
||||
WebSocketContainerScope containerScope = new SimpleContainerScope(policy);
|
||||
// Event Driver Factory
|
||||
EventDriverFactory factory = new EventDriverFactory(containerScope);
|
||||
factory.addImplementation(new JsrServerEndpointImpl());
|
||||
|
||||
ServerEndpointConfig config = new BasicServerEndpointConfig(containerScope,endpoint,"/");
|
||||
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(containerScope,endpoint,config);
|
||||
|
|
|
@ -175,7 +175,7 @@ public interface Session extends Closeable
|
|||
void setIdleTimeout(long ms);
|
||||
|
||||
/**
|
||||
* Suspend a the incoming read events on the connection.
|
||||
* Suspend the incoming read events on the connection.
|
||||
*
|
||||
* @return the suspend token suitable for resuming the reading of data on the connection.
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.eclipse.jetty.websocket.common.WebSocketSession;
|
|||
import org.eclipse.jetty.websocket.common.WebSocketSessionFactory;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
|
||||
import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory;
|
||||
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
|
||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||
|
||||
/**
|
||||
|
@ -66,12 +67,11 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
// From HttpClient
|
||||
private final HttpClient httpClient;
|
||||
|
||||
// Other
|
||||
private final WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();
|
||||
//
|
||||
private final WebSocketContainerScope containerScope;
|
||||
private final WebSocketExtensionFactory extensionRegistry;
|
||||
private final EventDriverFactory eventDriverFactory;
|
||||
private final SessionFactory sessionFactory;
|
||||
private final DecoratedObjectFactory objectFactory;
|
||||
private Masker masker;
|
||||
|
||||
private final int id = ThreadLocalRandom.current().nextInt();
|
||||
|
@ -107,12 +107,12 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory objectFactory)
|
||||
{
|
||||
this.containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy(),new MappedByteBufferPool(),objectFactory);
|
||||
this.httpClient = httpClient;
|
||||
this.objectFactory = objectFactory;
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(this);
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(containerScope);
|
||||
this.masker = new RandomMasker();
|
||||
this.eventDriverFactory = new EventDriverFactory(policy);
|
||||
this.sessionFactory = new WebSocketSessionFactory(this);
|
||||
this.eventDriverFactory = new EventDriverFactory(containerScope);
|
||||
this.sessionFactory = new WebSocketSessionFactory(containerScope);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,17 +229,14 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
this.httpClient.setExecutor(executor);
|
||||
this.httpClient.setByteBufferPool(bufferPool);
|
||||
addBean(this.httpClient);
|
||||
|
||||
this.containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy(), bufferPool, objectFactory);
|
||||
|
||||
if (objectFactory == null)
|
||||
this.objectFactory = new DecoratedObjectFactory();
|
||||
else
|
||||
this.objectFactory = objectFactory;
|
||||
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(this);
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(containerScope);
|
||||
|
||||
this.masker = new RandomMasker();
|
||||
this.eventDriverFactory = new EventDriverFactory(policy);
|
||||
this.sessionFactory = new WebSocketSessionFactory(this);
|
||||
this.eventDriverFactory = new EventDriverFactory(containerScope);
|
||||
this.sessionFactory = new WebSocketSessionFactory(containerScope);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,6 +252,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public WebSocketClient(WebSocketContainerScope scope, EventDriverFactory eventDriverFactory, SessionFactory sessionFactory)
|
||||
{
|
||||
this.containerScope = scope;
|
||||
SslContextFactory sslContextFactory = scope.getSslContextFactory();
|
||||
if(sslContextFactory == null)
|
||||
{
|
||||
|
@ -264,8 +262,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
this.httpClient.setExecutor(scope.getExecutor());
|
||||
addBean(this.httpClient);
|
||||
|
||||
this.objectFactory = new DecoratedObjectFactory();
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(this);
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(containerScope);
|
||||
|
||||
this.masker = new RandomMasker();
|
||||
this.eventDriverFactory = eventDriverFactory;
|
||||
|
@ -395,7 +392,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public long getAsyncWriteTimeout()
|
||||
{
|
||||
return this.policy.getAsyncWriteTimeout();
|
||||
return this.containerScope.getPolicy().getAsyncWriteTimeout();
|
||||
}
|
||||
|
||||
public SocketAddress getBindAddress()
|
||||
|
@ -451,7 +448,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public int getMaxBinaryMessageBufferSize()
|
||||
{
|
||||
return this.policy.getMaxBinaryMessageBufferSize();
|
||||
return getPolicy().getMaxBinaryMessageBufferSize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -461,7 +458,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public long getMaxBinaryMessageSize()
|
||||
{
|
||||
return this.policy.getMaxBinaryMessageSize();
|
||||
return getPolicy().getMaxBinaryMessageSize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -471,7 +468,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public long getMaxIdleTimeout()
|
||||
{
|
||||
return this.policy.getIdleTimeout();
|
||||
return getPolicy().getIdleTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -481,7 +478,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public int getMaxTextMessageBufferSize()
|
||||
{
|
||||
return this.policy.getMaxTextMessageBufferSize();
|
||||
return getPolicy().getMaxTextMessageBufferSize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -491,13 +488,12 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public long getMaxTextMessageSize()
|
||||
{
|
||||
return this.policy.getMaxTextMessageSize();
|
||||
return getPolicy().getMaxTextMessageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecoratedObjectFactory getObjectFactory()
|
||||
{
|
||||
return this.objectFactory;
|
||||
return this.containerScope.getObjectFactory();
|
||||
}
|
||||
|
||||
public Set<WebSocketSession> getOpenSessions()
|
||||
|
@ -507,7 +503,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
|
||||
public WebSocketPolicy getPolicy()
|
||||
{
|
||||
return this.policy;
|
||||
return this.containerScope.getPolicy();
|
||||
}
|
||||
|
||||
public Scheduler getScheduler()
|
||||
|
@ -568,7 +564,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
|
||||
public void setAsyncWriteTimeout(long ms)
|
||||
{
|
||||
this.policy.setAsyncWriteTimeout(ms);
|
||||
getPolicy().setAsyncWriteTimeout(ms);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -631,7 +627,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
|
||||
public void setMaxBinaryMessageBufferSize(int max)
|
||||
{
|
||||
this.policy.setMaxBinaryMessageBufferSize(max);
|
||||
getPolicy().setMaxBinaryMessageBufferSize(max);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -644,13 +640,13 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont
|
|||
*/
|
||||
public void setMaxIdleTimeout(long ms)
|
||||
{
|
||||
this.policy.setIdleTimeout(ms);
|
||||
getPolicy().setIdleTimeout(ms);
|
||||
this.httpClient.setIdleTimeout(ms);
|
||||
}
|
||||
|
||||
public void setMaxTextMessageBufferSize(int max)
|
||||
{
|
||||
this.policy.setMaxTextMessageBufferSize(max);
|
||||
getPolicy().setMaxTextMessageBufferSize(max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,8 +25,8 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketListener;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||
|
||||
/**
|
||||
* Create EventDriver implementations.
|
||||
|
@ -34,12 +34,12 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
|||
public class EventDriverFactory
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(EventDriverFactory.class);
|
||||
private final WebSocketPolicy policy;
|
||||
private final WebSocketContainerScope containerScope;
|
||||
private final List<EventDriverImpl> implementations;
|
||||
|
||||
public EventDriverFactory(WebSocketPolicy policy)
|
||||
public EventDriverFactory(WebSocketContainerScope containerScope)
|
||||
{
|
||||
this.policy = policy;
|
||||
this.containerScope = containerScope;
|
||||
this.implementations = new ArrayList<>();
|
||||
|
||||
addImplementation(new JettyListenerImpl());
|
||||
|
@ -117,7 +117,7 @@ public class EventDriverFactory
|
|||
{
|
||||
try
|
||||
{
|
||||
return impl.create(websocket,policy.clonePolicy());
|
||||
return impl.create(websocket,containerScope.getPolicy().clonePolicy());
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
|
@ -705,7 +705,10 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
|||
{
|
||||
if (suspendToken.getAndSet(false))
|
||||
{
|
||||
fillInterested();
|
||||
if (!isReading())
|
||||
{
|
||||
fillInterested();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.eclipse.jetty.websocket.api.WebSocketListener;
|
|||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.common.annotations.NotASocket;
|
||||
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -41,7 +42,7 @@ public class EventDriverFactoryTest
|
|||
@Test
|
||||
public void testAdapterConnectCloseSocket()
|
||||
{
|
||||
EventDriverFactory factory = new EventDriverFactory(WebSocketPolicy.newClientPolicy());
|
||||
EventDriverFactory factory = new EventDriverFactory(new SimpleContainerScope(WebSocketPolicy.newClientPolicy()));
|
||||
AdapterConnectCloseSocket socket = new AdapterConnectCloseSocket();
|
||||
EventDriver driver = factory.wrap(socket);
|
||||
|
||||
|
@ -55,7 +56,7 @@ public class EventDriverFactoryTest
|
|||
@Test
|
||||
public void testBadNotASocket()
|
||||
{
|
||||
EventDriverFactory factory = new EventDriverFactory(WebSocketPolicy.newClientPolicy());
|
||||
EventDriverFactory factory = new EventDriverFactory(new SimpleContainerScope(WebSocketPolicy.newClientPolicy()));
|
||||
try
|
||||
{
|
||||
NotASocket bad = new NotASocket();
|
||||
|
@ -75,7 +76,7 @@ public class EventDriverFactoryTest
|
|||
@Test
|
||||
public void testListenerBasicSocket()
|
||||
{
|
||||
EventDriverFactory factory = new EventDriverFactory(WebSocketPolicy.newClientPolicy());
|
||||
EventDriverFactory factory = new EventDriverFactory(new SimpleContainerScope(WebSocketPolicy.newClientPolicy()));
|
||||
ListenerBasicSocket socket = new ListenerBasicSocket();
|
||||
EventDriver driver = factory.wrap(socket);
|
||||
|
||||
|
|
|
@ -234,7 +234,7 @@ public class EventDriverTest
|
|||
private EventDriver wrap(Object websocket)
|
||||
{
|
||||
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
||||
EventDriverFactory factory = new EventDriverFactory(policy);
|
||||
EventDriverFactory factory = new EventDriverFactory(new SimpleContainerScope(policy));
|
||||
return factory.wrap(websocket);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,12 +74,12 @@ public class MessageOutputStreamTest
|
|||
policy.setInputBufferSize(1024);
|
||||
policy.setMaxBinaryMessageBufferSize(1024);
|
||||
|
||||
// Event Driver factory
|
||||
EventDriverFactory factory = new EventDriverFactory(policy);
|
||||
|
||||
// Container
|
||||
WebSocketContainerScope containerScope = new SimpleContainerScope(policy,bufferPool);
|
||||
|
||||
|
||||
// Event Driver factory
|
||||
EventDriverFactory factory = new EventDriverFactory(containerScope);
|
||||
|
||||
// local socket
|
||||
EventDriver driver = factory.wrap(new TrackingSocket("local"));
|
||||
|
||||
|
|
|
@ -72,12 +72,12 @@ public class MessageWriterTest
|
|||
policy.setInputBufferSize(1024);
|
||||
policy.setMaxTextMessageBufferSize(1024);
|
||||
|
||||
// Event Driver factory
|
||||
EventDriverFactory factory = new EventDriverFactory(policy);
|
||||
|
||||
// Container
|
||||
WebSocketContainerScope containerScope = new SimpleContainerScope(policy,bufferPool);
|
||||
|
||||
|
||||
// Event Driver factory
|
||||
EventDriverFactory factory = new EventDriverFactory(containerScope);
|
||||
|
||||
// local socket
|
||||
EventDriver driver = factory.wrap(new TrackingSocket("local"));
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
|||
this.contextClassloader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
this.defaultPolicy = policy;
|
||||
this.eventDriverFactory = new EventDriverFactory(defaultPolicy);
|
||||
this.eventDriverFactory = new EventDriverFactory(this);
|
||||
this.bufferPool = bufferPool;
|
||||
this.extensionFactory = new WebSocketExtensionFactory(this);
|
||||
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.websocket.server;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.EventQueue;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.SuspendToken;
|
||||
import org.eclipse.jetty.websocket.api.WriteCallback;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.common.test.BlockheadClient;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
|
||||
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SuspendResumeTest
|
||||
{
|
||||
@WebSocket
|
||||
public static class EchoSocket
|
||||
{
|
||||
private Session session;
|
||||
|
||||
@OnWebSocketConnect
|
||||
public void onConnect(Session session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@OnWebSocketMessage
|
||||
public void onMessage(String message)
|
||||
{
|
||||
SuspendToken suspendToken = this.session.suspend();
|
||||
this.session.getRemote().sendString(message,
|
||||
new WriteCallback()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void writeSuccess()
|
||||
{
|
||||
suspendToken.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFailed(Throwable t)
|
||||
{
|
||||
Assert.fail(t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class EchoCreator implements WebSocketCreator
|
||||
{
|
||||
@Override
|
||||
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||
{
|
||||
return new EchoSocket();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EchoServlet extends WebSocketServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void configure(WebSocketServletFactory factory)
|
||||
{
|
||||
factory.setCreator(new EchoCreator());
|
||||
}
|
||||
}
|
||||
|
||||
private static SimpleServletServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
server = new SimpleServletServer(new EchoServlet());
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer()
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuspendResume() throws Exception
|
||||
{
|
||||
try (BlockheadClient client = new BlockheadClient(server.getServerUri()))
|
||||
{
|
||||
client.setTimeout(1, TimeUnit.SECONDS);
|
||||
|
||||
client.connect();
|
||||
client.sendStandardRequest();
|
||||
client.expectUpgradeResponse();
|
||||
|
||||
client.write(new TextFrame().setPayload("echo1"));
|
||||
client.write(new TextFrame().setPayload("echo2"));
|
||||
|
||||
EventQueue<WebSocketFrame> frames = client.readFrames(2, 30, TimeUnit.SECONDS);
|
||||
WebSocketFrame tf = frames.poll();
|
||||
assertThat(EchoSocket.class.getSimpleName() + ".onMessage()", tf.getPayloadAsUTF8(), is("echo1"));
|
||||
tf = frames.poll();
|
||||
assertThat(EchoSocket.class.getSimpleName() + ".onMessage()", tf.getPayloadAsUTF8(), is("echo2"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,12 +18,15 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.server;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
|
@ -35,6 +38,7 @@ import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
|||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.JAR;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
|
@ -47,7 +51,6 @@ import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
|||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||
import org.eclipse.jetty.webapp.WebXmlConfiguration;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* Utility to build out exploded directory WebApps, in the /target/tests/ directory, for testing out servers that use javax.websocket endpoints.
|
||||
|
@ -82,7 +85,7 @@ public class WSServer
|
|||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
String endpointPath = clazz.getName().replace('.','/') + ".class";
|
||||
URL classUrl = cl.getResource(endpointPath);
|
||||
Assert.assertThat("Class URL for: " + clazz,classUrl,notNullValue());
|
||||
assertThat("Class URL for: " + clazz,classUrl,notNullValue());
|
||||
File destFile = new File(classesDir,OS.separators(endpointPath));
|
||||
FS.ensureDirExists(destFile.getParentFile());
|
||||
File srcFile = new File(classUrl.toURI());
|
||||
|
@ -93,7 +96,31 @@ public class WSServer
|
|||
{
|
||||
copyClass(endpointClass);
|
||||
}
|
||||
|
||||
|
||||
public void copyLib(Class<?> clazz, String jarFileName) throws URISyntaxException, IOException
|
||||
{
|
||||
webinf = new File(contextDir,"WEB-INF");
|
||||
FS.ensureDirExists(webinf);
|
||||
File libDir = new File(webinf,"lib");
|
||||
FS.ensureDirExists(libDir);
|
||||
File jarFile = new File(libDir, jarFileName);
|
||||
|
||||
URL codeSourceURL = clazz.getProtectionDomain().getCodeSource().getLocation();
|
||||
assertThat("Class CodeSource URL is file scheme", codeSourceURL.getProtocol(), is("file"));
|
||||
|
||||
File sourceCodeSourceFile = new File(codeSourceURL.toURI());
|
||||
if (sourceCodeSourceFile.isDirectory())
|
||||
{
|
||||
LOG.info("Creating " + jarFile + " from " + sourceCodeSourceFile);
|
||||
JAR.create(sourceCodeSourceFile, jarFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.info("Copying " + sourceCodeSourceFile + " to " + jarFile);
|
||||
IO.copy(sourceCodeSourceFile, jarFile);
|
||||
}
|
||||
}
|
||||
|
||||
public void copyWebInf(String testResourceName) throws IOException
|
||||
{
|
||||
webinf = new File(contextDir,"WEB-INF");
|
||||
|
@ -173,7 +200,7 @@ public class WSServer
|
|||
contexts = new ContextHandlerCollection();
|
||||
handlers.addHandler(contexts);
|
||||
server.setHandler(handlers);
|
||||
|
||||
|
||||
server.start();
|
||||
|
||||
String host = connector.getHost();
|
||||
|
|
|
@ -204,6 +204,33 @@ public class WebSocketUpgradeFilterTest
|
|||
return server15.getServer();
|
||||
}});
|
||||
|
||||
// WSUF from web.xml, SCI active, apply app-ws configuration via ServletContextListener with WEB-INF/lib/jetty-http.jar
|
||||
|
||||
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener/jetty-http.jar", new ServerProvider()
|
||||
{
|
||||
@Override
|
||||
public Server newServer() throws Exception
|
||||
{
|
||||
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
|
||||
|
||||
WSServer server = new WSServer(testDir, "/");
|
||||
|
||||
server.copyWebInf("wsuf-config-via-listener.xml");
|
||||
server.copyClass(InfoSocket.class);
|
||||
server.copyClass(InfoContextAttributeListener.class);
|
||||
// Add a jetty-http.jar to ensure that the classloader constraints
|
||||
// and the WebAppClassloader setup is sane and correct
|
||||
// The odd version string is present to capture bad regex behavior in Jetty
|
||||
server.copyLib(org.eclipse.jetty.http.pathmap.PathSpec.class, "jetty-http-9.99.999.jar");
|
||||
server.start();
|
||||
|
||||
WebAppContext webapp = server.createWebAppContext();
|
||||
server.deployWebapp(webapp);
|
||||
|
||||
return server.getServer();
|
||||
}
|
||||
}});
|
||||
|
||||
// WSUF from web.xml, SCI active, apply app-ws configuration via Servlet.init
|
||||
|
||||
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/Servlet.init", (ServerProvider) () ->
|
||||
|
|
80
pom.xml
80
pom.xml
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
@ -38,7 +40,6 @@
|
|||
<connection>scm:git:https://github.com/eclipse/jetty.project.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:eclipse/jetty.project.git</developerConnection>
|
||||
<url>https://github.com/eclipse/jetty.project</url>
|
||||
<tag>jetty-9.3.13.M0</tag>
|
||||
</scm>
|
||||
|
||||
<modules>
|
||||
|
@ -149,7 +150,6 @@
|
|||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.7.7.201606060606</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<!-- build tools -->
|
||||
|
@ -365,15 +365,10 @@
|
|||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-version-maven-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<version>3.0.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
|
@ -385,7 +380,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.6.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
|
@ -394,7 +389,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.10</version>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -417,7 +412,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.0.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
|
@ -432,7 +427,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<version>2.10.4</version>
|
||||
<configuration>
|
||||
<docfilessubdirs>true</docfilessubdirs>
|
||||
<detectLinks>true</detectLinks>
|
||||
|
@ -525,12 +520,12 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-plugin-plugin</artifactId>
|
||||
<version>3.4</version>
|
||||
<version>3.5</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>3.6</version>
|
||||
<version>3.7</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -560,12 +555,12 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.6</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.0.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -586,7 +581,17 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-version-maven-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.7.8</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.agilejava.docbkx</groupId>
|
||||
|
@ -634,17 +639,17 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>appassembler-maven-plugin</artifactId>
|
||||
<version>1.10</version>
|
||||
<version>2.0.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.9.1</version>
|
||||
<version>1.12</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>clirr-maven-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
<version>2.8</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
|
@ -654,7 +659,7 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<version>3.0.4</version>
|
||||
<configuration>
|
||||
<findbugsXmlOutput>true</findbugsXmlOutput>
|
||||
<xmlOutput>true</xmlOutput>
|
||||
|
@ -1013,37 +1018,6 @@
|
|||
</pluginManagement>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>jdk9</id>
|
||||
<activation>
|
||||
<jdk>[1.9,)</jdk>
|
||||
</activation>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>apache-plugins-snapshots</id>
|
||||
<url>https://repository.apache.org/content/groups/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>config</id>
|
||||
<activation>
|
||||
|
|
|
@ -50,8 +50,7 @@
|
|||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar
|
||||
</argLine>
|
||||
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
|
@ -43,6 +43,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -471,10 +472,10 @@ public class HttpClientStreamTest extends AbstractTest
|
|||
@Test(expected = ExecutionException.class)
|
||||
public void testInputStreamContentProviderThrowingWhileReading() throws Exception
|
||||
{
|
||||
start(new AbstractHandler()
|
||||
start(new AbstractHandler.ErrorDispatchHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
public void doNonErrorHandle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
IO.copy(request.getInputStream(), response.getOutputStream());
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
|||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
|
@ -106,7 +105,6 @@ public class TestTransparentProxyServer
|
|||
|
||||
// HTTP2 factory
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(https_config);
|
||||
NegotiatingServerConnectionFactory.checkProtocolNegotiationAvailable();
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(h2.getProtocol());
|
||||
|
||||
|
|
Loading…
Reference in New Issue