use of org.eclipse.jetty.continuation.Continuation in project voltdb by VoltDB.
the class HTTPClientInterface method process.
public void process(Request request, HttpServletResponse response) {
AuthenticationResult authResult = null;
boolean suspended = false;
String jsonp = request.getHeader(JSONP);
if (!validateJSONP(jsonp, request, response)) {
return;
}
String authHeader = request.getHeader(HttpHeader.AUTHORIZATION.asString());
if (m_spnegoEnabled && (authHeader == null || !authHeader.startsWith(HttpHeader.NEGOTIATE.asString()))) {
m_log.debug("SpengoAuthenticator: sending challenge");
response.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), HttpHeader.NEGOTIATE.asString());
unauthorized(jsonp, "must initiate SPNEGO negotiation", response);
request.setHandled(true);
return;
}
final Continuation continuation = ContinuationSupport.getContinuation(request);
String result = (String) continuation.getAttribute("result");
if (result != null) {
try {
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(result);
request.setHandled(true);
} catch (IllegalStateException | IOException e) {
// Thrown when we shut down the server via the JSON/HTTP (web studio) API
// Essentially we're closing everything down from underneath the HTTP request.
m_log.warn("JSON failed to send response: ", e);
}
return;
}
//Check if this is resumed request.
if (Boolean.TRUE.equals(continuation.getAttribute("SQLSUBMITTED"))) {
try {
continuation.suspend(response);
} catch (IllegalStateException e) {
// Thrown when we shut down the server via the JSON/HTTP (web studio) API
// Essentially we're closing everything down from underneath the HTTP request.
m_log.warn("JSON request completion exception in process: ", e);
}
return;
}
if (m_timeout > 0 && continuation.isInitial()) {
continuation.setTimeout(m_timeout);
}
try {
if (request.getMethod().equalsIgnoreCase("POST")) {
int queryParamSize = request.getContentLength();
if (queryParamSize > MAX_QUERY_PARAM_SIZE) {
ok(jsonp, "Query string too large: " + String.valueOf(request.getContentLength()), response);
request.setHandled(true);
return;
}
if (queryParamSize == 0) {
ok(jsonp, "Received POST with no parameters in the body.", response);
request.setHandled(true);
return;
}
}
if (jsonp == null) {
jsonp = request.getParameter(JSONP);
if (!validateJSONP(jsonp, request, response)) {
return;
}
}
String procName = request.getParameter("Procedure");
String params = request.getParameter("Parameters");
String timeoutStr = request.getParameter(QUERY_TIMEOUT_PARAM);
// null procs are bad news
if (procName == null) {
badRequest(jsonp, "Procedure parameter is missing", response);
request.setHandled(true);
return;
}
int queryTimeout = -1;
if (timeoutStr != null) {
try {
queryTimeout = Integer.parseInt(timeoutStr);
if (queryTimeout <= 0) {
throw new NumberFormatException("negative query timeout");
}
} catch (NumberFormatException e) {
badRequest(jsonp, "invalid query timeout: " + timeoutStr, response);
request.setHandled(true);
return;
}
}
authResult = authenticate(request);
if (!authResult.isAuthenticated()) {
unauthorized(jsonp, authResult.m_message, response);
request.setHandled(true);
return;
}
continuation.suspend(response);
suspended = true;
JSONProcCallback cb = new JSONProcCallback(continuation, jsonp);
boolean success;
if (params != null) {
ParameterSet paramSet = null;
try {
paramSet = ParameterSet.fromJSONString(params);
}// if decoding params has a fail, then fail
catch (Exception e) {
badRequest(jsonp, "failed to parse invocation parameters", response);
request.setHandled(true);
continuation.complete();
return;
}
// if the paramset has content, but decodes to null, fail
if (paramSet == null) {
badRequest(jsonp, "failed to decode invocation parameters", response);
request.setHandled(true);
continuation.complete();
return;
}
success = callProcedure(authResult, queryTimeout, cb, procName, paramSet.toArray());
} else {
success = callProcedure(authResult, queryTimeout, cb, procName);
}
if (!success) {
ok(jsonp, "Server is not accepting work at this time.", response);
request.setHandled(true);
continuation.complete();
return;
}
if (jsonp != null) {
request.setAttribute("jsonp", jsonp);
}
continuation.setAttribute("SQLSUBMITTED", Boolean.TRUE);
} catch (Exception e) {
String msg = Throwables.getStackTraceAsString(e);
m_rate_limited_log.log(EstTime.currentTimeMillis(), Level.WARN, e, "JSON interface exception");
ok(jsonp, msg, response);
if (suspended) {
continuation.complete();
}
request.setHandled(true);
}
}
use of org.eclipse.jetty.continuation.Continuation in project zm-mailbox by Zimbra.
the class WaitSetRequest method staticHandle.
public static Element staticHandle(Element request, Map<String, Object> context, Element response, boolean adminAllowed) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
HttpServletRequest servletRequest = (HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
String waitSetId = request.getAttribute(MailConstants.A_WAITSET_ID);
String lastKnownSeqNo = request.getAttribute(MailConstants.A_SEQ);
boolean block = request.getAttributeBool(MailConstants.A_BLOCK, false);
Callback cb = (Callback) servletRequest.getAttribute(VARS_ATTR_NAME);
if (cb == null) {
// Initial
Continuation continuation = ContinuationSupport.getContinuation(servletRequest);
cb = new Callback();
cb.continuationResume = new ResumeContinuationListener(continuation);
servletRequest.setAttribute(VARS_ATTR_NAME, cb);
String defInterestStr = null;
if (waitSetId.startsWith(WaitSetMgr.ALL_ACCOUNTS_ID_PREFIX)) {
WaitSetMgr.checkRightForAllAccounts(zsc);
// default interest types required for "All" waitsets
defInterestStr = request.getAttribute(MailConstants.A_DEFTYPES);
Set<MailItem.Type> defaultInterests = WaitSetRequest.parseInterestStr(defInterestStr, EnumSet.noneOf(MailItem.Type.class));
cb.ws = WaitSetMgr.lookupOrCreateForAllAccts(zsc.getRequestedAccountId(), waitSetId, defaultInterests, lastKnownSeqNo);
} else {
cb.ws = WaitSetMgr.lookup(waitSetId);
}
if (cb.ws == null)
throw AdminServiceException.NO_SUCH_WAITSET(waitSetId);
WaitSetMgr.checkRightForOwnerAccount(cb.ws, zsc.getRequestedAccountId());
List<WaitSetAccount> add = parseAddUpdateAccounts(zsc, request.getOptionalElement(MailConstants.E_WAITSET_ADD), cb.ws.getDefaultInterest());
List<WaitSetAccount> update = parseAddUpdateAccounts(zsc, request.getOptionalElement(MailConstants.E_WAITSET_UPDATE), cb.ws.getDefaultInterest());
List<String> remove = parseRemoveAccounts(zsc, request.getOptionalElement(MailConstants.E_WAITSET_REMOVE));
///////////////////
// workaround for 27480: load the mailboxes NOW, before we grab the waitset lock
List<Mailbox> referencedMailboxes = new ArrayList<Mailbox>();
for (WaitSetAccount acct : add) {
try {
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(acct.getAccountId(), MailboxManager.FetchMode.AUTOCREATE);
referencedMailboxes.add(mbox);
} catch (ServiceException e) {
ZimbraLog.session.debug("Caught exception preloading mailbox for waitset", e);
}
}
for (WaitSetAccount acct : update) {
try {
Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(acct.getAccountId(), MailboxManager.FetchMode.AUTOCREATE);
referencedMailboxes.add(mbox);
} catch (ServiceException e) {
ZimbraLog.session.debug("Caught exception preloading mailbox for waitset", e);
}
}
// the server in a very fast loop (they should be using the 'block' mode)
try {
Thread.sleep(INITIAL_SLEEP_TIME_MILLIS);
} catch (InterruptedException ex) {
}
cb.errors.addAll(cb.ws.removeAccounts(remove));
synchronized (cb.ws) {
// bug 28190: always grab the WS lock before the CB lock.
synchronized (cb) {
cb.errors.addAll(cb.ws.doWait(cb, lastKnownSeqNo, add, update));
// the ws until we release the cb lock!
if (cb.completed)
block = false;
}
}
if (block) {
// bit.
try {
Thread.sleep(NODATA_SLEEP_TIME_MILLIS);
} catch (InterruptedException ex) {
}
synchronized (cb) {
if (!cb.completed) {
// don't wait if it completed right away
long timeout = getTimeoutMillis(request, adminAllowed);
if (ZimbraLog.soap.isTraceEnabled())
ZimbraLog.soap.trace("Suspending <WaitSetRequest> for %dms", timeout);
cb.continuationResume.suspendAndUndispatch(timeout);
}
}
}
}
// if we got here, then we did *not* execute a jetty RetryContinuation,
// soooo, we'll fall through and finish up at the bottom
// clear the
cb.ws.doneWaiting();
response.addAttribute(MailConstants.A_WAITSET_ID, waitSetId);
if (cb.canceled) {
response.addAttribute(MailConstants.A_CANCELED, true);
} else if (cb.completed) {
response.addAttribute(MailConstants.A_SEQ, cb.seqNo);
for (String s : cb.signalledAccounts) {
Element saElt = response.addElement(MailConstants.E_A);
saElt.addAttribute(MailConstants.A_ID, s);
}
} else {
// timed out....they should try again
response.addAttribute(MailConstants.A_SEQ, lastKnownSeqNo);
}
encodeErrors(response, cb.errors);
return response;
}
use of org.eclipse.jetty.continuation.Continuation in project camel by apache.
the class CamelContinuationServlet method doService.
@Override
protected void doService(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
log.trace("Service: {}", request);
// is there a consumer registered for the request.
HttpConsumer consumer = getServletResolveConsumerStrategy().resolve(request, getConsumers());
if (consumer == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// figure out if continuation is enabled and what timeout to use
boolean useContinuation = false;
Long continuationTimeout = null;
HttpCommonEndpoint endpoint = consumer.getEndpoint();
if (endpoint instanceof JettyHttpEndpoint) {
JettyHttpEndpoint jettyEndpoint = (JettyHttpEndpoint) endpoint;
Boolean epUseContinuation = jettyEndpoint.getUseContinuation();
Long epContinuationTimeout = jettyEndpoint.getContinuationTimeout();
if (epUseContinuation != null) {
useContinuation = epUseContinuation;
} else {
useContinuation = jettyEndpoint.getComponent().isUseContinuation();
}
if (epContinuationTimeout != null) {
continuationTimeout = epContinuationTimeout;
} else {
continuationTimeout = jettyEndpoint.getComponent().getContinuationTimeout();
}
}
if (useContinuation) {
log.trace("Start request with continuation timeout of {}", continuationTimeout != null ? continuationTimeout : "jetty default");
} else {
log.trace("Usage of continuation is disabled, either by component or endpoint configuration, fallback to normal servlet processing instead");
super.doService(request, response);
return;
}
if (consumer.getEndpoint().getHttpMethodRestrict() != null) {
Iterator<?> it = ObjectHelper.createIterable(consumer.getEndpoint().getHttpMethodRestrict()).iterator();
boolean match = false;
while (it.hasNext()) {
String method = it.next().toString();
if (method.equalsIgnoreCase(request.getMethod())) {
match = true;
break;
}
}
if (!match) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
}
if ("TRACE".equals(request.getMethod()) && !consumer.isTraceEnabled()) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
// we do not support java serialized objects unless explicit enabled
String contentType = request.getContentType();
if (HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT.equals(contentType) && !consumer.getEndpoint().getComponent().isAllowJavaSerializedObject()) {
response.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
return;
}
final Exchange result = (Exchange) request.getAttribute(EXCHANGE_ATTRIBUTE_NAME);
if (result == null) {
// no asynchronous result so leverage continuation
final Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isInitial() && continuationTimeout != null) {
// set timeout on initial
continuation.setTimeout(continuationTimeout);
}
// are we suspended and a request is dispatched initially?
if (consumer.isSuspended() && continuation.isInitial()) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
if (continuation.isExpired()) {
String id = (String) continuation.getAttribute(EXCHANGE_ATTRIBUTE_ID);
// remember this id as expired
expiredExchanges.put(id, id);
log.warn("Continuation expired of exchangeId: {}", id);
consumer.getBinding().doWriteExceptionResponse(new TimeoutException(), response);
return;
}
// a new request so create an exchange
final Exchange exchange = new DefaultExchange(consumer.getEndpoint(), ExchangePattern.InOut);
if (consumer.getEndpoint().isBridgeEndpoint()) {
exchange.setProperty(Exchange.SKIP_GZIP_ENCODING, Boolean.TRUE);
exchange.setProperty(Exchange.SKIP_WWW_FORM_URLENCODED, Boolean.TRUE);
}
if (consumer.getEndpoint().isDisableStreamCache()) {
exchange.setProperty(Exchange.DISABLE_HTTP_STREAM_CACHE, Boolean.TRUE);
}
HttpHelper.setCharsetFromContentType(request.getContentType(), exchange);
exchange.setIn(new HttpMessage(exchange, request, response));
// set context path as header
String contextPath = consumer.getEndpoint().getPath();
exchange.getIn().setHeader("CamelServletContextPath", contextPath);
updateHttpPath(exchange, contextPath);
if (log.isTraceEnabled()) {
log.trace("Suspending continuation of exchangeId: {}", exchange.getExchangeId());
}
continuation.setAttribute(EXCHANGE_ATTRIBUTE_ID, exchange.getExchangeId());
// we want to handle the UoW
try {
consumer.createUoW(exchange);
} catch (Exception e) {
log.error("Error processing request", e);
throw new ServletException(e);
}
// must suspend before we process the exchange
continuation.suspend();
ClassLoader oldTccl = overrideTccl(exchange);
if (log.isTraceEnabled()) {
log.trace("Processing request for exchangeId: {}", exchange.getExchangeId());
}
// use the asynchronous API to process the exchange
consumer.getAsyncProcessor().process(exchange, new AsyncCallback() {
public void done(boolean doneSync) {
// check if the exchange id is already expired
boolean expired = expiredExchanges.remove(exchange.getExchangeId()) != null;
if (!expired) {
if (log.isTraceEnabled()) {
log.trace("Resuming continuation of exchangeId: {}", exchange.getExchangeId());
}
// resume processing after both, sync and async callbacks
continuation.setAttribute(EXCHANGE_ATTRIBUTE_NAME, exchange);
continuation.resume();
} else {
log.warn("Cannot resume expired continuation of exchangeId: {}", exchange.getExchangeId());
}
}
});
if (oldTccl != null) {
restoreTccl(exchange, oldTccl);
}
// method again when its resumed
return;
}
try {
// now lets output to the response
if (log.isTraceEnabled()) {
log.trace("Resumed continuation and writing response for exchangeId: {}", result.getExchangeId());
}
Integer bs = consumer.getEndpoint().getResponseBufferSize();
if (bs != null) {
log.trace("Using response buffer size: {}", bs);
response.setBufferSize(bs);
}
consumer.getBinding().writeResponse(result, response);
} catch (IOException e) {
log.error("Error processing request", e);
throw e;
} catch (Exception e) {
log.error("Error processing request", e);
throw new ServletException(e);
} finally {
consumer.doneUoW(result);
}
}
use of org.eclipse.jetty.continuation.Continuation in project leshan by eclipse.
the class EventSourceServlet method doGet.
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Enumeration<String> acceptValues = request.getHeaders("Accept");
while (acceptValues.hasMoreElements()) {
String accept = acceptValues.nextElement();
if (accept.equals("text/event-stream")) {
EventSource eventSource = newEventSource(request);
if (eventSource == null) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} else {
respond(request, response);
Continuation continuation = ContinuationSupport.getContinuation(request);
// Infinite timeout because the continuation is never resumed,
// but only completed on close
continuation.setTimeout(0L);
continuation.suspend(response);
EventSourceEmitter emitter = new EventSourceEmitter(eventSource, continuation);
emitter.scheduleHeartBeat();
open(eventSource, emitter);
}
return;
}
}
super.doGet(request, response);
}
use of org.eclipse.jetty.continuation.Continuation in project saga by timurstrekalov.
the class InstrumentingProxyServlet method service.
@Override
public void service(final ServletRequest req, final ServletResponse res) throws ServletException, IOException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
if ("CONNECT".equalsIgnoreCase(request.getMethod())) {
handleConnect(request, response);
return;
}
final InputStream in = request.getInputStream();
final Continuation continuation = ContinuationSupport.getContinuation(request);
if (!continuation.isInitial()) {
// Need better test that isInitial
response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT);
return;
}
String uri = request.getRequestURI();
if (request.getQueryString() != null) {
uri += "?" + request.getQueryString();
}
final HttpURI url = proxyHttpURI(request, uri);
logger.debug("proxy {}-->{}", uri, url);
if (url == null) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
final HttpExchange exchange = new CustomHttpExchange(continuation, response, request);
exchange.setScheme(HttpSchemes.HTTPS.equals(request.getScheme()) ? HttpSchemes.HTTPS_BUFFER : HttpSchemes.HTTP_BUFFER);
exchange.setMethod(request.getMethod());
exchange.setURL(url.toString());
exchange.setVersion(request.getProtocol());
logger.debug("{} {} {}", request.getMethod(), url, request.getProtocol());
// check connection header
String connectionHdr = request.getHeader("Connection");
if (connectionHdr != null) {
connectionHdr = connectionHdr.toLowerCase(Locale.ENGLISH);
if (!connectionHdr.contains("keep-alive") && !connectionHdr.contains("close")) {
connectionHdr = null;
}
}
// force host
if (_hostHeader != null) {
exchange.setRequestHeader("Host", _hostHeader);
}
// copy headers
boolean xForwardedFor = false;
boolean hasContent = false;
long contentLength = -1;
Enumeration<?> enm = request.getHeaderNames();
while (enm.hasMoreElements()) {
// TODO could be better than this!
String hdr = (String) enm.nextElement();
String lhdr = hdr.toLowerCase(Locale.ENGLISH);
if ("transfer-encoding".equals(lhdr)) {
if (request.getHeader("transfer-encoding").contains("chunk")) {
hasContent = true;
}
}
if (_DontProxyHeaders.contains(lhdr)) {
continue;
}
if (connectionHdr != null && connectionHdr.contains(lhdr)) {
continue;
}
if (_hostHeader != null && "host".equals(lhdr)) {
continue;
}
if ("content-type".equals(lhdr)) {
hasContent = true;
} else if ("content-length".equals(lhdr)) {
contentLength = request.getContentLength();
exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH, Long.toString(contentLength));
if (contentLength > 0) {
hasContent = true;
}
} else if ("x-forwarded-for".equals(lhdr)) {
xForwardedFor = true;
}
Enumeration<?> vals = request.getHeaders(hdr);
while (vals.hasMoreElements()) {
String val = (String) vals.nextElement();
if (val != null) {
logger.debug("{}: {}", hdr, val);
exchange.setRequestHeader(hdr, val);
}
}
}
// Proxy headers
exchange.setRequestHeader("Via", "1.1 (jetty)");
if (!xForwardedFor) {
exchange.addRequestHeader("X-Forwarded-For", request.getRemoteAddr());
exchange.addRequestHeader("X-Forwarded-Proto", request.getScheme());
exchange.addRequestHeader("X-Forwarded-Host", request.getHeader("Host"));
exchange.addRequestHeader("X-Forwarded-Server", request.getLocalName());
}
if (hasContent) {
exchange.setRequestContentSource(in);
}
customizeExchange(exchange, request);
/*
* we need to set the timeout on the continuation to take into
* account the timeout of the HttpClient and the HttpExchange
*/
long ctimeout = (_client.getTimeout() > exchange.getTimeout()) ? _client.getTimeout() : exchange.getTimeout();
// should fail/expire first from exchange
if (ctimeout == 0) {
// ideally never times out
continuation.setTimeout(0);
} else {
continuation.setTimeout(ctimeout + 1000);
}
customizeContinuation(continuation);
continuation.suspend(response);
_client.send(exchange);
}
Aggregations