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

Prepare a StreamingOutput response when serving file downloads. #1829

Merged
merged 7 commits into from Aug 16, 2018

Conversation

Projects
None yet
2 participants
@baconmania
Contributor

baconmania commented Aug 8, 2018

This prepares a 4k buffer and pipes the HTTP response InputStream to a jax-rs compatible StreamingOutput object.

.get()
.getResponseBodyAsStream();
PerRequestConfig unlimitedTimeout = new PerRequestConfig();
unlimitedTimeout.setRequestTimeoutInMs(-1);

This comment has been minimized.

@baconmania

baconmania Aug 8, 2018

Contributor

The default 60 second timeout on our AsyncHttpClient is insufficient for large file downloads.

@baconmania

baconmania Aug 8, 2018

Contributor

The default 60 second timeout on our AsyncHttpClient is insufficient for large file downloads.

@@ -656,4 +668,56 @@ public Response downloadFileOverProxy(
}
}
private static class NingOutputToJaxRsStreamingOutputWrapper implements AsyncHandler<Void>, StreamingOutput {

This comment has been minimized.

@baconmania

baconmania Aug 8, 2018

Contributor

Fully open to suggestions on a better name for this, heh.

@baconmania

baconmania Aug 8, 2018

Contributor

Fully open to suggestions on a better name for this, heh.

if (wrappedOutputStream == null) {
wrappedOutputStream = output;
try {
requestBuilder.execute(this).get();

This comment has been minimized.

@baconmania

baconmania Aug 8, 2018

Contributor

We need to do it this way because the OutputStream doesn't become available to us until Jersey actually calls write() on this implementation. The alternative would be to begin the proxied request before waiting for Jersey, in which case we'd be back to buffering a potentially large response in memory.

The get() here on the Future is also necessary because Jersey expects write() to be a blocking call, and closes the provided OutputStream after this method returns.

@baconmania

baconmania Aug 8, 2018

Contributor

We need to do it this way because the OutputStream doesn't become available to us until Jersey actually calls write() on this implementation. The alternative would be to begin the proxied request before waiting for Jersey, in which case we'd be back to buffering a potentially large response in memory.

The get() here on the Future is also necessary because Jersey expects write() to be a blocking call, and closes the provided OutputStream after this method returns.

@ssalinas

This comment has been minimized.

Show comment
Hide comment
@ssalinas

ssalinas Aug 9, 2018

Member

🚢

Member

ssalinas commented Aug 9, 2018

🚢

@ssalinas ssalinas added this to the 0.21.0 milestone Aug 9, 2018

@ssalinas ssalinas added the hs_stable label Aug 9, 2018

@ssalinas ssalinas merged commit fa2a287 into master Aug 16, 2018

0 of 2 checks passed

continuous-integration/travis-ci/pr The Travis CI build could not complete due to an error
Details
continuous-integration/travis-ci/push The Travis CI build could not complete due to an error
Details

@ssalinas ssalinas deleted the proper-download-streaming branch Aug 16, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment