<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" style="display:none"><!-- p { margin-top: 0px; margin-bottom: 0px; }--></style>
</head>
<body dir="ltr" style="font-size:12pt;color:#000000;background-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;">
<p>Hi,<br>
</p>
<p><br>
</p>
<p>sorry, for a kind of off-topic question, but as the FormDataProcessor is the topic here, I was wondering if there is already some kind of data sanitization​ in the core form handling of Undertow. If not, which handler is a good starting point to hook into
for this?<br>
</p>
<p><br>
</p>
<p>Best regards,<br>
</p>
<p>Sven<br>
</p>
<p><br>
</p>
<div style="color: rgb(33, 33, 33);">
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>Von:</b> undertow-dev-bounces@lists.jboss.org <undertow-dev-bounces@lists.jboss.org> im Auftrag von Bill O'Neil <bill@dartalley.com><br>
<b>Gesendet:</b> Mittwoch, 25. Januar 2017 14:53<br>
<b>An:</b> Stuart Douglas<br>
<b>Cc:</b> Oliver Dain; undertow-dev@lists.jboss.org<br>
<b>Betreff:</b> Re: [undertow-dev] FormDataProcessor ending exchange prematurely</font>
<div> </div>
</div>
<div>
<div dir="ltr">Hey Stuart, your last response reminded me of of a question I had hopefully its not unrelated. I was curious how and when you should dispatch back to the IO thread. For example lets say we have a simple handler that does a SQL query that is composed
with the AccessLogHandler.
<div><br>
</div>
<div>AccessLogHandler -> BlockingHandler -> CustomSqlHandler In this approach I believe the final access log statement will be logged from the worker thread not the initial IO thread.</div>
<div><br>
</div>
<div>Is it possible / recommended to kick back to an IO thread once blocking is complete?</div>
<div><br>
</div>
<div>AccessLogHandler -> BlockingHandler -> CustomSqlHandler -> DispatchBackToIOThread? This way the final logging of AccessLogHandler is handled in the IO thread.</div>
<div><br>
</div>
<div>I'm not very familiar with the best ways to mix the nonblocking and blocking handlers.</div>
<div><br>
</div>
<div><br>
</div>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">On Wed, Jan 25, 2017 at 12:24 AM, Stuart Douglas <span dir="ltr">
<<a href="mailto:sdouglas@redhat.com" target="_blank">sdouglas@redhat.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex; border-left:1px #ccc solid; padding-left:1ex">
The handler is executed<br>
io.undertow.server.Connectors#<wbr>executeRootHandler, which means that<br>
when the call stack returns the exchange will be ended.<br>
<br>
Conceptually this is similar to how dispatching to a thread pool<br>
works, when you call dispatch(HttpHandler) the exchange will be ended<br>
when the call stack returns, even though you are no longer on the IO<br>
thread (unless you call dispatch again).<br>
<br>
Stuart<br>
<div>
<div class="h5"><br>
<br>
On Wed, Jan 25, 2017 at 3:57 PM, Oliver Dain <<a href="mailto:oliver@analyticspot.com">oliver@analyticspot.com</a>> wrote:<br>
> I have some code for handling file uploads. It uses FormDataProcessor and<br>
> tries to do everything asynchronously. I call "FormDataParser.parse" passing<br>
> in another handler. I'll call that handler the OnFormDataAvailable. The<br>
> OnFormDataAvailable handler checks to see if it's on the IO thread. If it<br>
> is, it calls dispatch. Either way, once we're sure we're dispatched that<br>
> handler calls yet another handler.<br>
><br>
> What I've seen is that my OnFormDataAvailable handler (the one called by<br>
> parse()) is not on the IO thread so it doesn't need to call dispatch. And<br>
> yet, the exchange gets ended before the handler it calls is even close to<br>
> complete.<br>
><br>
> I've found a fix, but I don't understand why it's necessary. Specifically,<br>
> if OnFormDataAvailable is not on the IO thread when its invoked it calls the<br>
> 0-argument version of "HttpServerExchange.dispatch()<wbr>" (which you've told me<br>
> in another conversation shouldn't ever be necessary). If I do that,<br>
> everything is fine.<br>
><br>
> For completeness, here's the complete code:<br>
><br>
> public class FormDataParsingHandler {<br>
> private static final Logger log =<br>
> LoggerFactory.getLogger(<wbr>FormDataParsingHandler.class);<br>
> private static final FormParserFactory formParserFactory =<br>
> FormParserFactory.builder().<wbr>build();<br>
> public static final AttachmentKey<FormData> FORM_DATA_ATTACHMENT_KEY =<br>
> AttachmentKey.create(FormData.<wbr>class);<br>
><br>
> /**<br>
> * The only public method - this is what gets exposed as the HttpHandler.<br>
> */<br>
> public CompletableFuture<FormData> parseForm(HttpServerExchange exchange)<br>
> {<br>
> <a href="http://log.info" rel="noreferrer" target="_blank">log.info</a>("audio file upload request received.");<br>
> FormDataParser parser = formParserFactory.<wbr>createParser(exchange);<br>
> if (parser == null) {<br>
> log.warn("No parser found that can handle this content type. Headers<br>
> were: {}", exchange.getRequestHeaders());<br>
> throw new UserVisibleException("No parser for the given content<br>
> type.", ResponseCodes.BAD_REQUEST);<br>
> }<br>
><br>
> CompletableFuture<FormData> toComplete = new CompletableFuture<>();<br>
> try {<br>
> parser.parse(new OnFormDataAvailable(<wbr>toComplete));<br>
> } catch (Exception e) {<br>
> log.error("Error parsing form data:", e);<br>
> throw wrapAsUnchecked(e);<br>
> }<br>
><br>
> exchange.<wbr>addExchangeCompleteListener((<wbr>ex, nextListener) -> {<br>
> // Must close the parser so it can free any temporary files that were<br>
> created.<br>
> try {<br>
> parser.close();<br>
> } catch (IOException e) {<br>
> log.error("Error closing the FormDataParser. Request was handled<br>
> successfully but temporary files may not "<br>
> + "have been cleaned up.", e);<br>
> }<br>
> nextListener.proceed();<br>
> });<br>
><br>
> return toComplete;<br>
> }<br>
><br>
> // The FormDataParser calls an HttpHandler when it's complete so we add a<br>
> silly handler here that does nothing but<br>
> // complete this method's future when the form data is available.<br>
> private static class OnFormDataAvailable implements HttpHandler {<br>
> private final CompletableFuture<FormData> toComplete;<br>
><br>
> private OnFormDataAvailable(<wbr>CompletableFuture<FormData> toComplete) {<br>
> this.toComplete = toComplete;<br>
> }<br>
><br>
> @Override<br>
> public void handleRequest(<wbr>HttpServerExchange exchange) throws Exception<br>
> {<br>
> // Before we complete the future we have to re-dispatch or we'll fall<br>
> off the end of this method and Undertow<br>
> // will complete the exchange on our behalf.<br>
> FormData data = exchange.getAttachment(<wbr>FormDataParser.FORM_DATA);<br>
> if (exchange.isInIoThread()) {<br>
> log.debug("Was on the IO thread. Re-dispatching.");<br>
> exchange.dispatch(<wbr>SameThreadExecutor.INSTANCE, () -><br>
> afterDistpach(data));<br>
> } else {<br>
> // THIS THE MYSTERY LINE. WHY IS THIS NEEDED?<br>
> exchange.dispatch();<br>
> afterDistpach(data);<br>
> }<br>
> }<br>
><br>
> private void afterDistpach(FormData data) {<br>
> if (data == null) {<br>
> toComplete.<wbr>completeExceptionally(<br>
> new UserVisibleException("Parsing of data failed.",<br>
> ResponseCodes.BAD_REQUEST));<br>
> } else {<br>
> toComplete.complete(data);<br>
> }<br>
> }<br>
> }<br>
> }<br>
><br>
> --<br>
> CTO, Analytic Spot<br>
> 44 West Broadway #222<br>
> Eugene, OR 97401<br>
> <a href="http://analyticspot.com" rel="noreferrer" target="_blank">analyticspot.com</a> •
<a href="tel:425-296-6556" value="+14252966556">425-296-6556</a><br>
> <a href="http://www.linkedin.com/in/oliverdain" rel="noreferrer" target="_blank">
www.linkedin.com/in/oliverdain</a><br>
><br>
</div>
</div>
> ______________________________<wbr>_________________<br>
> undertow-dev mailing list<br>
> <a href="mailto:undertow-dev@lists.jboss.org">undertow-dev@lists.jboss.org</a><br>
> <a href="https://lists.jboss.org/mailman/listinfo/undertow-dev" rel="noreferrer" target="_blank">
https://lists.jboss.org/<wbr>mailman/listinfo/undertow-dev</a><br>
<br>
______________________________<wbr>_________________<br>
undertow-dev mailing list<br>
<a href="mailto:undertow-dev@lists.jboss.org">undertow-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/undertow-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/undertow-dev</a></blockquote>
</div>
<br>
</div>
</div>
</div>
</body>
</html>