in dicom_util/src/main/java/com/google/cloud/healthcare/DicomWebClientJetty.java [67:161]
public void stowRs(InputStream in) throws DicomWebException {
try {
log.debug("STOW-RS to: " + stowPath);
HTTP2Client client = new HTTP2Client();
SslContextFactory sslContextFactory = new SslContextFactory.Client();
client.addBean(sslContextFactory);
client.start();
HttpURI uri = new HttpURI(stowPath);
FuturePromise<Session> sessionPromise = new FuturePromise<>();
client.connect(sslContextFactory, new InetSocketAddress(uri.getHost(), CONNECT_PORT),
new ServerSessionListener.Adapter(), sessionPromise);
// Having a low timeout here causes flakyness when used with in transit compression.
// This is likely due to the Stow thread sleeping and then waking up again between
// the connect call and the session promise.get() call.
// Reference: https://github.com/GoogleCloudPlatform/healthcare-dicom-dicomweb-adapter/issues/108
Session session = sessionPromise.get(300, TimeUnit.SECONDS);
// Prepare the request
HttpFields requestFields = new HttpFields();
if (credentials != null) {
credentials.getRequestMetadata();
requestFields.add(HttpHeader.AUTHORIZATION,
"Bearer " + credentials.getAccessToken().getTokenValue());
}
requestFields.add(HttpHeader.CONTENT_TYPE,
"application/dicom");
requestFields.add(HttpHeader.ACCEPT,
"application/dicom+json");
MetaData.Request request = new MetaData.Request("POST", uri, HttpVersion.HTTP_2,
requestFields);
HeadersFrame headersFrame = new HeadersFrame(request, null, false);
// Prepare the listener to receive the HTTP response frames.
final StringBuilder resultBuilder = new StringBuilder();
final CompletableFuture<Integer> responseCodeFuture = new CompletableFuture<>();
final CompletableFuture<Boolean> doneFuture = new CompletableFuture<>();
Stream.Listener responseListener = new Stream.Listener.Adapter() {
@Override
public void onReset(Stream stream, ResetFrame frame) {
doneFuture.complete(false);
}
@Override
public void onHeaders(Stream stream, HeadersFrame frame) {
if (frame.getMetaData() instanceof Response) {
responseCodeFuture.complete(((Response) frame.getMetaData()).getStatus());
}
}
@Override
public void onData(Stream stream, DataFrame frame, Callback callback) {
byte[] bytes = new byte[frame.getData().remaining()];
frame.getData().get(bytes);
resultBuilder.append(new String(bytes, StandardCharsets.UTF_8));
if (frame.isEndStream()) {
doneFuture.complete(true);
}
callback.succeeded();
}
};
FuturePromise<Stream> streamPromise = new FuturePromise<>();
session.newStream(headersFrame, streamPromise, responseListener);
Stream stream = streamPromise.get();
DataStream dataStream = new DataStream(stream, in);
try {
dataStream.send();
} catch (IOException e) {
if (!doneFuture.isDone()) {
throw e;
}
}
doneFuture.get();
client.stop();
int httpStatus = responseCodeFuture.get();
if (httpStatus != HttpStatus.OK_200) {
String resp = resultBuilder.toString();
throw new DicomWebException(
"Http_" + httpStatus + ": " + resp, httpStatus, Status.ProcessingFailure);
}
} catch (Exception e) {
if (e instanceof DicomWebException) {
throw (DicomWebException) e;
}
throw new DicomWebException(e);
}
}