Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with HttpPostRequestEncoder #1293

Closed
xhh11 opened this issue Apr 19, 2013 · 18 comments
Closed

Issue with HttpPostRequestEncoder #1293

xhh11 opened this issue Apr 19, 2013 · 18 comments
Assignees
Labels
Milestone

Comments

@xhh11
Copy link

xhh11 commented Apr 19, 2013

If HttpPostRequestEncoder generates chunks, it won't work. Please try the HttpUpload example.

@normanmaurer
Copy link
Member

@xhh11 can you tell us which version you are using ? A test-case would also help..

@xhh11
Copy link
Author

xhh11 commented Apr 21, 2013

I was using the snapshot build of 4/16.

The client side :

java.nio.channels.ClosedChannelException
    at io.netty.handler.stream.ChunkedWriteHandler.doFlush(ChunkedWriteHandler.java:317)
    at io.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:150)
    at io.netty.channel.DefaultChannelHandlerContext.invokeFlush0(DefaultChannelHandlerContext.java:1293)
    at io.netty.channel.DefaultChannelHandlerContext.write0(DefaultChannelHandlerContext.java:1430)
    at io.netty.channel.DefaultChannelHandlerContext.access$2500(DefaultChannelHandlerContext.java:36)
    at io.netty.channel.DefaultChannelHandlerContext$21.run(DefaultChannelHandlerContext.java:1405)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:338)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:331)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:109)
    at java.lang.Thread.run(Thread.java:722)

and the server side:

io.netty.example.http.upload.HttpUploadServerHandler exceptionCaught
WARNING: 
java.lang.NullPointerException
    at io.netty.example.http.upload.HttpUploadServerHandler.messageReceived(HttpUploadServerHandler.java:186)
    at io.netty.channel.ChannelHandlerUtil.handleInboundBufferUpdated(ChannelHandlerUtil.java:60)
    at io.netty.channel.ChannelInboundMessageHandlerAdapter.inboundBufferUpdated(ChannelInboundMessageHandlerAdapter.java:105)
    at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:912)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:873)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:852)
    at io.netty.channel.ChannelHandlerUtil.handleInboundBufferUpdated(ChannelHandlerUtil.java:69)
    at io.netty.channel.ChannelInboundMessageHandlerAdapter.inboundBufferUpdated(ChannelInboundMessageHandlerAdapter.java:105)
    at io.netty.handler.codec.MessageToMessageCodec.inboundBufferUpdated(MessageToMessageCodec.java:124)
    at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:912)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:873)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:852)
    at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:442)
    at io.netty.handler.codec.ByteToMessageDecoder.inboundBufferUpdated(ByteToMessageDecoder.java:69)
    at io.netty.channel.ChannelInboundByteHandlerAdapter.inboundBufferUpdated(ChannelInboundByteHandlerAdapter.java:51)
    at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:912)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:873)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:852)
    at io.netty.channel.DefaultChannelPipeline.fireInboundBufferUpdated(DefaultChannelPipeline.java:978)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:116)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:434)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:397)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:327)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:109)
    at java.lang.Thread.run(Thread.java:722)

io.netty.handler.codec.http.multipart.HttpPostRequestDecoder$NotEnoughDataDecoderException
    at io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.getBodyHttpDatas(HttpPostRequestDecoder.java:295)
    at io.netty.example.http.upload.HttpUploadServerHandler.readHttpDataAllReceive(HttpUploadServerHandler.java:213)
    at io.netty.example.http.upload.HttpUploadServerHandler.messageReceived(HttpUploadServerHandler.java:177)
    at io.netty.channel.ChannelHandlerUtil.handleInboundBufferUpdated(ChannelHandlerUtil.java:60)
    at io.netty.channel.ChannelInboundMessageHandlerAdapter.inboundBufferUpdated(ChannelInboundMessageHandlerAdapter.java:105)
    at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:912)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:873)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:852)
    at io.netty.channel.ChannelHandlerUtil.handleInboundBufferUpdated(ChannelHandlerUtil.java:69)
    at io.netty.channel.ChannelInboundMessageHandlerAdapter.inboundBufferUpdated(ChannelInboundMessageHandlerAdapter.java:105)
    at io.netty.handler.codec.MessageToMessageCodec.inboundBufferUpdated(MessageToMessageCodec.java:124)
    at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:912)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:873)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:852)
    at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:442)
    at io.netty.handler.codec.ByteToMessageDecoder.inboundBufferUpdated(ByteToMessageDecoder.java:69)
    at io.netty.channel.ChannelInboundByteHandlerAdapter.inboundBufferUpdated(ChannelInboundByteHandlerAdapter.java:51)
    at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:912)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:873)
    at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:852)
    at io.netty.channel.DefaultChannelPipeline.fireInboundBufferUpdated(DefaultChannelPipeline.java:978)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:116)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:434)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:397)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:327)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:109)
    at java.lang.Thread.run(Thread.java:722)

