<div dir="ltr">Hey Sven,<div><br></div><div>What kind of sanitization are you looking for? It should be handling form encoding for you but I don&#39;t think any other type of sanitization.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Feb 7, 2017 at 10:17 AM, Sven Kubiak <span dir="ltr">&lt;<a href="mailto:sven@kubiak.me" target="_blank">sven@kubiak.me</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">




<div dir="ltr" style="font-size:12pt;color:#000000;background-color:#ffffff;font-family:Calibri,Arial,Helvetica,sans-serif">
<p>​​​Anyone?<br>
</p>
<p><br>
</p>
<p>Cheers,<br>
</p>
<p>Sven<br>
</p>
<p><br>
</p>
<div dir="ltr" style="font-size:12pt;color:#000000;background-color:#ffffff;font-family:Calibri,Arial,Helvetica,sans-serif">
<hr style="display:inline-block;width:98%">
<div id="m_8118920607015153860divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><span class=""><b>Von:</b> Sven Kubiak<br>
<b>Gesendet:</b> Mittwoch, 25. Januar 2017 15:58<br>
</span><b>An:</b> Bill O&#39;Neil; Stuart Douglas<br>
<b>Cc:</b> Oliver Dain; <a href="mailto:undertow-dev@lists.jboss.org" target="_blank">undertow-dev@lists.jboss.org</a><br>
<b>Betreff:</b> AW: [undertow-dev] FormDataProcessor ending exchange prematurely</font>
<div> </div>
</div><div><div class="h5">
<div>
<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 style="display:inline-block;width:98%">
<div id="m_8118920607015153860divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>Von:</b> <a href="mailto:undertow-dev-bounces@lists.jboss.org" target="_blank">undertow-dev-bounces@lists.<wbr>jboss.org</a> &lt;<a href="mailto:undertow-dev-bounces@lists.jboss.org" target="_blank">undertow-dev-bounces@lists.<wbr>jboss.org</a>&gt; im Auftrag von Bill O&#39;Neil &lt;<a href="mailto:bill@dartalley.com" target="_blank">bill@dartalley.com</a>&gt;<br>
<b>Gesendet:</b> Mittwoch, 25. Januar 2017 14:53<br>
<b>An:</b> Stuart Douglas<br>
<b>Cc:</b> Oliver Dain; <a href="mailto:undertow-dev@lists.jboss.org" target="_blank">undertow-dev@lists.jboss.org</a><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 -&gt; BlockingHandler -&gt; 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 -&gt; BlockingHandler -&gt; CustomSqlHandler -&gt; DispatchBackToIOThread? This way the final logging of AccessLogHandler is handled in the IO thread.</div>
<div><br>
</div>
<div>I&#39;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">
&lt;<a href="mailto:sdouglas@redhat.com" target="_blank">sdouglas@redhat.com</a>&gt;</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="m_8118920607015153860h5"><br>
<br>
On Wed, Jan 25, 2017 at 3:57 PM, Oliver Dain &lt;<a href="mailto:oliver@analyticspot.com" target="_blank">oliver@analyticspot.com</a>&gt; wrote:<br>
&gt; I have some code for handling file uploads. It uses FormDataProcessor and<br>
&gt; tries to do everything asynchronously. I call &quot;FormDataParser.parse&quot; passing<br>
&gt; in another handler. I&#39;ll call that handler the OnFormDataAvailable. The<br>
&gt; OnFormDataAvailable handler checks to see if it&#39;s on the IO thread. If it<br>
&gt; is, it calls dispatch. Either way, once we&#39;re sure we&#39;re dispatched that<br>
&gt; handler calls yet another handler.<br>
&gt;<br>
&gt; What I&#39;ve seen is that my OnFormDataAvailable handler (the one called by<br>
&gt; parse()) is not on the IO thread so it doesn&#39;t need to call dispatch. And<br>
&gt; yet, the exchange gets ended before the handler it calls is even close to<br>
&gt; complete.<br>
&gt;<br>
&gt; I&#39;ve found a fix, but I don&#39;t understand why it&#39;s necessary. Specifically,<br>
&gt; if OnFormDataAvailable is not on the IO thread when its invoked it calls the<br>
&gt; 0-argument version of &quot;HttpServerExchange.dispatch()<wbr>&quot; (which you&#39;ve told me<br>
&gt; in another conversation shouldn&#39;t ever be necessary). If I do that,<br>
&gt; everything is fine.<br>
&gt;<br>
&gt; For completeness, here&#39;s the complete code:<br>
&gt;<br>
&gt; public class FormDataParsingHandler {<br>
&gt;   private static final Logger log =<br>
&gt; LoggerFactory.getLogger(FormDa<wbr>taParsingHandler.class);<br>
&gt;   private static final FormParserFactory formParserFactory =<br>
&gt; FormParserFactory.builder().bu<wbr>ild();<br>
&gt;   public static final AttachmentKey&lt;FormData&gt; FORM_DATA_ATTACHMENT_KEY =<br>
&gt; AttachmentKey.create(FormData.<wbr>class);<br>
&gt;<br>
&gt;   /**<br>
&gt;    * The only public method - this is what gets exposed as the HttpHandler.<br>
&gt;    */<br>
&gt;   public CompletableFuture&lt;FormData&gt; parseForm(HttpServerExchange exchange)<br>
&gt; {<br>
&gt;     <a href="http://log.info" rel="noreferrer" target="_blank">log.info</a>(&quot;audio file upload request received.&quot;);<br>
&gt;     FormDataParser parser = formParserFactory.createParser<wbr>(exchange);<br>
&gt;     if (parser == null) {<br>
&gt;       log.warn(&quot;No parser found that can handle this content type. Headers<br>
&gt; were: {}&quot;, exchange.getRequestHeaders());<br>
&gt;       throw new UserVisibleException(&quot;No parser for the given content<br>
&gt; type.&quot;, ResponseCodes.BAD_REQUEST);<br>
&gt;     }<br>
&gt;<br>
&gt;     CompletableFuture&lt;FormData&gt; toComplete = new CompletableFuture&lt;&gt;();<br>
&gt;     try {<br>
&gt;       parser.parse(new OnFormDataAvailable(toComplete<wbr>));<br>
&gt;     } catch (Exception e) {<br>
&gt;       log.error(&quot;Error parsing form data:&quot;, e);<br>
&gt;       throw wrapAsUnchecked(e);<br>
&gt;     }<br>
&gt;<br>
&gt;     exchange.addExchangeCompleteL<wbr>istener((ex, nextListener) -&gt; {<br>
&gt;       // Must close the parser so it can free any temporary files that were<br>
&gt; created.<br>
&gt;       try {<br>
&gt;         parser.close();<br>
&gt;       } catch (IOException e) {<br>
&gt;         log.error(&quot;Error closing the FormDataParser. Request was handled<br>
&gt; successfully but temporary files may not &quot;<br>
&gt;             + &quot;have been cleaned up.&quot;, e);<br>
&gt;       }<br>
&gt;       nextListener.proceed();<br>
&gt;     });<br>
&gt;<br>
&gt;     return toComplete;<br>
&gt;   }<br>
&gt;<br>
&gt;   // The FormDataParser calls an HttpHandler when it&#39;s complete so we add a<br>
&gt; silly handler here that does nothing but<br>
&gt;   // complete this method&#39;s future when the form data is available.<br>
&gt;   private static class OnFormDataAvailable implements HttpHandler {<br>
&gt;     private final CompletableFuture&lt;FormData&gt; toComplete;<br>
&gt;<br>
&gt;     private OnFormDataAvailable(Completabl<wbr>eFuture&lt;FormData&gt; toComplete) {<br>
&gt;       this.toComplete = toComplete;<br>
&gt;     }<br>
&gt;<br>
&gt;     @Override<br>
&gt;     public void handleRequest(HttpServerExchan<wbr>ge exchange) throws Exception<br>
&gt; {<br>
&gt;       // Before we complete the future we have to re-dispatch or we&#39;ll fall<br>
&gt; off the end of this method and Undertow<br>
&gt;       // will complete the exchange on our behalf.<br>
&gt;       FormData data = exchange.getAttachment(FormDat<wbr>aParser.FORM_DATA);<br>
&gt;       if (exchange.isInIoThread()) {<br>
&gt;         log.debug(&quot;Was on the IO thread. Re-dispatching.&quot;);<br>
&gt;         exchange.dispatch(SameThreadE<wbr>xecutor.INSTANCE, () -&gt;<br>
&gt; afterDistpach(data));<br>
&gt;       } else {<br>
&gt;         // THIS THE MYSTERY LINE. WHY IS THIS NEEDED?<br>
&gt;         exchange.dispatch();<br>
&gt;         afterDistpach(data);<br>
&gt;       }<br>
&gt;     }<br>
&gt;<br>
&gt;     private void afterDistpach(FormData data) {<br>
&gt;       if (data == null) {<br>
&gt;         toComplete.completeExceptiona<wbr>lly(<br>
&gt;             new UserVisibleException(&quot;Parsing of data failed.&quot;,<br>
&gt; ResponseCodes.BAD_REQUEST));<br>
&gt;       } else {<br>
&gt;         toComplete.complete(data);<br>
&gt;       }<br>
&gt;     }<br>
&gt;   }<br>
&gt; }<br>
&gt;<br>
&gt; --<br>
&gt; CTO, Analytic Spot<br>
&gt; 44 West Broadway #222<br>
&gt; Eugene, OR 97401<br>
&gt; <a href="http://analyticspot.com" rel="noreferrer" target="_blank">analyticspot.com</a> •
<a href="tel:425-296-6556" value="+14252966556" target="_blank">425-296-6556</a><br>
&gt; <a href="http://www.linkedin.com/in/oliverdain" rel="noreferrer" target="_blank">
www.linkedin.com/in/oliverdain</a><br>
&gt;<br>
</div>
</div>
&gt; ______________________________<wbr>_________________<br>
&gt; undertow-dev mailing list<br>
&gt; <a href="mailto:undertow-dev@lists.jboss.org" target="_blank">undertow-dev@lists.jboss.org</a><br>
&gt; <a href="https://lists.jboss.org/mailman/listinfo/undertow-dev" rel="noreferrer" target="_blank">
https://lists.jboss.org/mailma<wbr>n/listinfo/undertow-dev</a><br>
<br>
______________________________<wbr>_________________<br>
undertow-dev mailing list<br>
<a href="mailto:undertow-dev@lists.jboss.org" target="_blank">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/mailma<wbr>n/listinfo/undertow-dev</a></blockquote>
</div>
<br>
</div>
</div>
</div>
</div>
</div></div></div>
</div>

<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><br></blockquote></div><br></div>