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

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
Ludovic Orban 2021-07-08 15:54:20 +02:00
commit 9288e89684
5 changed files with 135 additions and 28 deletions

10
.github/stale.yml vendored
View File

@ -18,3 +18,13 @@ markComment: >
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
This issue has been closed due to it having no activity.
# Issue/PRs having project assigned will not be marked as stale
exemptProjects: false
pulls:
daysUntilStale: 15
daysUntilClose: false
markComment: >
This pull request has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.

View File

@ -13,6 +13,20 @@ jetty-11.0.6 - 29 June 2021
+ 6451 Request#getServletPath() returns null for ROOT mapping
+ 6464 Wrong files/lib definitions in certain *-capture.mod files?
jetty-10.0.6 - 29 June 2021
+ 6375 Always check XML `Set` elements with `property` attribute
+ 6382 HttpClient TimeoutException message reports transient values
+ 6394 Review osgi manifests within Jetty 10
+ 6407 Malformed scheme logical expression check in WebSocket
ClientUpgradeRequest
+ 6410 Ensure Jetty IO uses SocketAddress instead of InetSocketAddress
+ 6418 Bad and/or missing Require-Capability for osgi.serviceloader
+ 6425 Update to asm 9.1
+ 6447 Deprecate support for UTF16 encoding in URIs
+ 6451 Request#getServletPath() returns null for ROOT mapping
+ 6464 Wrong files/lib definitions in certain *-capture.mod files?
+ 6473 Improve alias checking in PathResource
jetty-11.0.5 - 11 June 2021
+ 4772 Jetty WebSocket API onMessage annotation does not support partial
messages.
@ -401,7 +415,7 @@ jetty-11.0.0.beta1 - 10 July 2020
SETTINGS Frame.
+ 4903 Give better errors for non public Websocket Endpoints
+ 4904 WebsocketClient creates more connections than needed
+ 4907
+ 4907
org.eclipse.jetty.websocket.tests.SuspendResumeTest#testSuspendAfterClose
+ 4920 Restore ability to delete sessions on stop
+ 4921 Quickstart run improperly runs dynamically added context initializers

View File

