- Notifications
You must be signed in to change notification settings - Fork 240
Open
Labels
Description
Using the HTTP client to directly send a CONNECT request (i.e. not by means of proxy configuration) results in an unhandled decoder error. Reproducer:
;; in aleph.http-test (defn http-connect ([path] (http-connect path nil)) ([path options] (http/connect (make-url path) (merge (default-request-options) {:pool *pool*} options)))) (deftest test-connect (with-http1-server basic-handler {} (is (= string-response (bs/to-string (:body @(http-connect "/string")))))))This fails with
FAIL in (test-connect) (http_test.clj:325) - http1 expected: (= string-response (bs/to-string (:body (clojure.core/deref (http-connect "/string"))))) actual: (not (= "String!" "")) And the following exception is logged:
1142576 tid=624 WARN client - error in HTTP client java.lang.ClassCastException: io.netty.buffer.PooledUnsafeDirectByteBuf cannot be cast to io.netty.handler.codec.DecoderResultProvider at aleph.http.common$decoder_failed_QMARK_.invokeStatic(common.clj:237) at aleph.http.common$decoder_failed_QMARK_.invoke(common.clj:237) at aleph.http.client$http1_client_handler$reify__19484.channelRead(client.clj:209) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:280) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at manifold.executor$thread_factory$reify__12656$f__12657.invoke(executor.clj:71) at clojure.lang.AFn.run(AFn.java:22) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:750) It looks like Netty special-cases CONNECT requests somehow so that the message read from the channel is not a DecoderResultProvider but a raw byte buffer instead. It's questionable whether anyone would ever send a CONNECT request directly like this but given that we expose it as a first-class API via aleph.http/connect, we should probably do something about it.