Correctly shutting down a websocket handler
by Robin Anil
When a client disconnects, I see that onClose is not being fired. The only
way this seems to be firing if client sents a close frame.
Is there any way to detect disconnection and immediately close all the
opened resources.
Robin
Robin Anil | Software Engineer
1 year, 2 months
FormDataProcessor ending exchange prematurely
by Oliver Dain
I have some code for handling file uploads. It uses FormDataProcessor and
tries to do everything asynchronously. I call "FormDataParser.parse"
passing in another handler. I'll call that handler the OnFormDataAvailable.
The OnFormDataAvailable handler checks to see if it's on the IO thread. If
it is, it calls dispatch. Either way, once we're sure we're dispatched that
handler calls yet another handler.
What I've seen is that my OnFormDataAvailable handler (the one called by
parse()) is not on the IO thread so it doesn't need to call dispatch. And
yet, the exchange gets ended before the handler it calls is even close to
complete.
I've found a fix, but I don't understand why it's necessary. Specifically,
if OnFormDataAvailable is not on the IO thread when its invoked it calls
the 0-argument version of "HttpServerExchange.dispatch()" (which you've
told me in another conversation shouldn't ever be necessary). If I do that,
everything is fine.
For completeness, here's the complete code:
public class FormDataParsingHandler {
private static final Logger log =
LoggerFactory.getLogger(FormDataParsingHandler.class);
private static final FormParserFactory formParserFactory =
FormParserFactory.builder().build();
public static final AttachmentKey<FormData> FORM_DATA_ATTACHMENT_KEY
= AttachmentKey.create(FormData.class);
/**
* The only public method - this is what gets exposed as the HttpHandler.
*/
public CompletableFuture<FormData> parseForm(HttpServerExchange exchange) {
log.info("audio file upload request received.");
FormDataParser parser = formParserFactory.createParser(exchange);
if (parser == null) {
log.warn("No parser found that can handle this content type.
Headers were: {}", exchange.getRequestHeaders());
throw new UserVisibleException("No parser for the given content
type.", ResponseCodes.BAD_REQUEST);
}
CompletableFuture<FormData> toComplete = new CompletableFuture<>();
try {
parser.parse(new OnFormDataAvailable(toComplete));
} catch (Exception e) {
log.error("Error parsing form data:", e);
throw wrapAsUnchecked(e);
}
exchange.addExchangeCompleteListener((ex, nextListener) -> {
// Must close the parser so it can free any temporary files that
were created.
try {
parser.close();
} catch (IOException e) {
log.error("Error closing the FormDataParser. Request was
handled successfully but temporary files may not "
+ "have been cleaned up.", e);
}
nextListener.proceed();
});
return toComplete;
}
// The FormDataParser calls an HttpHandler when it's complete so we
add a silly handler here that does nothing but
// complete this method's future when the form data is available.
private static class OnFormDataAvailable implements HttpHandler {
private final CompletableFuture<FormData> toComplete;
private OnFormDataAvailable(CompletableFuture<FormData> toComplete) {
this.toComplete = toComplete;
}
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
// Before we complete the future we have to re-dispatch or we'll
fall off the end of this method and Undertow
// will complete the exchange on our behalf.
FormData data = exchange.getAttachment(FormDataParser.FORM_DATA);
if (exchange.isInIoThread()) {
log.debug("Was on the IO thread. Re-dispatching.");
exchange.dispatch(SameThreadExecutor.INSTANCE, () ->
afterDistpach(data));
} else {
// THIS THE MYSTERY LINE. WHY IS THIS NEEDED?
exchange.dispatch();
afterDistpach(data);
}
}
private void afterDistpach(FormData data) {
if (data == null) {
toComplete.completeExceptionally(
new UserVisibleException("Parsing of data failed.",
ResponseCodes.BAD_REQUEST));
} else {
toComplete.complete(data);
}
}
}
}
--
CTO, Analytic Spot
44 West Broadway #222
Eugene, OR 97401
analyticspot.com • 425-296-6556
www.linkedin.com/in/oliverdain
7 years, 10 months
Testing custom HttpHandlers
by Bill O'Neil
Hello,
How would you recommend testing custom HttpHanders? The DefaultServer class
in core part of the test code so it is not included in the jar for reuse.
Would it be reasonable to pull testing utils into their own project so it
can be reused? Or would you recommend just mocking a HttpServerExchange and
passing that to the HttpHandler?
Thanks,
Bill
7 years, 10 months
WebSockets static sendBinary methods.and PooledByteBuffers
by Mario Carbajal
>From looking at the source it seems that the WebSockets.sendBinary methods
that take ByteBuffer will take ownership of the buffer, meaning I shouldn't
modify (or return it to a pool) after I pass it to these methods. Is this
correct?
Looking at sendInternal, the buffer passed is then wrapped in a dummy
ImmediatePooledByteBuffer. I could make alternative versions of these
sendBinary methods that take PooledByteBuffer. Allowing me to use pooled
buffers.
Since this functionality is missing it makes me think that there may be a
reason why it shouldn't be done.
7 years, 10 months
Return HTTP Status 503 (Service Unvailable) until Web Application is available.
by Thomas Darimont
Hello group,
(coss-post from keycloak-user Mailing List)
the undertow servlet-container is started pretty early during the startup
of the
wildfly application server. However the initialization of the keycloak
server
application might take a while to complete. Within this period requests
that are
sent to the keycloak endpoints result in responses with HTTP Status Code
404.
Is it possible to configure undertow to return a HTTP Status Code 503
(Service Unvailable)
until the keycloak application startup has completed?
This would ease configuring load-balancers and to avoid showing a file not
found
to users during server restarts.
Cheers,
Thomas
7 years, 10 months
Is it safe to ignore this DEBUG message?
by Miere Teixeira
Hi there!
I've changed the way my HttpHandlers are reading the body content (JSON) on
POST requests, reading them asynchronously as explained here
<http://lists.jboss.org/pipermail/undertow-dev/2016-February/001503.html>.
Since then, my application log started to display messages like the
following one:
18:28:20.807 [XNIO-1 I/O-4] DEBUG io.undertow.request - UT005035: Closing
channel because of parse timeout for remote address /0:0:0:0:0:0:0:1:51781
Is it safe to ignore it? Is there something I should pay attention to use
exchange.getRequestReceiver().receiveFullBytes?
Regards!
Miere
--
Miere Teixeira
7 years, 10 months
when exactly are the headers and such written to the client?
by Michael Grove
I'm using EncodingHandler for gzip encoding of responses and I'm not seeing
the header on the client, but I have a breakpoint in
AllowedContentEncodings L95, and it's definitely hit, but I'm wondering if
it's hit after the initial part of the response is written so that header
isnt ever sent.
My handler dispatches to a worker thread if need be, does the biz logic,
calls startBlocking on the exchange, sets the status code and other headers
like Content-Type, and then writes the results to the stream from
HttpServerExchange#getOutputStream before calling endExchange.
I can see the Content-Type header correctly set, but not Content-Encoding.
The javadocs say they're written when the first write is initiated, but I
have't managed to find where that is, specifically in relation to the
EncodingHandler. Hoping someone can point me in the right direction or with
any luck, have a guess at what I've messed up.
Thanks.
Mike
7 years, 11 months
Resource Handling Revisited
by Hicks, Matt
Previously I've asked about streaming a single file back to the client and
got some good insight as to how to accomplish this with `transferFrom`, but
this misses out on all the extra features like resuming transfers, cached
content, etc. It would be very nice Undertow offered a static utility
method to serve up File, Path, and URL providing all of this functionality
that is currently contained in ResourceHandler (
https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io...
).
I don't think it would be difficult to extract all of that out of the
private method and simply have ResourceHandler call the static method.
Stuart, what do you think?
I'd even be willing to do the leg-work if you'd be willing to accept a PR
for it.
7 years, 11 months
IO and Worker Thread based on custom preferences
by tone randomnaja
Hi there !
Undertow has `IO Thread` and `Worker Thread` configuration (<subsystem
xmlns="urn:jboss:domain:io:1.1"><worker name="default".....) which could be
bounded per Listener (<http-listener....).
In my case I have 1 Listenner (AJP) and 1 Application (EAR),
I'd like to be able to priority and manage Worker Thread base on some
preferences, such as URL path.
Above for a reason of controlling the load of specific URL (under the same
Web Context).
Any suggestions or ideas ?
7 years, 11 months