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

Carapace 1.8 > java.lang.NullPointerException #412

Closed
hamadodene opened this issue Feb 20, 2023 · 4 comments · Fixed by #418
Closed

Carapace 1.8 > java.lang.NullPointerException #412

hamadodene opened this issue Feb 20, 2023 · 4 comments · Fixed by #418
Labels
bug Something isn't working

Comments

@hamadodene
Copy link
Contributor

In our production setup I have noticed several NPE.
I have no way to reproduce it.

eb 20, 2023 1:30:48 PM reactor.util.Loggers$Slf4JLogger error
SEVERE: [2e92224d-1, L:/xxxxxxxxxx:8089 - R:/xxxxxxxxxxx:43834]
java.lang.NullPointerException: Cannot invoke "java.lang.CharSequence.length()" because "this.text" is null
        at java.base/java.util.regex.Matcher.getTextLength(Matcher.java:1769)
        at java.base/java.util.regex.Matcher.reset(Matcher.java:415)
        at java.base/java.util.regex.Matcher.<init>(Matcher.java:252)
        at java.base/java.util.regex.Pattern.matcher(Pattern.java:1134)
        at java.base/java.util.regex.Pattern.matches(Pattern.java:1175)
        at org.carapaceproxy.core.ProxyRequestsManager$ConnectionsManager.lambda$apply$4(ProxyRequestsManager.java:598)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
        at java.base/java.util.concurrent.ConcurrentHashMap$EntrySpliterator.tryAdvance(ConcurrentHashMap.java:3660)
        at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
        at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
        at org.carapaceproxy.core.ProxyRequestsManager$ConnectionsManager.apply(ProxyRequestsManager.java:599)
        at org.carapaceproxy.core.ProxyRequestsManager.forward(ProxyRequestsManager.java:343)
        at org.carapaceproxy.core.ProxyRequestsManager.processRequest(ProxyRequestsManager.java:161)
        at org.carapaceproxy.core.Listeners.lambda$bootListener$4(Listeners.java:270)
        at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:959)
        at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:677)
        at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:475)
        at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:570)
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at reactor.netty.http.server.AbstractHttpServerMetricsHandler.channelRead(AbstractHttpServerMetricsHandler.java:190)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:214)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at org.carapaceproxy.core.Listeners$2.channelRead(Listeners.java:249)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:336)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:308)
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
        at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:800)
        at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:499)
        at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:397)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:833)

@hamadodene hamadodene added the bug Something isn't working label Feb 20, 2023
@hamadodene
Copy link
Contributor Author

   Map.Entry<ConnectionPoolConfiguration, ConnectionProvider> selectedPool = connectionPools.entrySet().stream()
                    .filter(e -> Pattern.matches(e.getKey().getDomain(), hostName))
                    .findFirst()
                    .orElse(defaultConnectionPool);

This exception is about the Filter and it seems that e.getKey().getDomain() returns null.
Can this be possible? @pv3nturi ?

@pv3ntur1
Copy link
Contributor

According to the stacktrace, the NPE is because hostName (the hostname in the request header HOST) is null

@pv3ntur1 pv3ntur1 reopened this Mar 28, 2023
@hamadodene
Copy link
Contributor Author

hamadodene commented Mar 28, 2023

Yes I agree with you.
I reproduced it with a unit test.
Host header in a valid http1.1 request should never be null. So it should always be valued.

Probably these requests are http1.0 requests. or simply an incomplete request.

In my opinion, in this case we should respond with a "400 Bad request" or in any case the request shouldn't be handled completely.

@aluccaroni what do you think about it?

@hamadodene
Copy link
Contributor Author

hamadodene commented Mar 29, 2023

I was able to reproduce the problem also manually directly from the browser.
The problem can be reproduced if these conditions are met:

  1. You have more than 1 connection pool (If you only have the default connection pool you have an error elsewhere in the code)

  2. We have a route that accepts all requests without a particular filter on the HOST header. Otherwise the request returns 404 (since in our specific case we match using Header Host in the route) because if Header host is null it is set as default "". This causes a 404 to be returned as there are no other routes.

  3. You have an empty HOST header

As a workaround you can simply create a route that returns 404 or other in case of null Host Header. Something like:

route.1.action=404notfound
route.1.enabled=true
route.1.id=missingHeaderHostRoute
route.1.match=request.headers.host ~ "^.{0}$"

the 404notfound action is an action that returns an html error page with a 404 code.

But in my opinion the Fix should be done directly from code. A NullPointerException is not acceptable in this specific case.

We can create an specific action BadRequest with errore code 400 and if Header host is not present we can redirect

We can handle it as for 404 NotFound. We can create a 400 BadRequest action and if Header host is not present in the request we return a BadRequest error page (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants