jooby-project / jooby

The modular web framework for Java and Kotlin
https://jooby.io
Apache License 2.0
1.7k stars 199 forks source link

File and image transfer problems in 3.1.x #3437

Closed ogrammer closed 4 months ago

ogrammer commented 4 months ago

In Jooby 3.0.10, returning a Path to a file caused no problems. For files that were supposed to be downloaded, they got downloaded. For images, they got rendered. In 3.1.2, trying to download the file is an instant "Failed download" in the browser, and when returning path to images many times the image will not render fully and break in the middle of rendering it.

There is no error in the server log. The error in browser console is NS_ERROR_NET_PARTIAL_TRANSFER. Not using HTTP 2, using jooby-jetty.

In 3.1.2, to work around, returning Files.newInputStream(path) instead of Path appears to work

It isnt much info, but i dont know how to get more info, sorry

jknack commented 4 months ago

Jooby 3.1 moved to jetty 12, so yea it is possible. Can you provide an example to reproduce the bug?

ogrammer commented 4 months ago

@jknack, it is just:

get("/test.zip", ctx -> {
    ctx.setResponseType("application/zip");
    return Path.of("test.zip");
});

Does not work or only works very very rarely.

Changing to this makes it work:

get("/test.zip", ctx -> {
    ctx.setResponseType("application/zip");
    return Files.newInputStream(Path.of("test.zip"));
});
ogrammer commented 4 months ago

My test file is 70 MB for reference but it also happens with small files.

jknack commented 4 months ago

@ogrammer with a zip file of 25mb, the following test executed successfully all times:

public class Issue3437 {
    @ServerTest(iterations = 1000, server = JettyServer.class)
    public void shouldRenderPathInstances(ServerTestRunner runner) {
        runner.define(app -> {
            app.get("/test.zip", ctx -> {
                ctx.setResponseType("application/zip");
                return Path.of("/Users/edgar/Downloads/test.zip");
            });
        }).ready(http -> {
            http.get("/test.zip", rsp -> {
                assertEquals(200, rsp.code());
            });
        });
    }
}
ogrammer commented 4 months ago

@jknack You need to try with firefox not jooby http client. It happens with firefox and i am certain it is a jooby or jetty bug because it does not happen in versions before 3.1.x and also does not happen if I use InputStream instead of Path (which jooby makes into a FileChannel)