Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2018-11-07 14:06:21 +01:00
commit d81c0cad24
9 changed files with 135 additions and 141 deletions

View File

@ -26,84 +26,58 @@ Effectively this means that you have to stop Jetty to update a file.
==== Remedy
Jetty provides a configuration switch in the `webdefault.xml` file for the DefaultServlet that enables or disables the use of memory-mapped files.
Jetty provides a configuration switch for the `DefaultServlet` that enables or disables the use of memory-mapped files.
If you are running on Windows and are having file-locking problems, you should set this switch to disable memory-mapped file buffers.
Use one of the following options to configure the switch.
The default `webdefault.xml` file is found in the jetty distribution under the `etc/` directory or in the `jetty-webapp-${VERSION}.jar` artifact at `org/eclipse/jetty/webapp/webdefault.xml`.
Edit the file in the distribution or extract it to a convenient disk location and edit it to change `useFileMappedBuffer` to false.
The easiest option is to simply edit the default file contained in the jetty distribution itself.
===== Using override-web.xml
An <<override-web-xml, override-web.xml>> file can be placed in your webapp's `WEB-INF` directory to change the default setting of the `DefaultServlet` for memory-mapped file buffers.
Create an `override-web.xml` file with appropriate headers for your version of the servlet specification, and place the following inside the `<web-app>` element:
[source, xml, subs="{sub-order}"]
----
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>true</param-value> <!-- change to false -->
</init-param>
----
Make sure to apply your custom `webdefault.xml` file to all of your webapps.
You can do that by changing the configuration of the Deployment Manager in `etc/jetty-deploy.xml`.
[source, xml, subs="{sub-order}"]
----
<Call id="webappprovider" name="addAppProvider">
<Arg>
<New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
.
.
<!-- this should be the new custom webdefault.xml or change should be made in this file -->
<Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/etc/webdefault.xml</Set>
<Set name="scanInterval">1</Set>
<Set name="extractWars">true</Set>
.
.
</New>
</Arg>
</Call>
----
Alternatively, if you have individually configured your webapps with context xml files, you need to call the `WebAppContext.setDefaultsDescriptor(String path)` method:
[source, xml, subs="{sub-order}"]
----
<New id="myWebAppContext" class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war">./webapps/fredapp</Set>
<Set name="defaultsDescriptor">/home/fred/jetty/mywebdefaults.xml</Set>
.
.
</New>
----
Instead, you could redefine the DefaultServlet in your web.xml file, making sure to set useFileMappedBuffer to false:
[source, xml, subs="{sub-order}"]
----
<web-app ...>
...
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
...
</web-app>
<servlet-name>default</servlet-name>
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
----
===== Using a Context XML File
You can create or update a context xml file that configures your webapp to apply the setting to disable memory-mapped file buffers.
Add the following to your context xml file:
[source, xml, subs="{sub-order}"]
----
<Call name="setInitParameter">
<Arg>org.eclipse.jetty.servlet.Default.useFileMappedBuffer</Arg>
<Arg>false</Arg>
</Call>
----
===== Using the Jetty Maven Plugin
If you don't want to use either of the other two solutions, you can configure the plugin directly to disable memory-mapped file buffers.
Add the following to the plugin's configuration under the `<webApp>` element:
[source, xml, subs="{sub-order}"]
----
<_initParams>
<org.eclipse.jetty.servlet.Default.useFileMappedBuffer>false</org.eclipse.jetty.servlet.Default.useFileMappedBuffer>
</_initParams>
----
==== Alternate Remedy
You can force a `WebAppContext` to always copy a web app directory on deployment.
The base directory of your web app (ie the root directory where your static content exists) will be copied to the link:#ref-temporary-directories[temp directory].
The base directory of your web app (i.e. the root directory where your static content exists) will be copied to the link:#ref-temporary-directories[temp directory].
Configure this in an xml file like so:
[source, xml, subs="{sub-order}"]
@ -120,4 +94,4 @@ Configure this in an xml file like so:
____
[NOTE]
Be careful with this option when using an explicitly setlink:#ref-temp-directories[temp directory] name - as the name of the temp directory will not unique across redeployments, copying the static content into the same directory name each time may not avoid the locking problem.
____
____

View File

@ -64,7 +64,8 @@
<Set name="maxErrorDispatches"><Property name="jetty.httpConfig.maxErrorDispatches" default="10"/></Set>
<Set name="blockingTimeout"><Property deprecated="jetty.httpConfig.blockingTimeout" name="jetty.httpConfig.blockingTimeout.DEPRECATED" default="-1"/></Set>
<Set name="persistentConnectionsEnabled"><Property name="jetty.httpConfig.persistentConnectionsEnabled" default="true"/></Set>
<Set name="cookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.cookieCompliance" default="RFC6265"/></Arg></Call></Set>
<Set name="requestCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.requestCookieCompliance" default="RFC6265"/></Arg></Call></Set>
<Set name="responseCookieCompliance"><Call class="org.eclipse.jetty.http.CookieCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.responseCookieCompliance" default="RFC6265"/></Arg></Call></Set>
<Set name="multiPartFormDataCompliance"><Call class="org.eclipse.jetty.http.MultiPartFormDataCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.multiPartFormDataCompliance" default="RFC7578"/></Arg></Call></Set>
</New>

