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:
commit
d81c0cad24
|
@ -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.
|
||||
____
|
||||
____
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue