Ok, so after an hour or two of smashing my face against this problem, it's a bit of a doozy...
I've written a shitty http client that can send Multipart POST requests to a server.
The server I was using to test against was Rapidoid, as it's insanely easy to do anything. (Props for that).
The library I'm writing uses the new Java 11 HttpClient, and as far as I can tell, the problem doesn't lie with that.
The problem:
ERROR | 05/Jan/2019 19:27:03:122 | server1 | org.rapidoid.net.impl.RapidoidWorker | Failed to process message! | error = java.lang.RuntimeException: Error in the response order control! Expected handle: 1, real: 0
java.lang.RuntimeException: Error in the response order control! Expected handle: 1, real: 0
at org.rapidoid.u.U.rte(U.java:423)
at org.rapidoid.u.U.rte(U.java:435)
at org.rapidoid.net.impl.RapidoidConnection.processedSeq(RapidoidConnection.java:276)
at org.rapidoid.net.impl.RapidoidWorker.processNext(RapidoidWorker.java:281)
at org.rapidoid.net.impl.RapidoidWorker.processMsgs(RapidoidWorker.java:216)
at org.rapidoid.net.impl.RapidoidWorker.process(RapidoidWorker.java:208)
at org.rapidoid.net.impl.RapidoidWorker.readOP(RapidoidWorker.java:159)
at org.rapidoid.net.impl.AbstractEventLoop.processKey(AbstractEventLoop.java:93)
at org.rapidoid.net.impl.AbstractEventLoop.insideLoop(AbstractEventLoop.java:146)
at org.rapidoid.net.impl.AbstractLoop.run(AbstractLoop.java:71)
at org.rapidoid.net.impl.RapidoidWorkerThread.run(RapidoidWorkerThread.java:58)
An attempt to describe said problem:
After poking it for a bit, I've determined that the HttpManagedHandlerDecorator
promotes the connection to async, when it shouldn't.
But it does so in an alternating fashion.
So, I chunk up the request, because, well, that's a good thing to do.
When the first chunk comes through, rapidoid processes it without issue.
As it was processing the first chunk, the connection seems to be set to sync
, and it tells the connection
that the seq 0 was handled.
The problem arises when the next seq is handled.
For some reason, HttpManagedHandlerDecorator
sets it to async:
Breakpoint reached
at org.rapidoid.net.impl.RapidoidConnection.async(RapidoidConnection.java:490)
at org.rapidoid.http.handler.HttpManagedHandlerDecorator.handle(HttpManagedHandlerDecorator.java:63)
at org.rapidoid.http.handler.AbstractDecoratingHttpHandler.handle(AbstractDecoratingHttpHandler.java:55)
at org.rapidoid.http.FastHttp.handleIfFound(FastHttp.java:285)
at org.rapidoid.http.FastHttp.onRequest(FastHttp.java:136)
at org.rapidoid.http.FastHttpProtocol.process(FastHttpProtocol.java:59)
at org.rapidoid.net.impl.RapidoidWorker.processNext(RapidoidWorker.java:271)
at org.rapidoid.net.impl.RapidoidWorker.processMsgs(RapidoidWorker.java:216)
at org.rapidoid.net.impl.RapidoidWorker.process(RapidoidWorker.java:208)
at org.rapidoid.net.impl.RapidoidWorker.readOP(RapidoidWorker.java:159)
at org.rapidoid.net.impl.AbstractEventLoop.processKey(AbstractEventLoop.java:93)
at org.rapidoid.net.impl.AbstractEventLoop.insideLoop(AbstractEventLoop.java:146)
at org.rapidoid.net.impl.AbstractLoop.run(AbstractLoop.java:71)
at org.rapidoid.net.impl.RapidoidWorkerThread.run(RapidoidWorkerThread.java:58)
So the connection is now marked as async, and the RapidoidWorker checks if the current request is async, if so, it doesn't care, and continues processing.
Meanwhile, it sets it back to sync, so when the second chunk comes in, the connection errors out, because
it was marked as sync, and as a result, tries to tell the connection that seq 2 was handled, but the
connection was never informed about seq 1, so it throws the error.
Beyond that, I have no idea.
If this wall of text helps in some way, awesome.
Otherwise I'm fine answering any questions you might have.
The client I've written isn't public yet, but I'd be happy to give you the code to take a look.
bug