View File

@ -62,8 +62,11 @@ patch-module: servlet.api=lib/jetty-schemas-3.1.jar
## Maximum number of error dispatches to prevent looping
# jetty.httpConfig.maxErrorDispatches=10
## Cookie compliance mode of: RFC2965, RFC6265
# jetty.httpConfig.cookieCompliance=RFC6265
## Cookie compliance mode for parsing request Cookie headers: RFC2965, RFC6265
# jetty.httpConfig.requestCookieCompliance=RFC6265
## Cookie compliance mode for generating response Set-Cookie: RFC2965, RFC6265
# jetty.httpConfig.responseCookieCompliance=RFC6265
## multipart/form-data compliance mode of: LEGACY(slow), RFC7578(fast)
# jetty.httpConfig.multiPartFormDataCompliance=LEGACY

View File

@ -33,6 +33,8 @@ import org.eclipse.jetty.util.TreeTrie;
import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.DumpableCollection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -48,7 +50,7 @@ import org.eclipse.jetty.util.log.Logger;
* </p>
*/
@ManagedObject("HTTP Configuration")
public class HttpConfiguration
public class HttpConfiguration implements Dumpable
{
private static final Logger LOG = Log.getLogger(HttpConfiguration.class);
@ -74,7 +76,8 @@ public class HttpConfiguration
private long _minRequestDataRate;
private long _minResponseDataRate;
private HttpCompliance _httpCompliance = HttpCompliance.RFC7230;
private CookieCompliance _cookieCompliance = CookieCompliance.RFC6265;
private CookieCompliance _requestCookieCompliance = CookieCompliance.RFC6265;
private CookieCompliance _responseCookieCompliance = CookieCompliance.RFC6265;
private MultiPartFormDataCompliance _multiPartCompliance = MultiPartFormDataCompliance.RFC7578;
private boolean _notifyRemoteAsyncErrors = true;
@ -138,7 +141,8 @@ public class HttpConfiguration
_useDirectByteBuffers=config._useDirectByteBuffers;
_minRequestDataRate=config._minRequestDataRate;
_minResponseDataRate=config._minResponseDataRate;
_cookieCompliance=config._cookieCompliance;
_requestCookieCompliance =config._requestCookieCompliance;
_responseCookieCompliance =config._responseCookieCompliance;
_notifyRemoteAsyncErrors=config._notifyRemoteAsyncErrors;
}
@ -560,21 +564,43 @@ public class HttpConfiguration
this._httpCompliance = _httpCompliance;
}
public CookieCompliance getCookieCompliance()
/**
* @see #getResponseCookieCompliance()
* @return The CookieCompliance used for parsing request <code>Cookie</code> headers.
*/
public CookieCompliance getRequestCookieCompliance()
{
return _cookieCompliance;
}
public void setCookieCompliance(CookieCompliance cookieCompliance)
{
_cookieCompliance = cookieCompliance==null?CookieCompliance.RFC6265:cookieCompliance;
return _requestCookieCompliance;
}
public boolean isCookieCompliance(CookieCompliance compliance)
/**
* @see #getRequestCookieCompliance()
* @return The CookieCompliance used for generating response <code>Set-Cookie</code> headers
*/
public CookieCompliance getResponseCookieCompliance()
{
return _cookieCompliance.equals(compliance);
return _responseCookieCompliance;
}
/**
* @see #setRequestCookieCompliance(CookieCompliance)
* @param cookieCompliance The CookieCompliance to use for parsing request <code>Cookie</code> headers.
*/
public void setRequestCookieCompliance(CookieCompliance cookieCompliance)
{
_requestCookieCompliance = cookieCompliance==null?CookieCompliance.RFC6265:cookieCompliance;
}
/**
* @see #setResponseCookieCompliance(CookieCompliance)
* @param cookieCompliance The CookieCompliance to use for generating response <code>Set-Cookie</code> headers
*/
public void setResponseCookieCompliance(CookieCompliance cookieCompliance)
{
_responseCookieCompliance = cookieCompliance==null?CookieCompliance.RFC6265:cookieCompliance;
}
/**
* Sets the compliance level for multipart/form-data handling.
*
@ -607,15 +633,51 @@ public class HttpConfiguration
return _notifyRemoteAsyncErrors;
}
@Override public String dump()
{
return Dumpable.dump(this);
}
@Override public void dump(Appendable out, String indent) throws IOException
{
Dumpable.dumpObjects(out,indent,this,
new DumpableCollection("customizers",_customizers),
new DumpableCollection("formEncodedMethods",_formEncodedMethods.keySet()),
"outputBufferSize=" + _outputBufferSize,
"outputAggregationSize=" + _outputAggregationSize,
"requestHeaderSize=" + _requestHeaderSize,
"responseHeaderSize=" + _responseHeaderSize,
"headerCacheSize=" + _headerCacheSize,
"secureScheme=" + _secureScheme,
"securePort=" + _securePort,
"idleTimeout=" + _idleTimeout,
"blockingTimeout=" + _blockingTimeout,
"sendDateHeader=" + _sendDateHeader,
"sendServerVersion=" + _sendServerVersion,
"sendXPoweredBy=" + _sendXPoweredBy,
"delayDispatchUntilContent=" + _delayDispatchUntilContent,
"persistentConnectionsEnabled=" + _persistentConnectionsEnabled,
"maxErrorDispatches=" + _maxErrorDispatches,
"minRequestDataRate=" + _minRequestDataRate,
"minResponseDataRate=" + _minResponseDataRate,
"cookieCompliance=" + _requestCookieCompliance,
"setRequestCookieCompliance=" + _responseCookieCompliance,
"notifyRemoteAsyncErrors=" + _notifyRemoteAsyncErrors
);
}
@Override
public String toString()
{
return String.format("%s@%x{%d/%d,%d/%d,%s://:%d,%s}",
this.getClass().getSimpleName(),
hashCode(),
_outputBufferSize, _outputAggregationSize,
_requestHeaderSize,_responseHeaderSize,
_secureScheme,_securePort,
_customizers);
this.getClass().getSimpleName(),
hashCode(),
_outputBufferSize,
_outputAggregationSize,
_requestHeaderSize,
_responseHeaderSize,
_secureScheme,
_securePort,
_customizers);
}
}

View File

@ -767,7 +767,7 @@ public class Request implements HttpServletRequest
if (field.getHeader()==HttpHeader.COOKIE)
{
if (_cookies==null)
_cookies = new Cookies(getHttpChannel().getHttpConfiguration().getCookieCompliance());
_cookies = new Cookies(getHttpChannel().getHttpConfiguration().getRequestCookieCompliance());
_cookies.addCookieField(field.getValue());
}
}
@ -2043,7 +2043,7 @@ public class Request implements HttpServletRequest
public void setCookies(Cookie[] cookies)
{
if (_cookies == null)
_cookies = new Cookies(getHttpChannel().getHttpConfiguration().getCookieCompliance());
_cookies = new Cookies(getHttpChannel().getHttpConfiguration().getRequestCookieCompliance());
_cookies.setCookies(cookies);
}

View File

@ -173,7 +173,7 @@ public class Response implements HttpServletResponse
throw new IllegalArgumentException("Cookie.name cannot be blank/null");
}
if (getHttpChannel().getHttpConfiguration().isCookieCompliance(CookieCompliance.RFC2965))
if (getHttpChannel().getHttpConfiguration().getResponseCookieCompliance()==CookieCompliance.RFC2965)
addSetRFC2965Cookie(
cookie.getName(),
cookie.getValue(),
@ -218,7 +218,7 @@ public class Response implements HttpServletResponse
throw new IllegalArgumentException("Cookie.name cannot be blank/null");
}
if (getHttpChannel().getHttpConfiguration().isCookieCompliance(CookieCompliance.RFC2965))
if (getHttpChannel().getHttpConfiguration().getResponseCookieCompliance()==CookieCompliance.RFC2965)
addSetRFC2965Cookie(cookie.getName(),
cookie.getValue(),
cookie.getDomain(),

View File

@ -944,7 +944,7 @@ public class ResponseTest
public void testAddCookieComplianceRFC2965() throws Exception
{
Response response = getResponse();
response.getHttpChannel().getHttpConfiguration().setCookieCompliance(CookieCompliance.RFC2965);
response.getHttpChannel().getHttpConfiguration().setResponseCookieCompliance(CookieCompliance.RFC2965);
Cookie cookie = new Cookie("name", "value");
cookie.setDomain("domain");

View File

@ -75,50 +75,4 @@ public class UnixSocketEndPoint extends ChannelEndPoint
LOG.debug(e);
}
}
@Override
public boolean flush(ByteBuffer... buffers) throws IOException
{
// TODO this is a work around for https://github.com/jnr/jnr-unixsocket/issues/50
long flushed=0;
try
{
for (ByteBuffer b : buffers)
{
if (b.hasRemaining())
{
int r=b.remaining();
int p=b.position();
int l=_channel.write(b);
if (l>=0)
{
b.position(p+l);
flushed+=l;
}
if (CEPLOG.isDebugEnabled())
CEPLOG.debug("flushed {}/{} r={} {}", l,r,b.remaining(), this);
if (b.hasRemaining())
break;
}
}
}
catch (IOException e)
{
throw new EofException(e);
}
if (flushed>0)
notIdle();
for (ByteBuffer b : buffers)
if (!BufferUtil.isEmpty(b))
return false;
return true;
}
}

View File

@ -1006,7 +1006,7 @@
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-unixsocket</artifactId>
<version>0.18</version>
<version>0.20</version>
</dependency>
<dependency>
<groupId>junit</groupId>