Merged branch 'jetty-9.4.x' into 'master'.

This commit is contained in:
Simone Bordet 2016-07-20 13:19:15 +02:00
commit f068780749
16 changed files with 197 additions and 63 deletions

View File

@ -1,22 +0,0 @@
This is a source checkout of the Eclipse Jetty webserver.
To build, use:
mvn clean install
The jetty distribution will be built in
jetty-distribution/target/distribution
The first build may take a long time as Maven downloads all the
dependencies.
The tests do a lot of stress testing, and on some machines it is
necessary to set the file descriptor limit to greater than 2048
for the tests to all pass successfully.
Bypass tests by building with -Dmaven.test.skip=true but note
that this will not produce some test jars that are leveraged
in other places in the build.
See also README.md

View File

@ -33,7 +33,22 @@ Documentation
Project documentation is located on our Eclipse website.
- [http://www.eclipse.org/jetty/documentation](http://www.eclipse.org/jetty/documentation)
- README.TXT
Building
========
To build, use:
```shell
mvn clean install
```
The jetty distribution will be built in `jetty-distribution/target/distribution`
The first build may take a long time as Maven downloads all the dependencies.
The tests do a lot of stress testing, and on some machines it is necessary to set the file descriptor limit to greater than 2048 for the tests to all pass successfully.
Bypass tests by building with `mvn -Dmaven.test.skip=true install` but note that this will not produce some test jars that are leveraged in other places in the build.
Professional Services
---------------------

View File

@ -0,0 +1,8 @@
[name]
alpn-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.9.v20160720/alpn-boot-8.1.9.v20160720.jar|lib/alpn/alpn-boot-8.1.9.v20160720.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.9.v20160720.jar

View File

@ -0,0 +1,8 @@
[name]
alpn-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.9.v20160720/alpn-boot-8.1.9.v20160720.jar|lib/alpn/alpn-boot-8.1.9.v20160720.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.9.v20160720.jar

View File

@ -26,15 +26,15 @@ For those browsers that support HTTP/2, they all now support the ALPN negotiatio
Starting with Jetty 9.3.0, only ALPN is supported by Jetty.
The Jetty project provides an implementation of the TLS extension for ALPN for OpenJDK 7 and OpenJDK 8.
The Jetty project provides an implementation of the TLS extension for ALPN for OpenJDK 7 and OpenJDK 8.
ALPN allows the application layer to negotiate which protocol to use over the secure connection.
Any protocol can be negotiated by ALPN within a TLS connection.
The protocols that are most commonly negotiated are HTTP/2 (for browsers that support it) and, historically, SPDY.
The ALPN implementation is therefore not HTTP/2 or SPDY specific in any way.
Any protocol can be negotiated by ALPN within a TLS connection.
The protocols that are most commonly negotiated are HTTP/2 (for browsers that support it) and, historically, SPDY.
The ALPN implementation is therefore not HTTP/2 or SPDY specific in any way.
Jetty's ALPN implementation, although hosted under the umbrella of the Jetty project, is independent of Jetty (the Servlet Container); you can use the ALPN implementation in any other Java network server.
The Jetty distribution will automatically enable ALPN when it is needed to by a HTTP/2 connector, so for the most part ALPN is transparent to the average deployer.
The Jetty distribution will automatically enable ALPN when it is needed to by a HTTP/2 connector, so for the most part ALPN is transparent to the average deployer.
This section provides the detail required for unusual deployments or developing to the ALPN API.
[[alpn-starting]]
@ -54,7 +54,7 @@ Be certain link:#alpn-versions[to get the ALPN Boot Jar version which matches th
[[alpn-osgi]]
===== Starting in OSGi
To use ALPN in an OSGi environment, in addition to putting the ALPN jar on the boot classpath for the container, you will also need to deploy the jetty-osgi-alpn jar.
To use ALPN in an OSGi environment, in addition to putting the ALPN jar on the boot classpath for the container, you will also need to deploy the jetty-osgi-alpn jar.
This jar contains a Fragment-Host directive that ensures the ALPN classes will be available from the system bundle.
You can download the http://central.maven.org/maven2/org/eclipse/jetty/osgi/jetty-osgi-alpn/[jetty-osgi-alpn jar] from Maven Central.
@ -62,14 +62,14 @@ You can download the http://central.maven.org/maven2/org/eclipse/jetty/osgi/jett
[[alpn-understanding]]
==== Understanding the ALPN API
Applications need to interact with ALPN TLS extension protocol negotiations.
Applications need to interact with ALPN TLS extension protocol negotiations.
For example, server applications need to know whether the client supports ALPN, and client applications needs to know whether the server supports ALPN.
To implement this interaction, Jetty's ALPN implementation provides an API to applications, hosted at Maven coordinates
`org.eclipse.jetty.alpn:alpn-api`.
`org.eclipse.jetty.alpn:alpn-api`.
You need to declare this dependency as provided, because the `alpn-boot` Jar already includes it (see the previous section), and it is therefore available from the boot classpath.
The API consists of a single class, `org.eclipse.jetty.alpn.ALPN`, and applications need to register instances of `SSLSocket` or `SSLEngine` with a `ClientProvider` or `ServerProvider` (depending on whether the application is a client application or server application).
The API consists of a single class, `org.eclipse.jetty.alpn.ALPN`, and applications need to register instances of `SSLSocket` or `SSLEngine` with a `ClientProvider` or `ServerProvider` (depending on whether the application is a client application or server application).
Refer to `ALPN` Javadocs and to the examples below for further details about client and server provider methods.
[[alpn-client-example]]
@ -156,7 +156,7 @@ Failing to do so will cause a memory leak.
[[alpn-tests]]
==== Unit Tests
You can write and run unit tests that use the ALPN implementation.
You can write and run unit tests that use the ALPN implementation.
The solution that we use with Maven is to specify an additional command line argument to the Surefire plugin:
[source, xml, subs="{sub-order}"]
@ -202,7 +202,7 @@ Since the ALPN class is in the boot classpath, we chose not to use logging libra
[[alpn-license-details]]
==== License Details
The ALPN implementation relies on modification of a few OpenJDK classes and on a few new classes that need to live in the `sun.security.ssl` package.
The ALPN implementation relies on modification of a few OpenJDK classes and on a few new classes that need to live in the `sun.security.ssl` package.
These classes are released under the same GPLv2+exception license of OpenJDK.
The ALPN class and its nested classes are released under same license as the classes of the Jetty project.
@ -248,6 +248,8 @@ The ALPN implementation, relying on modifications of OpenJDK classes, updates ev
|1.8.0u77 |8.1.7.v20160121
|1.8.0u91 |8.1.7.v20160121
|1.8.0u92 |8.1.8.v20160420
|1.8.0u101 |8.1.9.v20160720
|1.8.0u102 |8.1.9.v20160720
|=============================
[[alpn-build]]
@ -263,7 +265,7 @@ $ hg clone http://hg.openjdk.java.net/jdk7u/jdk7u jdk7u # OpenJDK 7
$ hg clone http://hg.openjdk.java.net/jdk8u/jdk8u jdk8u # OpenJDK 8
$ cd !$
$ ./get_source.sh
....
To update the source to a specific tag, use the following command:
@ -271,7 +273,7 @@ To update the source to a specific tag, use the following command:
[source, screen, subs="{sub-order}"]
....
$ ./make/scripts/hgforest.sh update <tag-name>
....
The list of OpenJDK tags can be obtained from these pages:

View File

@ -907,7 +907,7 @@ public class HttpParser
case HOST:
_host=true;
if (!(_field instanceof HostPortHttpField))
if (!(_field instanceof HostPortHttpField) && _valueString!=null && !_valueString.isEmpty())
{
_field=new HostPortHttpField(_header,legacyString(_headerString,_header.asString()),_valueString);
add_to_connection_trie=_connectionFields!=null;

View File

@ -18,21 +18,24 @@
package org.eclipse.jetty.http;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Properties;
import java.util.Set;
import org.eclipse.jetty.util.ArrayTrie;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.log.Log;
@ -200,16 +203,36 @@ public class MimeTypes
try
{
ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime");
Enumeration<String> i = mime.getKeys();
while(i.hasMoreElements())
String resourceName = "org/eclipse/jetty/http/mime.properties";
URL mimeTypesUrl = Loader.getResource(resourceName);
if (mimeTypesUrl == null)
{
String ext = i.nextElement();
String m = mime.getString(ext);
__dftMimeMap.put(StringUtil.asciiToLowerCase(ext),normalizeMimeType(m));
LOG.warn("Missing mime-type resource: {}", resourceName);
}
else
{
try (InputStream in = mimeTypesUrl.openStream();
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8))
{
Properties mime = new Properties();
mime.load(reader);
mime.stringPropertyNames().stream()
.filter(x->x!=null)
.forEach(x->
__dftMimeMap.put(StringUtil.asciiToLowerCase(x), normalizeMimeType(mime.getProperty(x))));
if (__dftMimeMap.size()<mime.size())
{
LOG.warn("Encountered duplicate or null mime-type extension in resource: {}", mimeTypesUrl);
}
}
if (__dftMimeMap.size()==0)
{
LOG.warn("Empty mime types declaration at {}", mimeTypesUrl);
}
}
}
catch(MissingResourceException e)
catch(IOException e)
{
LOG.warn(e.toString());
LOG.debug(e);
@ -217,15 +240,37 @@ public class MimeTypes
try
{
ResourceBundle encoding = ResourceBundle.getBundle("org/eclipse/jetty/http/encoding");
Enumeration<String> i = encoding.getKeys();
while(i.hasMoreElements())
String resourceName = "org/eclipse/jetty/http/encoding.properties";
URL mimeTypesUrl = Loader.getResource(resourceName);
if (mimeTypesUrl == null)
{
String type = i.nextElement();
__encodings.put(type,encoding.getString(type));
LOG.warn("Missing mime-type resource: {}", resourceName);
}
else
{
try (InputStream in = mimeTypesUrl.openStream();
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8))
{
Properties encoding = new Properties();
encoding.load(reader);
encoding.stringPropertyNames().stream()
.filter(t->t!=null)
.forEach(t->__encodings.put(t, encoding.getProperty(t)));
if (__encodings.size()<encoding.size())
{
LOG.warn("Encountered null or duplicate encoding type in resource: {}", mimeTypesUrl);
}
}
if (__encodings.size()==0)
{
LOG.warn("Empty mime types declaration at {}", mimeTypesUrl);
}
}
}
catch(MissingResourceException e)
catch(IOException e)
{
LOG.warn(e.toString());
LOG.debug(e);

View File

@ -1707,6 +1707,21 @@ public class HttpParserTest
Assert.assertEquals(8888, _port);
}
@Test
public void testEmptyHostPort() throws Exception
{
ByteBuffer buffer = BufferUtil.toBuffer(
"GET / HTTP/1.1\r\n"
+ "Host:\r\n"
+ "Connection: close\r\n"
+ "\r\n");
HttpParser.RequestHandler handler = new Handler();
HttpParser parser = new HttpParser(handler);
parser.parseNext(buffer);
Assert.assertEquals(null, _host);
Assert.assertEquals(null, _bad);
}
@Test
public void testCachedField() throws Exception
{

View File

@ -1330,12 +1330,14 @@ public class Request implements HttpServletRequest
HttpField host = metadata==null?null:metadata.getFields().getField(HttpHeader.HOST);
if (host!=null)
{
// TODO is this needed now?
HostPortHttpField authority = (host instanceof HostPortHttpField)
?((HostPortHttpField)host)
:new HostPortHttpField(host.getValue());
metadata.getURI().setAuthority(authority.getHost(),authority.getPort());
return authority.getHost();
if (!(host instanceof HostPortHttpField) && host.getValue()!=null && !host.getValue().isEmpty())
host=new HostPortHttpField(host.getValue());
if (host instanceof HostPortHttpField)
{
HostPortHttpField authority = (HostPortHttpField)host;
metadata.getURI().setAuthority(authority.getHost(),authority.getPort());
return authority.getHost();
}
}
// Return host from connection

View File

@ -396,6 +396,27 @@ public class HttpConnectionTest
checkContains(response,0,"HTTP/1.1 400");
}
@Test
public void testNoHost() throws Exception
{
String response;
response=connector.getResponse("GET / HTTP/1.1\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 400");
}
@Test
public void testEmptyHost() throws Exception
{
String response;
response=connector.getResponse("GET / HTTP/1.1\r\n"+
"Host:\r\n"+
"\r\n");
checkContains(response,0,"HTTP/1.1 200");
}
@Test
public void testBadURIencoding() throws Exception
{

View File

@ -591,7 +591,7 @@ public class PartialRFC2616Test
offset=0;
response=connector.getResponse("GET /R1 HTTP/1.1\n"+"Host:\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 400","400")+1;
offset=checkContains(response,offset,"HTTP/1.1 200","200")+1;
}
}