@trustin
Copy link
Member

trustin commented Apr 25, 2013

@fredericBregier, can you take a look?

@trustin
Copy link
Member

trustin commented Apr 25, 2013

I also see the same problem at master just in case it was unclear.

@xhh11
Copy link
Author

xhh11 commented Apr 25, 2013

I tried latest snapshot and the behavior is kind of different.

First, the get request will trigger two messageReceived events, the first time a DefaultHttpRequest and the second an empty LastHttpContent. I remember this was fixed some time ago but somehow it comes back.

Second, when uploading a file, the server generates a HttpPostRequestDecoder$NotEnoughDataDecoderException.

@fredericBregier
Copy link
Member

I'm not enough still familiar with Netty 4.
However, here are some elements that I could say:

  • On Netty 3, Upload is still ok, no error
  • On Netty 4, I can reproduce the error. It seems that the root cause (for the error) is that decoder (server side) is null while it should not. Here are the steps:
  1. HttpRequest "formget=GET" is received (server side)
  2. when the decoder is created (new HttpPostRequestDecoder) it ends with the exception IncompatibleDataDecoderException due to "no body to decode", which means the request is not identified as POST, PUT or PATCH (ok) => decoder is null (correct). Note that the request is not Multipart according to the header (No CONTENT_TYPE at all in the header received)
  3. The request is answeared correctly (in the catch)
  4. HttpContent is then received
  5. but decoder is null => NullPointerException

The issue seems related to the HttpContent passed without corresponding POST/PUT/PATCH request. Probable chunk get request ?

So it might be an issue of:

  • Content_type mis filled (not present in reception on server side, and therefore not set on client side)?
  • but since a HttpContent follows, it should be a chunk mode so ContentType filled?

I may have some more time later on, but as I will be very busy in the following days (for one week at least), it might take too long...

@xhh11
Copy link
Author

xhh11 commented Apr 26, 2013

A note might not be related with this topic. When I tried the HttpUpload example, I saw a warning message :
You don't have Javassist in your class path or you don't have enough permission to load dynamically generated classes. Please check the configuration for better performance.

Is it recommended for Netty to work with Javassist?

@trustin
Copy link
Member

trustin commented Apr 27, 2013

@xhh11, Yes. Javassist in the classpath is recommended.

@trustin
Copy link
Member

trustin commented Apr 27, 2013

@fredericBregier Can you just fix it for us? I don't have much knowledge about multipart form requests nor the code itself.

@ghost ghost assigned fredericBregier Apr 27, 2013
@fredericBregier
Copy link
Member

As I said, I will not be able to work on it before 1 week at least. If this is urgent, someone else could have a look.

I suspect an automatic "chunk" that might be introduced in netty 4 code but no evidence right now. So might be something totally different.

I've seen no difference until now between v4 and v3, except of course netty api, So the reason I point out my "lack" of v4 knowledge as also the possible different behavior on "chunk" operations.

So if not urgent, I may work on it in 1 week at least.

@fredericBregier
Copy link
Member

After looking more in depth, the issue seems to come from a major change in V4 by introducing the EMPTY_LAST_CONTENT in LastHttpContent, and probably in HttpObjectDecoder.

I do not know how this HttpObjectDecoder is supposed to act, so I don't know how to fix it.

It seems the behaviour is:

  1. once all Http is received
  2. the HttpObjectDecoder send a LastHttpContent to close the send

So I believe it should be handle as an "end" marker in the HttpPostRequestDecoder, but as I'm not sure, could someone explain to me what is the behind logic?

@fredericBregier
Copy link
Member

@normanmaurer and @trustin I'm a bit limited here on this issue, since it will need me to go deep in the "new" logic of the HttpObjectDecoder and in particular the LastHttpContent behavior.
I'm quite sure the issue is there, but I still not fully understand (probably due to lack of time) the reason behind.
Can someone explain me the logic?

