-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Fix NPE on null host when checking virtual host #10922
Comments
Hi, can you share your |
Use the `Request.getServerName` static and check for null host.
Can you try to branch associated with PR #10923 to see if it fixes your problem? |
Hi @gregw , <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_10_0.dtd">
<Configure id="wac" class="org.eclipse.jetty.ee8.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war"><Property name="jetty.webapps"/>/root.war</Set>
<Set name="virtualHosts">
<Array type="java.lang.String">
<Item>hello</Item>
<Item>www.example.com</Item>
</Array>
</Set>
</Configure> The servlet is very simple package com.example.hello;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
PrintWriter out = res.getWriter();
out.println("Hello, world!");
out.close();
} The web.xml <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
metadata-complete="true" version="4.0"
>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.example.hello.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app> Current status? In the process of creating the repro we suspect that we may be blaming the worng tool and haproxy health check may be doing something funky ... Jetty is behind haproxy for SSL processing offload in production. Our haproxy server line is as follows,, maybe someone can help to convert it to an equivalent curl command line. Haproxy configuration: Jetty works as expected with We're investigating the equivalent curl command to haproxy's health probe. |
I am sorry I can not because I don;t Git:( |
Use the `Request.getServerName` static and check for null host.
@sbordet any idea how I can easily test this with h2 and/or haproxy in a reliable way? Also any idea how a h2 request could have a null host? |
@gregw I can't get a tcp dump even running as root in my VM because of I find it interesting that requestlog was able to tell us the host (www.jetty10922.com) ... <?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Set name="RequestLog">
<New id="RequestLog" class="org.eclipse.jetty.server.CustomRequestLog">
<!-- Writer -->
<Arg>
<New class="org.eclipse.jetty.server.Slf4jRequestLogWriter" />
</Arg>
<!-- Format String -->
<Arg>
<Property name="jetty.customrequestlog.formatString">
<Default>
%{client}a - %u "%r" %{HOST}i %s %O "%{Referer}i"
</Default>
</Property>
</Arg>
</New>
</Set>
</Configure> haproxy server configuration default
option forwardfor if-none
option httpchk GET /check
backend be_jetty
acl is_logout var(txn.path) -i -m sub /logout
## Failure
http-check send meth GET uri /check hdr host www.jetty10922.com
http-request del-header x-real-ip
http-response set-header Clear-Site-Data '"*"' if is_logout
server s1 services.:8080 proto h2 send-proxy-v2 check cookie dynamic 2023-11-28 10:18:44.059:INFO :oe.jetty:main: Virtual threads are enabled.
2023-11-28 10:18:44.236:INFO :oejs.Server:main: jetty-12.0.3; built: 2023-10-27T03:25:22.284Z; git: a873259fd5af141dedaa6c7fa8fe8fbdedce0d61; jvm 21.0.1+12-LTS
2023-11-28 10:18:44.254:INFO :oejdp.ScanningAppProvider:main: Deployment monitor core in [file:///home/admin/jetty12/jetty.base/webapps/] at intervals 1s
2023-11-28 10:18:44.259:WARN :oejdp.ScanningAppProvider:main: class org.eclipse.jetty.deploy.providers.ContextProvider@e853c382[file:///home/admin/jetty12/jetty.base/webapps/] no environment for App@14912267[ee8,null,/home/admin/jetty12/jetty.base/webapps/root.xml], ignoring
2023-11-28 10:18:44.262:INFO :oejdp.ScanningAppProvider:main: Deployment monitor ee8 in [file:///home/admin/jetty12/jetty.base/webapps/] at intervals 1s
2023-11-28 10:18:44.262:INFO :oejd.DeploymentManager:main: addApp: App@401446b4[ee8,null,/home/admin/jetty12/jetty.base/webapps/root.xml]
2023-11-28 10:18:44.287:INFO :oejs.DefaultSessionIdManager:main: Session workerName=node0
2023-11-28 10:18:44.477:INFO :oejsh.ContextHandler:main: Started oeje8n.ContextHandler$CoreContextHandler@594f2763{root,/,b=file:///home/admin/jetty12/jetty.base/tmp/jetty-0_0_0_0-8080-root_war-_-hello-10283893731801770771/webapp/,a=AVAILABLE,vh=[hello,www.example.com],h=oeje8n.ContextHandler$CoreContextHandler$CoreToNestedHandler@78809848{STARTED}}
2023-11-28 10:18:44.494:INFO :oejs.AbstractConnector:main: Started ServerConnector@c5718917{[proxy], ([proxy], http/1.1, h2c)}{0.0.0.0:8080}
2023-11-28 10:18:44.506:INFO :oejs.Server:main: Started oejs.Server@70c2200d{STARTING}[12.0.3,sto=5000] @904ms
2023-11-28 10:18:48.858:WARN :oejs.Response:qtp408482683-virtual-1: writeError: status=500, message=java.lang.NullPointerException: Cannot invoke "java.lang.String.equalsIgnoreCase(java.lang.String)" because "host" is null, response=ErrorResponse@c7d1c746{500,GET@b7d675b3 https:/check HTTP/2.0}
java.lang.NullPointerException: Cannot invoke "java.lang.String.equalsIgnoreCase(java.lang.String)" because "host" is null
at org.eclipse.jetty.server.handler.ContextHandler.checkVirtualHost(ContextHandler.java:752)
at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:774)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:151)
at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:594)
at org.eclipse.jetty.server.Server.handle(Server.java:179)
at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:649)
at org.eclipse.jetty.util.thread.Invocable$ReadyTask.run(Invocable.java:105)
at org.eclipse.jetty.http2.server.internal.HttpStreamOverHTTP2$1.run(HttpStreamOverHTTP2.java:129)
at java.base/java.util.concurrent.ThreadPerTaskExecutor$TaskRunner.run(Unknown Source)
at java.base/java.lang.VirtualThread.run(Unknown Source)
2023-11-28 10:18:48.864:INFO :oejs.RequestLog:qtp408482683-virtual-1: 192.168.120.100 - - "GET /check HTTP/2.0" www.jetty10922.com 500 0 "-" Apologies for not being able to get a tcpdump. Thanks again for looking at this. |
@a1730 can you enable DEBUG logging on the server, and paste/attach the logs here? HTTP/2 requests cannot have an empty host, so it's something else. If you use |
Summary of tests
Please note Jetty.xml was unchanged for the tests <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://eclipse.dev/jetty/configure_10_0.dtd">
<Configure id="wac" class="org.eclipse.jetty.ee8.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="war"><Property name="jetty.webapps"/>/root.war</Set>
<Set name="virtualHosts">
<Array type="java.lang.String">
<Item>hello</Item>
<Item>www.example.com</Item>
</Array>
</Set>
</Configure> @sbordet, |
So, we decided to send a covered server services.innov8.cglcons.com (added server for SSL certificate) backend be_jetty
########### right here
http-check send ver HTTP/1.1 meth GET uri /check hdr host services.innov8.cglcons.com
server s1 services.:8080 proto h2 check 2023-11-28 14:26:01.253:INFO :oe.jetty:main: Virtual threads are enabled.
2023-11-28 14:26:01.425:INFO :oejs.Server:main: jetty-12.0.3; built: 2023-10-27T03:25:22.284Z; git: a873259fd5af141dedaa6c7fa8fe8fbdedce0d61; jvm 21.0.1+12-LTS
2023-11-28 14:26:01.435:INFO :oejdp.ScanningAppProvider:main: Deployment monitor core in [file:///home/admin/jetty12/jetty.base/webapps/] at intervals 1s
2023-11-28 14:26:01.439:WARN :oejdp.ScanningAppProvider:main: class org.eclipse.jetty.deploy.providers.ContextProvider@3af7fdc[file:///home/admin/jetty12/jetty.base/webapps/] no environment for App@bf58fe1e[ee8,null,/home/admin/jetty12/jetty.base/webapps/root.xml], ignoring
2023-11-28 14:26:01.442:INFO :oejdp.ScanningAppProvider:main: Deployment monitor ee8 in [file:///home/admin/jetty12/jetty.base/webapps/] at intervals 1s
2023-11-28 14:26:01.443:INFO :oejd.DeploymentManager:main: addApp: App@7e2ccf3e[ee8,null,/home/admin/jetty12/jetty.base/webapps/root.xml]
2023-11-28 14:26:01.465:INFO :oejs.DefaultSessionIdManager:main: Session workerName=node0
2023-11-28 14:26:01.654:INFO :oejsh.ContextHandler:main: Started oeje8n.ContextHandler$CoreContextHandler@c0f12fc{root,/,b=file:///home/admin/jetty12/jetty.base/tmp/jetty-0_0_0_0-8080-root_war-_-hello-8591522459426100967/webapp/,a=AVAILABLE,vh=[hello,www.example.com,services.innov8.cglcons.com],h=oeje8n.ContextHandler$CoreContextHandler$CoreToNestedHandler@f6d88737{STARTED}}
2023-11-28 14:26:01.659:INFO :oejs.AbstractConnector:main: Started ServerConnector@13a3793c{[proxy], ([proxy], http/1.1, h2c)}{0.0.0.0:8080}
2023-11-28 14:26:01.671:INFO :oejs.Server:main: Started oejs.Server@fb6a4c9d{STARTING}[12.0.3,sto=5000] @856ms
2023-11-28 14:26:05.772:WARN :oejs.Response:qtp1232113641-virtual-1: writeError: status=500, message=java.lang.NullPointerException: Cannot invoke "java.lang.String.equalsIgnoreCase(java.lang.String)" because "host" is null, response=ErrorResponse@d8592a97{500,GET@6fa216ca https:/check HTTP/2.0}
java.lang.NullPointerException: Cannot invoke "java.lang.String.equalsIgnoreCase(java.lang.String)" because "host" is null
at org.eclipse.jetty.server.handler.ContextHandler.checkVirtualHost(ContextHandler.java:752)
at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:774)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:151)
at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:594)
at org.eclipse.jetty.server.Server.handle(Server.java:179)
at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:649)
at org.eclipse.jetty.util.thread.Invocable$ReadyTask.run(Invocable.java:105)
at org.eclipse.jetty.http2.server.internal.HttpStreamOverHTTP2$1.run(HttpStreamOverHTTP2.java:129)
at java.base/java.util.concurrent.ThreadPerTaskExecutor$TaskRunner.run(Unknown Source)
at java.base/java.lang.VirtualThread.run(Unknown Source)
2023-11-28 14:26:05.778:INFO :oejs.RequestLog:qtp1232113641-virtual-1: 192.168.120.100 - - "GET /check HTTP/2.0" services.innov8.cglcons.com 500 0 "-" However, the following works and we are comfortable proceeding with our tests with this configuration. backend be_jetty
########### right here
http-check send ver HTTP/1.1 meth GET uri /check hdr host services.innov8.cglcons.com
server s1 services.:8080 check 2023-11-28 14:28:35.600:INFO :oe.jetty:main: Virtual threads are enabled.
2023-11-28 14:28:35.785:INFO :oejs.Server:main: jetty-12.0.3; built: 2023-10-27T03:25:22.284Z; git: a873259fd5af141dedaa6c7fa8fe8fbdedce0d61; jvm 21.0.1+12-LTS
2023-11-28 14:28:35.795:INFO :oejdp.ScanningAppProvider:main: Deployment monitor core in [file:///home/admin/jetty12/jetty.base/webapps/] at intervals 1s
2023-11-28 14:28:35.799:WARN :oejdp.ScanningAppProvider:main: class org.eclipse.jetty.deploy.providers.ContextProvider@bfd2fab0[file:///home/admin/jetty12/jetty.base/webapps/] no environment for App@e9ba7ca5[ee8,null,/home/admin/jetty12/jetty.base/webapps/root.xml], ignoring
2023-11-28 14:28:35.802:INFO :oejdp.ScanningAppProvider:main: Deployment monitor ee8 in [file:///home/admin/jetty12/jetty.base/webapps/] at intervals 1s
2023-11-28 14:28:35.803:INFO :oejd.DeploymentManager:main: addApp: App@902a433[ee8,null,/home/admin/jetty12/jetty.base/webapps/root.xml]
2023-11-28 14:28:35.826:INFO :oejs.DefaultSessionIdManager:main: Session workerName=node0
2023-11-28 14:28:36.043:INFO :oejsh.ContextHandler:main: Started oeje8n.ContextHandler$CoreContextHandler@a601b8f{root,/,b=file:///home/admin/jetty12/jetty.base/tmp/jetty-0_0_0_0-8080-root_war-_-hello-8470861502493695068/webapp/,a=AVAILABLE,vh=[hello,www.example.com,services.innov8.cglcons.com],h=oeje8n.ContextHandler$CoreContextHandler$CoreToNestedHandler@b8b12381{STARTED}}
2023-11-28 14:28:36.049:INFO :oejs.AbstractConnector:main: Started ServerConnector@93fdf345{[proxy], ([proxy], http/1.1, h2c)}{0.0.0.0:8080}
2023-11-28 14:28:36.061:INFO :oejs.Server:main: Started oejs.Server@c8dfb2b8{STARTING}[12.0.3,sto=5000] @920ms
2023-11-28 14:28:39.217:INFO :oejs.RequestLog:qtp2134917938-30: 192.168.120.100 - - "GET /check HTTP/1.1" services.innov8.cglcons.com 200 14 "-"
2023-11-28 14:28:41.222:INFO :oejs.RequestLog:qtp2134917938-33: 192.168.120.100 - - "GET /check HTTP/1.1" services.innov8.cglcons.com 200 14 "-"
2023-11-28 14:28:43.226:INFO :oejs.RequestLog:qtp2134917938-30: 192.168.120.100 - - "GET /check HTTP/1.1" services.innov8.cglcons.com 200 14 "-"
2023-11-28 14:28:45.232:INFO :oejs.RequestLog:qtp2134917938-33: 192.168.120.100 - - "GET /check HTTP/1.1" services.innov8.cglcons.com 200 14 "-"
2023-11-28 14:28:46.605:INFO :oejs.RequestLog:qtp2134917938-30: 192.168.120.196 - - "GET /hello HTTP/1.1" services.innov8.cglcons.com 200 14 "-"
2023-11-28 14:28:47.235:INFO :oejs.RequestLog:qtp2134917938-33: 192.168.120.100 - - "GET /check HTTP/1.1" services.innov8.cglcons.com 200 14 "-"
2023-11-28 14:28:47.912:INFO :oejs.RequestLog:qtp2134917938-30: 192.168.120.196 - - "GET /hello HTTP/1.1" services.innov8.cglcons.com 200 14 "-"
2023-11-28 14:28:49.242:INFO :oejs.RequestLog:qtp2134917938-33: 192.168.120.100 - - "GET /check HTTP/1.1" services.innov8.cglcons.com 200 14 "-" Our test client sent /hello to Jetty via haproxy and got a 200 Life is good™ even if it is in HTTP1/1 land. |
Use the `Request.getServerName` static and check for null host.
Wow! That was a very quick fix. |
Jetty version(s)
Jetty Environment
ee8
Java version/vendor
(use: java -version)
openjdk version "21.0.1" 2023-10-17 LTS
OS type/version
Linux Debian/12.2
Linux jetty02 6.1.0-13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.55-1 (2023-09-29) x86_64 GNU/Linux
Description
We have a simple HelloWorld servlet mapped to multiple host names in context.xml that used to work on Jetty-10 but started failing migration tests to Jetty-12. We tracked the problem to new code in Jetty-12. This Jetty-10 code worked but this Jetty-12 based code failed
How to reproduce?
Deploy your hello world servlet with a virtual host (www.example.com), and issue curl request to the jetty server using random host name (random.example.com) .
On Jetty-10 you will get HTTP-404.
However, you will encounter a NPE on Jetty-12:
On Jetty-12, remove all virtual host mapping from context.xml, redeploy, and issue your curl command - Bingo (404).
The culprit is here:
jetty.project/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
Line 752 in a873259
The text was updated successfully, but these errors were encountered: