use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class HttpChannelState method onError.
protected void onError(Throwable failure) {
final List<AsyncListener> listeners;
final AsyncContextEvent event;
final Request baseRequest = _channel.getRequest();
int code = HttpStatus.INTERNAL_SERVER_ERROR_500;
String reason = null;
if (failure instanceof BadMessageException) {
BadMessageException bme = (BadMessageException) failure;
code = bme.getCode();
reason = bme.getReason();
} else if (failure instanceof UnavailableException) {
if (((UnavailableException) failure).isPermanent())
code = HttpStatus.NOT_FOUND_404;
else
code = HttpStatus.SERVICE_UNAVAILABLE_503;
}
try (Locker.Lock lock = _locker.lock()) {
if (LOG.isDebugEnabled())
LOG.debug("onError {} {}", toStringLocked(), failure);
// Set error on request.
if (_event != null) {
_event.addThrowable(failure);
_event.getSuppliedRequest().setAttribute(ERROR_STATUS_CODE, code);
_event.getSuppliedRequest().setAttribute(ERROR_EXCEPTION, failure);
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, failure == null ? null : failure.getClass());
_event.getSuppliedRequest().setAttribute(ERROR_MESSAGE, reason);
} else {
Throwable error = (Throwable) baseRequest.getAttribute(ERROR_EXCEPTION);
if (error != null)
throw new IllegalStateException("Error already set", error);
baseRequest.setAttribute(ERROR_STATUS_CODE, code);
baseRequest.setAttribute(ERROR_EXCEPTION, failure);
baseRequest.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, failure == null ? null : failure.getClass());
baseRequest.setAttribute(ERROR_MESSAGE, reason);
}
// Are we blocking?
if (_async == Async.NOT_ASYNC) {
// Only called from within HttpChannel Handling, so much be dispatched, let's stay dispatched!
if (_state == State.DISPATCHED) {
_state = State.THROWN;
return;
}
throw new IllegalStateException(this.getStatusStringLocked());
}
// We are Async
_async = Async.ERRORING;
listeners = _asyncListeners;
event = _event;
}
if (listeners != null) {
Runnable task = new Runnable() {
@Override
public void run() {
for (AsyncListener listener : listeners) {
try {
listener.onError(event);
} catch (Throwable x) {
LOG.warn(x + " while invoking onError listener " + listener);
LOG.debug(x);
}
}
}
@Override
public String toString() {
return "onError";
}
};
runInContext(event, task);
}
boolean dispatch = false;
try (Locker.Lock lock = _locker.lock()) {
switch(_async) {
case ERRORING:
{
// Still in this state ? The listeners did not invoke API methods
// and the container must provide a default error dispatch.
_async = Async.ERRORED;
break;
}
case DISPATCH:
case COMPLETE:
{
// The listeners called dispatch() or complete().
break;
}
default:
{
throw new IllegalStateException(toString());
}
}
if (_state == State.ASYNC_WAIT) {
_state = State.ASYNC_WOKEN;
dispatch = true;
}
}
if (dispatch) {
if (LOG.isDebugEnabled())
LOG.debug("Dispatch after error {}", this);
scheduleDispatch();
}
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class HpackTest method encodeDecodeTooLargeTest.
@Test
public void encodeDecodeTooLargeTest() {
HpackEncoder encoder = new HpackEncoder();
HpackDecoder decoder = new HpackDecoder(4096, 164);
ByteBuffer buffer = BufferUtil.allocate(16 * 1024);
HttpFields fields0 = new HttpFields();
fields0.add("1234567890", "1234567890123456789012345678901234567890");
fields0.add("Cookie", "abcdeffhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR");
MetaData original0 = new MetaData(HttpVersion.HTTP_2, fields0);
BufferUtil.clearToFill(buffer);
encoder.encode(buffer, original0);
BufferUtil.flipToFlush(buffer, 0);
MetaData decoded0 = (MetaData) decoder.decode(buffer);
assertMetadataSame(original0, decoded0);
HttpFields fields1 = new HttpFields();
fields1.add("1234567890", "1234567890123456789012345678901234567890");
fields1.add("Cookie", "abcdeffhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR");
fields1.add("x", "y");
MetaData original1 = new MetaData(HttpVersion.HTTP_2, fields1);
BufferUtil.clearToFill(buffer);
encoder.encode(buffer, original1);
BufferUtil.flipToFlush(buffer, 0);
try {
decoder.decode(buffer);
Assert.fail();
} catch (BadMessageException e) {
assertEquals(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE_431, e.getCode());
}
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class SecureRequestCustomizer method customize.
/**
* <p>
* Customizes the request attributes to be set for SSL requests.
* </p>
* <p>
* The requirements of the Servlet specs are:
* </p>
* <ul>
* <li>an attribute named "javax.servlet.request.ssl_session_id" of type String (since Servlet Spec 3.0).</li>
* <li>an attribute named "javax.servlet.request.cipher_suite" of type String.</li>
* <li>an attribute named "javax.servlet.request.key_size" of type Integer.</li>
* <li>an attribute named "javax.servlet.request.X509Certificate" of type java.security.cert.X509Certificate[]. This
* is an array of objects of type X509Certificate, the order of this array is defined as being in ascending order of
* trust. The first certificate in the chain is the one set by the client, the next is the one used to authenticate
* the first, and so on.</li>
* </ul>
*
* @param sslEngine
* the sslEngine to be customized.
* @param request
* HttpRequest to be customized.
*/
protected void customize(SSLEngine sslEngine, Request request) {
SSLSession sslSession = sslEngine.getSession();
if (_sniHostCheck) {
String name = request.getServerName();
X509 x509 = (X509) sslSession.getValue(SniX509ExtendedKeyManager.SNI_X509);
if (x509 != null && !x509.matches(name)) {
LOG.warn("Host {} does not match SNI {}", name, x509);
throw new BadMessageException(400, "Host does not match SNI");
}
if (LOG.isDebugEnabled())
LOG.debug("Host {} matched SNI {}", name, x509);
}
try {
String cipherSuite = sslSession.getCipherSuite();
Integer keySize;
X509Certificate[] certs;
String idStr;
CachedInfo cachedInfo = (CachedInfo) sslSession.getValue(CACHED_INFO_ATTR);
if (cachedInfo != null) {
keySize = cachedInfo.getKeySize();
certs = cachedInfo.getCerts();
idStr = cachedInfo.getIdStr();
} else {
keySize = SslContextFactory.deduceKeyLength(cipherSuite);
certs = SslContextFactory.getCertChain(sslSession);
byte[] bytes = sslSession.getId();
idStr = TypeUtil.toHexString(bytes);
cachedInfo = new CachedInfo(keySize, certs, idStr);
sslSession.putValue(CACHED_INFO_ATTR, cachedInfo);
}
if (certs != null)
request.setAttribute("javax.servlet.request.X509Certificate", certs);
request.setAttribute("javax.servlet.request.cipher_suite", cipherSuite);
request.setAttribute("javax.servlet.request.key_size", keySize);
request.setAttribute("javax.servlet.request.ssl_session_id", idStr);
String sessionAttribute = getSslSessionAttribute();
if (sessionAttribute != null && !sessionAttribute.isEmpty())
request.setAttribute(sessionAttribute, sslSession);
} catch (Exception e) {
LOG.warn(Log.EXCEPTION, e);
}
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class Request method setMetaData.
/* ------------------------------------------------------------ */
/**
* @param request the Request metadata
*/
public void setMetaData(org.eclipse.jetty.http.MetaData.Request request) {
_metaData = request;
setMethod(request.getMethod());
HttpURI uri = request.getURI();
_originalURI = uri.isAbsolute() && request.getHttpVersion() != HttpVersion.HTTP_2 ? uri.toString() : uri.getPathQuery();
String path = uri.getDecodedPath();
String info;
if (path == null || path.length() == 0) {
if (uri.isAbsolute()) {
path = "/";
uri.setPath(path);
} else {
setPathInfo("");
throw new BadMessageException(400, "Bad URI");
}
info = path;
} else if (!path.startsWith("/")) {
if (!"*".equals(path) && !HttpMethod.CONNECT.is(getMethod())) {
setPathInfo(path);
throw new BadMessageException(400, "Bad URI");
}
info = path;
} else
// TODO should this be done prior to decoding???
info = URIUtil.canonicalPath(path);
if (info == null) {
setPathInfo(path);
throw new BadMessageException(400, "Bad URI");
}
setPathInfo(info);
}
use of org.eclipse.jetty.http.BadMessageException in project jetty.project by eclipse.
the class HttpInput method read.
@Override
public int read(byte[] b, int off, int len) throws IOException {
boolean wake = false;
int l;
synchronized (_inputQ) {
// Setup blocking only if not async
if (!isAsync()) {
if (_blockUntil == 0) {
long blockingTimeout = getBlockingTimeout();
if (blockingTimeout > 0)
_blockUntil = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(blockingTimeout);
}
}
// Calculate minimum request rate for DOS protection
long minRequestDataRate = _channelState.getHttpChannel().getHttpConfiguration().getMinRequestDataRate();
if (minRequestDataRate > 0 && _firstByteTimeStamp != -1) {
long period = System.nanoTime() - _firstByteTimeStamp;
if (period > 0) {
long minimum_data = minRequestDataRate * TimeUnit.NANOSECONDS.toMillis(period) / TimeUnit.SECONDS.toMillis(1);
if (_contentArrived < minimum_data)
throw new BadMessageException(HttpStatus.REQUEST_TIMEOUT_408, String.format("Request data rate < %d B/s", minRequestDataRate));
}
}
// Consume content looking for bytes to read
while (true) {
Content item = nextContent();
if (item != null) {
l = get(item, b, off, len);
if (LOG.isDebugEnabled())
LOG.debug("{} read {} from {}", this, l, item);
// Consume any following poison pills
if (item.isEmpty())
nextInterceptedContent();
break;
}
// No content, so should we block?
if (!_state.blockForContent(this)) {
// Not blocking, so what should we return?
l = _state.noContent();
// If EOF do we need to wake for allDataRead callback?
if (l < 0)
wake = _channelState.onReadEof();
break;
}
}
}
if (wake)
wake();
return l;
}
Aggregations