@normanmaurer
Copy link
Member

@fredericBregier yeah... the LastHttpContent always mark the end of the request/response.

So its like this:
1 x HttpRequest
0-n x HttpContent
1x LastHttpContent

FullHttpContent implements HttpRequest and LastHttpContent to represent a full message.

@fredericBregier
Copy link
Member

@normanmaurer ok, that's almost what I understood. Thank you!

In the next days, I will try to go deep again and fix the V4 if I found how to do it.
Cheers

normanmaurer pushed a commit that referenced this issue May 6, 2013
@normanmaurer
Copy link
Member

@fredericBregier too late... I just fixed it ;)

@xhh11
Copy link
Author

xhh11 commented May 6, 2013

Does your fix included in latest build (174)? I tried the build and the upload example is still not working.

10:25:32.818 [main] DEBUG i.n.u.i.l.InternalLoggerFactory - Using SLF4J as the default logging framework
10:25:32.824 [main] DEBUG i.n.c.MultithreadEventLoopGroup - io.netty.eventLoopThreads: 24
10:25:32.832 [main] DEBUG io.netty.channel.nio.NioEventLoop - io.netty.selectorAutoRebuildThreshold: 512
10:25:32.880 [main] DEBUG i.n.util.internal.PlatformDependent - UID: 1000
10:25:32.881 [main] DEBUG i.n.util.internal.PlatformDependent - Java version: 7
10:25:32.883 [main] DEBUG i.n.util.internal.PlatformDependent0 - java.nio.ByteBuffer.cleaner: available
10:25:32.884 [main] DEBUG i.n.util.internal.PlatformDependent0 - java.nio.Buffer.address: available
10:25:32.885 [main] DEBUG i.n.util.internal.PlatformDependent0 - sun.misc.Unsafe.theUnsafe: available
10:25:32.885 [main] DEBUG i.n.util.internal.PlatformDependent0 - sun.misc.Unsafe.copyMemory: available
10:25:32.886 [main] DEBUG i.n.util.internal.PlatformDependent0 - java.nio.Bits.unaligned: true
10:25:32.886 [main] DEBUG i.n.util.internal.PlatformDependent - sun.misc.Unsafe: available
10:25:32.990 [main] DEBUG i.n.util.internal.PlatformDependent - Javassist: available
10:25:32.990 [main] DEBUG i.n.util.internal.PlatformDependent - io.netty.preferDirect: false
10:25:33.026 [main] DEBUG io.netty.util.ResourceLeakDetector - io.netty.resourceLeakDetection: false
10:25:33.037 [main] DEBUG i.n.buffer.PooledByteBufAllocator - io.netty.allocator.numHeapArenas: 12
10:25:33.037 [main] DEBUG i.n.buffer.PooledByteBufAllocator - io.netty.allocator.numDirectArenas: 12
10:25:33.037 [main] DEBUG i.n.buffer.PooledByteBufAllocator - io.netty.allocator.pageSize: 8192
10:25:33.038 [main] DEBUG i.n.buffer.PooledByteBufAllocator - io.netty.allocator.maxOrder: 11
10:25:33.038 [main] DEBUG i.n.buffer.PooledByteBufAllocator - io.netty.allocator.chunkSize: 16777216
10:25:33.046 [main] DEBUG io.netty.util.NetUtil - Loopback interface: lo
10:25:33.046 [main] DEBUG io.netty.util.NetUtil - Loopback address: /0:0:0:0:0:0:0:1%1 (primary)
10:25:33.046 [main] DEBUG io.netty.util.NetUtil - Loopback address: /127.0.0.1
10:25:33.046 [main] DEBUG io.netty.util.NetUtil - /proc/sys/net/core/somaxconn: 128
HTTP Upload Server at port 8080.
Open your browser and navigate to http://localhost:8080/
10:25:40.826 [nioEventLoopGroup-2-1] DEBUG i.n.u.i.JavassistTypeParameterMatcherGenerator - Generated: io.netty.util.internal.matchers.io.netty.handler.codec.http.HttpObjectMatcher
10:25:40.835 [nioEventLoopGroup-2-1] DEBUG i.n.u.i.JavassistTypeParameterMatcherGenerator - Generated: io.netty.util.internal.matchers.io.netty.handler.codec.http.HttpRequestMatcher
May 06, 2013 10:25:41 AM io.netty.example.http.upload.HttpUploadServerHandler exceptionCaught

