Details
Description
my UI developers have a jnlp file that downloads jars to run on the client. in Jetty 6.1.9 this worked for java 1.5 clients, but in 6.1.18, it does not work as expected. with java 1.5 clients, it complains that the Content-Type is null, and, it is:
This is what the client sends to the server:
mattrose@coltrane:~$ telnet 192.168.70.156 80
Trying 192.168.70.156...
Connected to 192.168.70.156.
Escape character is '^]'.
HEAD /webstart/N-central/jrcc-1.5.jar?version-id=7.0.0.888 HTTP/1.1
pragma: no-cache
accept-encoding: pack200-gzip,gzip
Content-Type: application/x-java-archive; charset=utf-8
User-Agent: JNLP/1.5 javaws/1.5.0_20 (b02) J2SE/1.5.0_20
UA-Java-Version: 1.5.0_20
Host: 192.168.101.108
Accept: text/html, image/gif, image/jpeg, ; q=.2, */; q=.2
Connection: keep-alive
and this is the response from the server:
HTTP/1.1 200 OK
Content-Type: text/html; charset=iso-8859-1
Content-Length: 1403
x-java-jnlp-version-id: 7.0.0.888
Server: Jetty(6.1.9)
But if I send the same thing to a 6.1.18 server, I get this in response:
HTTP/1.1 200 OK
x-java-jnlp-version-id: 7.0.0.892
Content-Length: 0
Server: Jetty(6.1.18)
I tried to figure out why the difference exists, so that I could patch it myself, but I couldn't figure out why the Content-Type: header wasn't getting set in this one circumstance.
-
- testcase.tar.gz
- 25/Aug/09 10:23 AM
- 88 kB
- Matt Rose
-
Hide
- jnlp-servlet.jar
- 26/Aug/09 8:12 AM
- 60 kB
- Matt Rose
-
- META-INF/MANIFEST.MF 0.1 kB
- jnlp/sample/.../JarDiff$JarFile2.class 4 kB
- jnlp/sample/jardiff/JarDiff.class 7 kB
- jnlp/sample/.../JarDiffConstants.class 0.3 kB
- jnlp/sample/jardiff/JarDiffPatcher.class 6 kB
- jnlp/sample/.../Patcher$PatchDelegate.class 0.2 kB
- jnlp/sample/jardiff/Patcher.class 0.4 kB
- jnlp/sample/.../DownloadRequest.class 6 kB
- jnlp/sample/.../DownloadResponse$1.class 0.2 kB
- jnlp/.../DownloadResponse$ByteArrayFileDownloadResponse.class 1 kB
- jnlp/.../DownloadResponse$DiskFileDownloadResponse.class 1 kB
- jnlp/.../DownloadResponse$FileDownloadResponse.class 3 kB
- jnlp/.../DownloadResponse$HeadRequestResponse.class 1 kB
- jnlp/.../DownloadResponse$JnlpErrorResponse.class 1 kB
- jnlp/.../DownloadResponse$NoContentResponse.class 0.5 kB
- jnlp/.../DownloadResponse$NotFoundResponse.class 0.7 kB
- jnlp/.../DownloadResponse$NotModifiedResponse.class 0.7 kB
- jnlp/.../DownloadResponse$ResourceFileDownloadResponse.class 1 kB
- jnlp/sample/.../DownloadResponse.class 3 kB
- jnlp/sample/.../ErrorResponseException.class 0.6 kB
- jnlp/.../JarDiffHandler$JarDiffEntry.class 0.5 kB
- jnlp/.../JarDiffHandler$JarDiffKey.class 1 kB
- jnlp/sample/servlet/JarDiffHandler.class 7 kB
- jnlp/sample/.../JnlpDownloadServlet.class 7 kB
- jnlp/.../JnlpFileHandler$JnlpFileEntry.class 0.7 kB
- jnlp/sample/.../JnlpFileHandler.class 9 kB
- jnlp/sample/servlet/JnlpResource.class 5 kB
- jnlp/sample/servlet/Logger.class 4 kB
- jnlp/sample/.../ResourceCatalog$1.class 3 kB
- jnlp/sample/.../ResourceCatalog$2.class 3 kB
-
- Notepad.jnlp
- 26/Aug/09 8:12 AM
- 2 kB
- Matt Rose
-
Hide
- Notepad__V2.0.894.jar
- 26/Aug/09 8:12 AM
- 34 kB
- Matt Rose
-
- META-INF/MANIFEST.MF 0.1 kB
- ElementTreePanel$1.class 2 kB
- ElementTreePanel$2.class 0.6 kB
- ElementTreePanel$ElementTreeModel.class 2 kB
- ElementTreePanel.class 7 kB
- Notepad$1.class 0.5 kB
- Notepad$ActionChangedListener.class 1 kB
- Notepad$AppCloser.class 0.4 kB
- Notepad$ExitAction.class 0.5 kB
- Notepad$FileLoader$1.class 1.0 kB
- Notepad$FileLoader$2.class 0.7 kB
- Notepad$FileLoader.class 2 kB
- Notepad$FileSaver$1.class 1.0 kB
- Notepad$FileSaver.class 2 kB
- Notepad$NewAction.class 1 kB
- Notepad$OpenAction.class 2 kB
- Notepad$RedoAction.class 1 kB
- Notepad$SaveAction.class 1 kB
- Notepad$ShowElementTreeAction$1.class 0.8 kB
- Notepad$ShowElementTreeAction.class 2 kB
- Notepad$StatusBar.class 0.5 kB
- Notepad$UndoAction.class 1 kB
- Notepad$UndoHandler.class 1.0 kB
- Notepad.class 12 kB
- resources/copy.gif 0.7 kB
- resources/cut.gif 1 kB
- resources/new.gif 0.8 kB
- resources/Notepad.properties 2 kB
- resources/Notepad_fr.properties 0.3 kB
- resources/Notepad_sv.properties 0.3 kB
-
- web.xml
- 26/Aug/09 8:12 AM
- 9 kB
- Matt Rose
Issue Links
- supercedes
-
JETTY-1083
Java 1.5 Webstart with Version download broken
-
Activity
I applied your patch to my source tree, and still no Content-Type.
I'm having my doubts about the GzipFilter being the source of the problem, because I changed the minGzipSize to 1, which should make the response skip the GzipFilter, and I still get the same response. I've asked my Java developer again for a test case, and I'll attach it as soon as I get it.
1. Installation instructions (on Linux)
copy the tarball to a pristine jetty webapps/test directory
untar it:
tar zxf testcase.tar
This contains some example files that show the problem in the "webstart" directory, the jnlp download servlet, and a patch for the web.xml file
patch the web.xml file:
patch -p0 < web-xml.patch
And, you'll find that once you've done that, you can issue a HEAD command on any file in that webstart directory, and it will return with just the RESPONSE, and the Content-Length of 0 and the Server header:
mattrose@coltrane:~$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
HEAD /webstart/Notepad.jnlp HTTP/1.0
HTTP/1.1 200 OK
Content-Length: 0
Server: Jetty(6.1.18)
Connection closed by foreign host.
mattrose@coltrane:~$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
HEAD /webstart/index.html HTTP/1.0
HTTP/1.1 200 OK
Content-Length: 0
Server: Jetty(6.1.18)
Connection closed by foreign host.
This is what the debug log looks like, as you can see, GzipFilter isn't even in the filter chain.
2009-08-25 13:00:17.467::DEBUG: REQUEST /webstart/N-central/jrcc-1.5.jar on org.mortbay.jetty.HttpConnection@f9e48
2009-08-25 13:00:17.468::DEBUG: sessionManager=org.mortbay.jetty.servlet.HashSessionManager@3a9bba
2009-08-25 13:00:17.468::DEBUG: session=null
2009-08-25 13:00:17.468::DEBUG: servlet=JnlpDownloadServlet
2009-08-25 13:00:17.468::DEBUG: chain=null
2009-08-25 13:00:17.468::DEBUG: servlet holder=JnlpDownloadServlet
2009-08-25 13:00:17.469::DEBUG: loaded class jnlp.sample.servlet.ErrorResponseException from ContextLoader@ui(...)
2009-08-25 13:00:17.487::DEBUG: loaded class jnlp.sample.servlet.ResourceCatalog$1 from ContextLoader@ui(...)
2009-08-25 13:00:17.519::DEBUG: loaded class jnlp.sample.servlet.DownloadResponse$JnlpErrorResponse from ContextLoader@ui(...)
2009-08-25 13:00:17.522::DEBUG: loaded class jnlp.sample.servlet.DownloadResponse$HeadRequestResponse from ContextLoader@ui(...)
2009-08-25 13:00:17.523::DEBUG: RESPONSE /webstart/N-central/jrcc-1.5.jar 200
2009-08-25 13:00:25.376::DEBUG: uri=
2009-08-25 13:00:25.376::DEBUG: fields=^M
2009-08-25 13:00:25.376::DEBUG: EXCEPTION
HttpException(400,null,null)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:361)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
2009-08-25 13:00:25.379::DEBUG: BAD
Thanks for the test case. I'm getting an error when I try to run it, though, on a pristine Jetty 6.1.18 distribution:
ayao@ayao-laptop:~$ telnet localhost 8080
Trying ::1...
Connected to localhost.
Escape character is '^]'.
HEAD /webstart/Notepad.jnlp HTTP/1.0
HTTP/1.1 500 Internal Server Error
Content-Length: 0
Server: Jetty(6.1.18)
And in the server log:
2009-08-26 17:17:30.873:/:WARN: Internal error:
java.lang.NullPointerException
at jnlp.sample.servlet.JarDiffHandler.isJavawsVersion(JarDiffHandler.java:160)
at jnlp.sample.servlet.JnlpDownloadServlet.constructResponse(JnlpDownloadServlet.java:178)
at jnlp.sample.servlet.JnlpDownloadServlet.handleRequest(JnlpDownloadServlet.java:111)
at jnlp.sample.servlet.JnlpDownloadServlet.doGet(JnlpDownloadServlet.java:79)
at javax.servlet.http.HttpServlet.doHead(HttpServlet.java:281)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:724)
....
Seems completely unrelated, but have you run into this error before?
And hmm, I agree that GzipFilter doesn't seem involved after all. It was an educated guess on our part based on its effects on the content length when using HEAD, but that looks now to be an unrelated issue. So on to the next theory!
I've been playing around with the testcase a little bit more, and I've figured out a slightly better configuration. I'll attach the files and some more instructions.
It seems like HEAD requests are not being passed on to the JNLP download servlet properly. GET requests work fine, but the response to HEAD requests do not have the same headers that GET responses do. I looked around in the jnlp download servlet, and the code looks good there, and it used to work in Jetty-6.1.9, and there's nothing that's changed in that servlet.
this is 3 of the 4 files I have installed on a build of the jetty-6 branch I checked out yesterday. This same configuration should work for jetty-6.1.18
jnlp-servlet.jar goes in $JETTY_HOME/lib
Notepad.jnlp goes in $JETTY_HOME/webapps/test
Notepad__V2.0.894.jar goes in $JETTY_HOME/webapps/test/webstart
web.xml (to follow), goes in $JETTY_HOME/webapps/test/web.xml
Thanks for the updates!
I've found the reason that the content-type isn't being sent – it is suppressed when a HEAD request would result in an error message (see http://fisheye.codehaus.org/changelog/jetty?cs=3472).
It's masking the presence of an actual error message – a GET of /webstart/Notepad.jnlp (from the previous example/instructions) gives me the NPE I brought up earlier (and the HEAD has a null content type) ; a GET of /Notepad.jnlp works (and so does its HEAD).
Matt,
I have changed jetty-6 trunk so that if an error is produced, you will get the full set of headers, rather than the truncated headers that would have been produced due to the changes to the error handling mentioned in Athena's previous comment.
So the situation is now that that requests to the URL /Notepad.jnlp all work and produces HTTP 200 and a full set of headers.
However, requests to /webstart/Notepad.jnlp produces an error, although with a full set of headers. The error message is reproduced below for your convenience, but I think it has nothing to do with jetty, but something to do with the configuration of the jnlp file itself:
java.lang.NullPointerException at jnlp.sample.servlet.JarDiffHandler.isJavawsVersion(JarDiffHandler.java:160) at jnlp.sample.servlet.JnlpDownloadServlet.constructResponse(JnlpDownloadServlet.java:178) at jnlp.sample.servlet.JnlpDownloadServlet.handleRequest(JnlpDownloadServlet.java:111) at jnlp.sample.servlet.JnlpDownloadServlet.doGet(JnlpDownloadServlet.java:79) at javax.servlet.http.HttpServlet.doHead(HttpServlet.java:281) at javax.servlet.http.HttpServlet.service(HttpServlet.java:724) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.acme.TestFilter.doFilter(TestFilter.java:76) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.servlet.UserAgentFilter.doFilter(UserAgentFilter.java:81) at org.mortbay.servlet.GzipFilter.doFilter(GzipFilter.java:155) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230) at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:536) at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:913) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:405) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
cheers
Jan
We weren't able to duplicate the null content type, but suspect that this could be caused by the GzipFilter. I've just committed a patch to disable the GzipFilter for HEAD requests (it was causing some other tiny issues as well).
But to be sure, a simple test case which reproduces this issue reliably would be very helpful for us to make sure we did get it!
cheers