@ -329,7 +329,7 @@ public class SslBytesServerTest extends SslBytesTest
final SSLSocket client2 = newClient(proxy);
threadPool.submit(() ->
Future<Object> handshakeFuture = threadPool.submit(() ->
{
client2.startHandshake();
return null;
@ -361,6 +361,9 @@ public class SslBytesServerTest extends SslBytesTest
// Client Done
TLSRecord doneRecord = proxy.readFromClient();
assertNotNull(doneRecord);
// Wait for socket to be done with handshake
handshakeFuture.get(5, TimeUnit.SECONDS);
// Close
client2.close();
TLSRecord closeRecord = proxy.readFromClient();

View File

@ -15,6 +15,7 @@ package org.eclipse.jetty.http;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
@ -217,6 +218,7 @@ public class HttpParser
private final int _maxHeaderBytes;
private final HttpCompliance _complianceMode;
private final Utf8StringBuilder _uri = new Utf8StringBuilder(INITIAL_URI_LENGTH);
private final FieldCache _fieldCache = new FieldCache();
private HttpField _field;
private HttpHeader _header;
private String _headerString;
@ -241,11 +243,8 @@ public class HttpParser
private boolean _headResponse;
private boolean _cr;
private ByteBuffer _contentChunk;
private Index.Mutable<HttpField> _fieldCache;
private int _length;
private final StringBuilder _string = new StringBuilder();
private int _headerCacheSize = 1024;
private boolean _headerCacheCaseSensitive;
private static HttpCompliance compliance()
{
@ -304,22 +303,22 @@ public class HttpParser
public int getHeaderCacheSize()
{
return _headerCacheSize;
return _fieldCache.getCapacity();
}
public void setHeaderCacheSize(int headerCacheSize)
{
_headerCacheSize = headerCacheSize;
_fieldCache.setCapacity(headerCacheSize);
}
public boolean isHeaderCacheCaseSensitive()
{
return _headerCacheCaseSensitive;
return _fieldCache.isCaseSensitive();
}
public void setHeaderCacheCaseSensitive(boolean headerCacheCaseSensitive)
{
_headerCacheCaseSensitive = headerCacheCaseSensitive;
_fieldCache.setCaseSensitive(headerCacheCaseSensitive);
}
protected void checkViolation(Violation violation) throws BadMessageException
@ -746,6 +745,7 @@ public class HttpParser
break;
case LF:
_fieldCache.prepare();
setState(State.HEADER);
_responseHandler.startResponse(_version, _responseStatus, null);
break;
@ -851,6 +851,7 @@ public class HttpParser
case LF:
if (_responseHandler != null)
{
_fieldCache.prepare();
setState(State.HEADER);
_responseHandler.startResponse(_version, _responseStatus, null);
}
@ -881,7 +882,7 @@ public class HttpParser
_version = HttpVersion.CACHE.get(takeString());
}
checkVersion();
_fieldCache.prepare();
setState(State.HEADER);
_requestHandler.startRequest(_methodString, _uri.toString(), _version);
@ -905,6 +906,7 @@ public class HttpParser
{
case LF:
String reason = takeString();
_fieldCache.prepare();
setState(State.HEADER);
_responseHandler.startResponse(_version, _responseStatus, reason);
continue;
@ -1026,7 +1028,7 @@ public class HttpParser
_field = new HostPortHttpField(_header,
CASE_SENSITIVE_FIELD_NAME.isAllowedBy(_complianceMode) ? _headerString : _header.asString(),
_valueString);
addToFieldCache = true;
addToFieldCache = _fieldCache.isEnabled();
}
break;
@ -1035,7 +1037,7 @@ public class HttpParser
if (_field == null)
_field = new HttpField(_header, caseInsensitiveHeader(_headerString, _header.asString()), _valueString);
if (getHeaderCacheSize() > 0 && _field.contains(HttpHeaderValue.CLOSE.asString()))
_fieldCache = NO_CACHE;
_fieldCache.setCapacity(-1);
break;
case AUTHORIZATION:
@ -1046,7 +1048,7 @@ public class HttpParser
case COOKIE:
case CACHE_CONTROL:
case USER_AGENT:
addToFieldCache = _field == null;
addToFieldCache = _field == null && _fieldCache.cacheable(_header, _valueString);
break;
default:
@ -1054,18 +1056,12 @@ public class HttpParser
}
// Cache field?
if (addToFieldCache && _header != null && _valueString != null)
if (addToFieldCache)
{
if (_fieldCache == null)
_fieldCache = Index.buildCaseSensitiveMutableVisibleAsciiAlphabet(getHeaderCacheSize());
if (_field == null)
_field = new HttpField(_header, caseInsensitiveHeader(_headerString, _header.asString()), _valueString);
if (_field.getValue().length() < getHeaderCacheSize() && !_fieldCache.put(_field))
{
_fieldCache.clear();
_fieldCache.put(_field);
}
_fieldCache.add(_field);
}
}
_handler.parsedHeader(_field != null ? _field : new HttpField(_header, _headerString, _valueString));
@ -1244,7 +1240,7 @@ public class HttpParser
if (buffer.hasRemaining())
{
// Try a look ahead for the known header name and value.
HttpField cachedField = _fieldCache == null ? null : _fieldCache.getBest(buffer, -1, buffer.remaining());
HttpField cachedField = _fieldCache.getBest(buffer, -1, buffer.remaining());
if (cachedField == null)
cachedField = CACHE.getBest(buffer, -1, buffer.remaining());
@ -1911,7 +1907,8 @@ public class HttpParser
public Index<HttpField> getFieldCache()
{
return _fieldCache;
_fieldCache.prepare();
return _fieldCache.getCache();
}
@Override
@ -2007,4 +2004,87 @@ public class HttpParser
LOG.debug(String.format("Illegal character %s in state=%s for buffer %s", token, state, BufferUtil.toDetailString(buffer)));
}
}
private static class FieldCache
{
private int _size = 1024;
private Index.Mutable<HttpField> _cache;
private List<HttpField> _cacheableFields;
private boolean _caseSensitive;
public int getCapacity()
{
return _size;
}
public void setCapacity(int size)
{
_size = size;
if (_size <= 0)
_cache = NO_CACHE;
else
_cache = null;
}
public boolean isCaseSensitive()
{
return _caseSensitive;
}
public void setCaseSensitive(boolean caseSensitive)
{
_caseSensitive = caseSensitive;
}
public boolean isEnabled()
{
return _cache != NO_CACHE;
}
public Index<HttpField> getCache()
{
return _cache;
}
public HttpField getBest(ByteBuffer buffer, int i, int remaining)
{
Index.Mutable<HttpField> cache = _cache;
return cache == null ? null : _cache.getBest(buffer, i, remaining);
}
public void add(HttpField field)
{
if (_cache == null)
{
if (_cacheableFields == null)
_cacheableFields = new ArrayList<>();
_cacheableFields.add(field);
}
else if (!_cache.put(field))
{
_cache.clear();
_cache.put(field);
}
}
public boolean cacheable(HttpHeader header, String valueString)
{
return isEnabled() && header != null && valueString.length() <= _size;
}
private void prepare()
{
if (_cache == null && _cacheableFields != null)
{
_cache = Index.buildMutableVisibleAsciiAlphabet(_caseSensitive, _size);
for (HttpField f : _cacheableFields)
{
if (!_cache.put(f))
break;
}
_cacheableFields.clear();
_cacheableFields = null;
}
}
}
}

View File

@ -259,13 +259,13 @@ public interface Index<V>
* @param <V> The type of the index
* @return A case sensitive mutable Index tacking visible ASCII alphabet to a max capacity.
*/
static <V> Mutable<V> buildCaseSensitiveMutableVisibleAsciiAlphabet(int maxCapacity)
static <V> Mutable<V> buildMutableVisibleAsciiAlphabet(boolean caseSensitive, int maxCapacity)
{
if (maxCapacity < 0 || maxCapacity > ArrayTrie.MAX_CAPACITY)
return new TreeTrie<>(true);
return new TreeTrie<>(caseSensitive);
if (maxCapacity == 0)
return EmptyTrie.instance(true);
return new ArrayTrie<>(true, maxCapacity);
return EmptyTrie.instance(caseSensitive);
return new ArrayTrie<>(caseSensitive, maxCapacity);
}
static <V> Index<V> empty(boolean caseSensitive)