WARNING: WELCOME TO THE WILD WILD WEB SERVER

VERSION: HTTP/1.1
REQUEST_URI: http://localhost:8080/formpostmultipart

HEADER: Host=localhost
HEADER: Connection=close
HEADER: Accept-Encoding=gzip,deflate
HEADER: Accept-Charset=ISO-8859-1,utf-8;q=0.7,;q=0.7
HEADER: Accept-Language=fr
HEADER: Referer=http://localhost:8080/formpost
HEADER: User-Agent=Netty Simple Http Client side
HEADER: Accept=text/html,application/xhtml+xml,application/xml;q=0.9,
/*;q=0.8
HEADER: Cookie=my-cookie=foo; another-cookie=bar
HEADER: Content-Type=multipart/form-data; boundary=5a287d4ebc90b901
HEADER: Transfer-Encoding=chunked

COOKIE: another-cookie=bar
COOKIE: my-cookie=foo

Is Chunked: true
IsMultipart: true
Chunks: o
BODY Attribute: Attribute: Mixed: getform=POST

BODY Attribute: Attribute: Mixed: info=first value

BODY Attribute: Attribute: Mixed: secondinfo=secondvalue ���&

BODY Attribute: Attribute: Mixed: thirdinfo=short text

io.netty.buffer.IllegalBufferAccessException
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:114)
at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:48)
at io.netty.buffer.DefaultCompositeByteBuf$Component.freeIfNecessary(DefaultCompositeByteBuf.java:1245)
at io.netty.buffer.DefaultCompositeByteBuf.deallocate(DefaultCompositeByteBuf.java:1501)
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:119)
at io.netty.buffer.DefaultCompositeByteBuf.addComponents0(DefaultCompositeByteBuf.java:203)
at io.netty.buffer.DefaultCompositeByteBuf.(DefaultCompositeByteBuf.java:82)
at io.netty.buffer.Unpooled.wrappedBuffer(Unpooled.java:335)
at io.netty.buffer.Unpooled.wrappedBuffer(Unpooled.java:272)
at io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.offer(HttpPostRequestDecoder.java:358)
at io.netty.example.http.upload.HttpUploadServerHandler.messageReceived(HttpUploadServerHandler.java:180)
at io.netty.channel.ChannelHandlerUtil.handleInboundBufferUpdated(ChannelHandlerUtil.java:60)
at io.netty.channel.ChannelInboundMessageHandlerAdapter.inboundBufferUpdated(ChannelInboundMessageHandlerAdapter.java:100)
at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:944)
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:912)
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:892)
at io.netty.channel.ChannelHandlerUtil.handleInboundBufferUpdated(ChannelHandlerUtil.java:69)
at io.netty.channel.ChannelInboundMessageHandlerAdapter.inboundBufferUpdated(ChannelInboundMessageHandlerAdapter.java:100)
at io.netty.handler.codec.MessageToMessageCodec.inboundBufferUpdated(MessageToMessageCodec.java:114)
at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:944)
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:912)
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:892)
at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:441)
at io.netty.handler.codec.ByteToMessageDecoder.inboundBufferUpdated(ByteToMessageDecoder.java:69)
at io.netty.channel.ChannelInboundByteHandlerAdapter.inboundBufferUpdated(ChannelInboundByteHandlerAdapter.java:46)
at io.netty.channel.DefaultChannelHandlerContext.invokeInboundBufferUpdated(DefaultChannelHandlerContext.java:944)
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated0(DefaultChannelHandlerContext.java:912)
at io.netty.channel.DefaultChannelHandlerContext.fireInboundBufferUpdated(DefaultChannelHandlerContext.java:892)
at io.netty.channel.DefaultChannelPipeline.fireInboundBufferUpdated(DefaultChannelPipeline.java:826)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:116)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:429)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:392)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:322)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:114)
at java.lang.Thread.run(Thread.java:722)

normanmaurer pushed a commit that referenced this issue May 6, 2013
* Also let HttpPostRequestDecoder extends Iterator and let its Exceptiosn extend DecoderException
@normanmaurer
Copy link
Member

@xhh11 this is an other issue.. which I just fixed :) Please try again

@fredericBregier
Copy link
Member

@normanmaurer Thank you!! I have not so much time available and going deep in would have been definitively too long for Netty, as you are so quick to fix issues ! Awesome !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants