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

Handle exceptions in filter implementations #113

Closed
robfletcher opened this issue Nov 10, 2013 · 12 comments
Closed

Handle exceptions in filter implementations #113

robfletcher opened this issue Nov 10, 2013 · 12 comments
Milestone

Comments

@robfletcher
Copy link

If I run into an unrecoverable error in a filter is there a way for me to hand off to an exception handler so that the proxy returns an error response? This is easy enough to do in requestPre and requestPost since I can construct and return my own response but I can't see a way to do it in responsePre or responsePost.

@oxtoacart
Copy link
Collaborator

Oh yeah, that would be useful, wouldn't it?

What if I changed the signature of responsePre and responsePost to allow you to return an HttpObject?

@robfletcher
Copy link
Author

That would work for me

@oxtoacart
Copy link
Collaborator

I've deployed beta4-SNAPSHOT, so this should be available now.

@robfletcher
Copy link
Author

I'm not sure this is really working for me. I'm most likely to be handling an error when dealing with a LastHttpContent instance and by then I will have processed and returned the initial HttpResponse and potentially some HttpContent instances as well. What happens to them? Have they not already been sent back to the client at that point? Should I instead aggregate everything and return a single FullHttpResponse?

What I'm seeing in one test is a 200 response and in another an exception is thrown inside LittleProxy that I've pasted in below. In both cases the behavior should really be the same as I'm testing two variations of the same condition so there's more than likely something I'm doing incorrectly.

java.lang.ClassCastException: io.netty.handler.codec.http.LastHttpContent$1 cannot be cast to io.netty.handler.codec.http.HttpRequest
    at org.littleshoot.proxy.impl.ClientToProxyConnection.readHTTPInitial(ClientToProxyConnection.java:1)
    at org.littleshoot.proxy.impl.ProxyConnection.readHTTP(ProxyConnection.java:143)
    at org.littleshoot.proxy.impl.ProxyConnection.read(ProxyConnection.java:130)
    at org.littleshoot.proxy.impl.ProxyConnection.channelRead0(ProxyConnection.java:563)
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:98)
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
    at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:253)
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
    at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
    at org.littleshoot.proxy.impl.ProxyConnection$RequestReadMonitor.channelRead(ProxyConnection.java:691)
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:173)
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
    at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86)
    at org.littleshoot.proxy.impl.ProxyConnection$BytesReadMonitor.channelRead(ProxyConnection.java:668)
    at io.netty.chan

@oxtoacart
Copy link
Collaborator

Can you tell me a little bit more about your use case please? If you detect an error condition on the LastHttpContent, do you want to have sent anything to the client? If not, then you are correct that you'll need to aggregate everything before filtering. This is already supported in LittleProxy by having your HttpFiltersSource.getMaximumResponseBufferSizeInBytes() method return a positive value. This will cause LittleProxy to decompress and aggregate the response so that by the time it gets to your filter, you're dealing with a FullHttpResponse.

@robfletcher
Copy link
Author

In my case if anything goes wrong during response processing it's catastrophic. All I'd really like is to get a 502 back to say the proxy has experienced an error. Right now the connection aborts.

@oxtoacart
Copy link
Collaborator

In that case, I think HttpFiltersSource.getMaximumResponseBufferSizeInBytes() is what you need. Just set that to something bigger than any response that you anticipate. In your filter, you should then receive a FullHttpResponse, which you can then replace with a 502.

@oxtoacart
Copy link
Collaborator

@robfletcher Let me know if this gets you what you need. If not, let's figure out what will work.

@alexnederlof
Copy link

@oxtoacart Not sure if my request is exactly the same but I did not want to create a duplicate. For the project I'm working on I would like to modify the responses so that I can insert JavaScript into HTML from a server. Would this be possible with this fix? I don't see a way of doing this with the latest release. Let me know If I have to file a separate issue. I could also try to provide a fix if needed, although that would take some time. Thanks!

@oxtoacart
Copy link
Collaborator

@alexnederlof Yes, this should work for you.

In your HttpFiltersSource, implement getMaximumResponseBufferSize() and have it return a value large enough to hold your largest responses in memory.

Then, in your HttpFilters implementation, implement responsePre(). If you set a non-zero response buffer size, the HttpObject handed to your responsePre method will be a FullHttpResponse, whose body you can access using the content() method. You can then either manipulate the content ByteBuf directly or better yet, just create a new DefaultFullHttpResponse with your modified content.

@alexnederlof
Copy link

Nice! I'll give it a shot. Thanks for the quick reply!

@twistedpair
Copy link

If you're using Selenium, or any browser for that matter, you can just pass the PAC file name into the Selenium config or the browser startup switches and use a basic JS function to ignore the Websockets connections (e.g. URL starts with wss: or ws:) that LittleProxy doesn't support and can cause this issue.

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

No branches or pull requests

4 participants