View File

@ -966,7 +966,7 @@ public class StartArgs
licenseCheckRequired = true;
return;
}
if (arg.startsWith("--add=") || arg.startsWith("--add-to-start="))
if (arg.startsWith("--add-to-start="))
{
startModules.addAll(Props.getValues(arg));
run = false;

View File

@ -0,0 +1,8 @@
[name]
alpn-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.9.v20160720/alpn-boot-8.1.9.v20160720.jar|lib/alpn/alpn-boot-8.1.9.v20160720.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.9.v20160720.jar

View File

@ -0,0 +1,8 @@
[name]
alpn-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.1.9.v20160720/alpn-boot-8.1.9.v20160720.jar|lib/alpn/alpn-boot-8.1.9.v20160720.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-8.1.9.v20160720.jar

26
pom.xml
View File

@ -17,7 +17,7 @@
<build-support-version>1.4</build-support-version>
<slf4j-version>1.6.6</slf4j-version>
<jetty-test-policy-version>1.2</jetty-test-policy-version>
<alpn.api.version>1.1.2.v20150522</alpn.api.version>
<alpn.api.version>1.1.3.v20160715</alpn.api.version>
<jsp.version>8.0.33</jsp.version>
<!-- default values are unsupported, but required to be defined for reactor sanity reasons -->
<alpn.version>undefined</alpn.version>
@ -1370,6 +1370,30 @@
<alpn.version>8.1.8.v20160420</alpn.version>
</properties>
</profile>
<profile>
<id>8u101</id>
<activation>
<property>
<name>java.version</name>
<value>1.8.0_101</value>
</property>
</activation>
<properties>
<alpn.version>8.1.9.v20160720</alpn.version>
</properties>
</profile>
<profile>
<id>8u102</id>
<activation>
<property>
<name>java.version</name>
<value>1.8.0_102</value>
</property>
</activation>
<properties>
<alpn.version>8.1.9.v20160720</alpn.version>
</properties>
</profile>
</profiles>
<issueManagement>

View File

@ -1459,7 +1459,7 @@ public abstract class RFC2616BaseTest
req4.append("\n");
HttpTester.Response response = http.request(req4);
assertEquals("14.23 HTTP/1.1 - Empty Host", HttpStatus.BAD_REQUEST_400, response.getStatus());
assertEquals("14.23 HTTP/1.1 - Empty Host", HttpStatus.OK_200, response.getStatus());
}
}