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 ==== 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. 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`. ===== Using override-web.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. 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}"] [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>
<servlet-name>default</servlet-name> <servlet-name>default</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class> <init-param>
<init-param> <param-name>useFileMappedBuffer</param-name>
<param-name>useFileMappedBuffer</param-name> <param-value>false</param-value>
<param-value>false</param-value> </init-param>
</init-param> </servlet>
<load-on-startup>0</load-on-startup>
</servlet>
...
</web-app>
---- ----
===== 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 ==== Alternate Remedy
You can force a `WebAppContext` to always copy a web app directory on deployment. 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: Configure this in an xml file like so:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
@ -120,4 +94,4 @@ Configure this in an xml file like so:
____ ____
[NOTE] [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. 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="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="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="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> <Set name="multiPartFormDataCompliance"><Call class="org.eclipse.jetty.http.MultiPartFormDataCompliance" name="valueOf"><Arg><Property name="jetty.httpConfig.multiPartFormDataCompliance" default="RFC7578"/></Arg></Call></Set>
</New> </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 ## Maximum number of error dispatches to prevent looping
# jetty.httpConfig.maxErrorDispatches=10 # jetty.httpConfig.maxErrorDispatches=10
## Cookie compliance mode of: RFC2965, RFC6265 ## Cookie compliance mode for parsing request Cookie headers: RFC2965, RFC6265
# jetty.httpConfig.cookieCompliance=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) ## multipart/form-data compliance mode of: LEGACY(slow), RFC7578(fast)
# jetty.httpConfig.multiPartFormDataCompliance=LEGACY # 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.Trie;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject; 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.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ -48,7 +50,7 @@ import org.eclipse.jetty.util.log.Logger;
* </p> * </p>
*/ */
@ManagedObject("HTTP Configuration") @ManagedObject("HTTP Configuration")
public class HttpConfiguration public class HttpConfiguration implements Dumpable
{ {
private static final Logger LOG = Log.getLogger(HttpConfiguration.class); private static final Logger LOG = Log.getLogger(HttpConfiguration.class);
@ -74,7 +76,8 @@ public class HttpConfiguration
private long _minRequestDataRate; private long _minRequestDataRate;
private long _minResponseDataRate; private long _minResponseDataRate;
private HttpCompliance _httpCompliance = HttpCompliance.RFC7230; 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 MultiPartFormDataCompliance _multiPartCompliance = MultiPartFormDataCompliance.RFC7578;
private boolean _notifyRemoteAsyncErrors = true; private boolean _notifyRemoteAsyncErrors = true;
@ -138,7 +141,8 @@ public class HttpConfiguration
_useDirectByteBuffers=config._useDirectByteBuffers; _useDirectByteBuffers=config._useDirectByteBuffers;
_minRequestDataRate=config._minRequestDataRate; _minRequestDataRate=config._minRequestDataRate;
_minResponseDataRate=config._minResponseDataRate; _minResponseDataRate=config._minResponseDataRate;
_cookieCompliance=config._cookieCompliance; _requestCookieCompliance =config._requestCookieCompliance;
_responseCookieCompliance =config._responseCookieCompliance;
_notifyRemoteAsyncErrors=config._notifyRemoteAsyncErrors; _notifyRemoteAsyncErrors=config._notifyRemoteAsyncErrors;
} }
@ -560,21 +564,43 @@ public class HttpConfiguration
this._httpCompliance = _httpCompliance; this._httpCompliance = _httpCompliance;
} }
public CookieCompliance getCookieCompliance() /**
* @see #getResponseCookieCompliance()
* @return The CookieCompliance used for parsing request <code>Cookie</code> headers.
*/
public CookieCompliance getRequestCookieCompliance()
{ {
return _cookieCompliance; return _requestCookieCompliance;
}
public void setCookieCompliance(CookieCompliance cookieCompliance)
{
_cookieCompliance = cookieCompliance==null?CookieCompliance.RFC6265:cookieCompliance;
} }
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. * Sets the compliance level for multipart/form-data handling.
* *
@ -607,15 +633,51 @@ public class HttpConfiguration
return _notifyRemoteAsyncErrors; 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 @Override
public String toString() public String toString()
{ {
return String.format("%s@%x{%d/%d,%d/%d,%s://:%d,%s}", return String.format("%s@%x{%d/%d,%d/%d,%s://:%d,%s}",
this.getClass().getSimpleName(), this.getClass().getSimpleName(),
hashCode(), hashCode(),
_outputBufferSize, _outputAggregationSize, _outputBufferSize,
_requestHeaderSize,_responseHeaderSize, _outputAggregationSize,
_secureScheme,_securePort, _requestHeaderSize,
_customizers); _responseHeaderSize,
_secureScheme,
_securePort,
_customizers);
} }
} }

View File

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

View File

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

View File

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

View File

@ -75,50 +75,4 @@ public class UnixSocketEndPoint extends ChannelEndPoint
LOG.debug(e); 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> <dependency>
<groupId>com.github.jnr</groupId> <groupId>com.github.jnr</groupId>
<artifactId>jnr-unixsocket</artifactId> <artifactId>jnr-unixsocket</artifactId>
<version>0.18</version> <version>0.20</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>