use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class ServerTimeoutsTest method testBlockingReadWithMinimumDataRateBelowLimit.
@Test
public void testBlockingReadWithMinimumDataRateBelowLimit() throws Exception {
int bytesPerSecond = 20;
httpConfig.setMinRequestDataRate(bytesPerSecond);
CountDownLatch handlerLatch = new CountDownLatch(1);
start(new AbstractHandler.ErrorDispatchHandler() {
@Override
public void doNonErrorHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
baseRequest.setHandled(true);
ServletInputStream input = request.getInputStream();
while (true) {
int read = input.read();
if (read < 0)
break;
}
} catch (BadMessageException x) {
handlerLatch.countDown();
throw x;
}
}
});
DeferredContentProvider contentProvider = new DeferredContentProvider();
CountDownLatch resultLatch = new CountDownLatch(1);
client.newRequest(newURI()).content(contentProvider).send(result -> {
if (result.getResponse().getStatus() == HttpStatus.REQUEST_TIMEOUT_408)
resultLatch.countDown();
});
for (int i = 0; i < 3; ++i) {
contentProvider.offer(ByteBuffer.allocate(bytesPerSecond / 2));
Thread.sleep(2500);
}
contentProvider.close();
// Request should timeout.
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(resultLatch.await(5, TimeUnit.SECONDS));
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class HTTP2ServerConnection method upgrade.
public boolean upgrade(Request request) {
if (HttpMethod.PRI.is(request.getMethod())) {
getParser().directUpgrade();
} else {
HttpField settingsField = request.getFields().getField(HttpHeader.HTTP2_SETTINGS);
if (settingsField == null)
throw new BadMessageException("Missing " + HttpHeader.HTTP2_SETTINGS + " header");
String value = settingsField.getValue();
final byte[] settings = B64Code.decodeRFC4648URL(value == null ? "" : value);
if (LOG.isDebugEnabled())
LOG.debug("{} settings {}", this, TypeUtil.toHexString(settings));
SettingsFrame settingsFrame = SettingsBodyParser.parseBody(BufferUtil.toBuffer(settings));
if (settingsFrame == null) {
LOG.warn("Invalid {} header value: {}", HttpHeader.HTTP2_SETTINGS, value);
throw new BadMessageException();
}
getParser().standardUpgrade();
upgradeFrames.add(new PrefaceFrame());
upgradeFrames.add(settingsFrame);
// Remember the request to send a response from onOpen().
upgradeFrames.add(new HeadersFrame(1, new Request(request), null, true));
}
return true;
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class HttpChannelOverHTTP2 method onPushRequest.
public Runnable onPushRequest(MetaData.Request request) {
try {
onRequest(request);
getRequest().setAttribute("org.eclipse.jetty.pushed", Boolean.TRUE);
onContentComplete();
onRequestComplete();
if (LOG.isDebugEnabled()) {
Stream stream = getStream();
LOG.debug("HTTP2 PUSH Request #{}/{}:{}{} {} {}{}{}", stream.getId(), Integer.toHexString(stream.getSession().hashCode()), System.lineSeparator(), request.getMethod(), request.getURI(), request.getHttpVersion(), System.lineSeparator(), request.getFields());
}
return this;
} catch (BadMessageException x) {
onBadMessage(x.getCode(), x.getReason());
return null;
} catch (Throwable x) {
onBadMessage(HttpStatus.INTERNAL_SERVER_ERROR_500, null);
return null;
}
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class HpackDecoder method decode.
public MetaData decode(ByteBuffer buffer) {
if (LOG.isDebugEnabled())
LOG.debug(String.format("CtxTbl[%x] decoding %d octets", _context.hashCode(), buffer.remaining()));
// If the buffer is big, don't even think about decoding it
if (buffer.remaining() > _builder.getMaxSize())
throw new BadMessageException(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE_431, "Header frame size " + buffer.remaining() + ">" + _builder.getMaxSize());
while (buffer.hasRemaining()) {
if (LOG.isDebugEnabled() && buffer.hasArray()) {
int l = Math.min(buffer.remaining(), 32);
LOG.debug("decode {}{}", TypeUtil.toHexString(buffer.array(), buffer.arrayOffset() + buffer.position(), l), l < buffer.remaining() ? "..." : "");
}
byte b = buffer.get();
if (b < 0) {
// 7.1 indexed if the high bit is set
int index = NBitInteger.decode(buffer, 7);
Entry entry = _context.get(index);
if (entry == null) {
throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "Unknown index " + index);
} else if (entry.isStatic()) {
if (LOG.isDebugEnabled())
LOG.debug("decode IdxStatic {}", entry);
// emit field
_builder.emit(entry.getHttpField());
// TODO copy and add to reference set if there is room
// _context.add(entry.getHttpField());
} else {
if (LOG.isDebugEnabled())
LOG.debug("decode Idx {}", entry);
// emit
_builder.emit(entry.getHttpField());
}
} else {
// look at the first nibble in detail
byte f = (byte) ((b & 0xF0) >> 4);
String name;
HttpHeader header;
String value;
boolean indexed;
int name_index;
switch(f) {
// 7.3
case 2:
case // 7.3
3:
// change table size
int size = NBitInteger.decode(buffer, 5);
if (LOG.isDebugEnabled())
LOG.debug("decode resize=" + size);
if (size > _localMaxDynamicTableSize)
throw new IllegalArgumentException();
_context.resize(size);
continue;
// 7.2.2
case 0:
case // 7.2.3
1:
indexed = false;
name_index = NBitInteger.decode(buffer, 4);
break;
// 7.2.1
case 4:
// 7.2.1
case 5:
// 7.2.1
case 6:
case // 7.2.1
7:
indexed = true;
name_index = NBitInteger.decode(buffer, 6);
break;
default:
throw new IllegalStateException();
}
boolean huffmanName = false;
// decode the name
if (name_index > 0) {
Entry name_entry = _context.get(name_index);
name = name_entry.getHttpField().getName();
header = name_entry.getHttpField().getHeader();
} else {
huffmanName = (buffer.get() & 0x80) == 0x80;
int length = NBitInteger.decode(buffer, 7);
_builder.checkSize(length, huffmanName);
if (huffmanName)
name = Huffman.decode(buffer, length);
else
name = toASCIIString(buffer, length);
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (c >= 'A' && c <= 'Z') {
throw new BadMessageException(400, "Uppercase header name");
}
}
header = HttpHeader.CACHE.get(name);
}
// decode the value
boolean huffmanValue = (buffer.get() & 0x80) == 0x80;
int length = NBitInteger.decode(buffer, 7);
_builder.checkSize(length, huffmanValue);
if (huffmanValue)
value = Huffman.decode(buffer, length);
else
value = toASCIIString(buffer, length);
// Make the new field
HttpField field;
if (header == null) {
// just make a normal field and bypass header name lookup
field = new HttpField(null, name, value);
} else {
// and/or of a type that may be looked up multiple times.
switch(header) {
case C_STATUS:
if (indexed)
field = new HttpField.IntValueHttpField(header, name, value);
else
field = new HttpField(header, name, value);
break;
case C_AUTHORITY:
field = new AuthorityHttpField(value);
break;
case CONTENT_LENGTH:
if ("0".equals(value))
field = CONTENT_LENGTH_0;
else
field = new HttpField.LongValueHttpField(header, name, value);
break;
default:
field = new HttpField(header, name, value);
break;
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("decoded '{}' by {}/{}/{}", field, name_index > 0 ? "IdxName" : (huffmanName ? "HuffName" : "LitName"), huffmanValue ? "HuffVal" : "LitVal", indexed ? "Idx" : "");
}
// emit the field
_builder.emit(field);
// if indexed
if (indexed) {
// add to dynamic table
if (_context.add(field) == null)
throw new BadMessageException(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE_431, "Indexed field value too large");
}
}
}
return _builder.build();
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class MetaDataBuilder method emit.
public void emit(HttpField field) {
HttpHeader header = field.getHeader();
String name = field.getName();
String value = field.getValue();
int field_size = name.length() + (value == null ? 0 : value.length());
_size += field_size + 32;
if (_size > _maxSize)
throw new BadMessageException(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE_431, "Header size " + _size + ">" + _maxSize);
if (field instanceof StaticTableHttpField) {
StaticTableHttpField staticField = (StaticTableHttpField) field;
switch(header) {
case C_STATUS:
_status = (Integer) staticField.getStaticValue();
break;
case C_METHOD:
_method = value;
break;
case C_SCHEME:
_scheme = (HttpScheme) staticField.getStaticValue();
break;
default:
throw new IllegalArgumentException(name);
}
} else if (header != null) {
switch(header) {
case C_STATUS:
_status = field.getIntValue();
break;
case C_METHOD:
_method = value;
break;
case C_SCHEME:
if (value != null)
_scheme = HttpScheme.CACHE.get(value);
break;
case C_AUTHORITY:
if (field instanceof HostPortHttpField)
_authority = (HostPortHttpField) field;
else if (value != null)
_authority = new AuthorityHttpField(value);
break;
case HOST:
// :authority fields must come first. If we have one, ignore the host header as far as authority goes.
if (_authority == null) {
if (field instanceof HostPortHttpField)
_authority = (HostPortHttpField) field;
else if (value != null)
_authority = new AuthorityHttpField(value);
}
_fields.add(field);
break;
case C_PATH:
_path = value;
break;
case CONTENT_LENGTH:
_contentLength = field.getLongValue();
_fields.add(field);
break;
default:
if (name.charAt(0) != ':')
_fields.add(field);
break;
}
} else {
if (name.charAt(0) != ':')
_fields.add(field);
}
}
Aggregations