Commit actions are (properly) deferred
Issue: SPR-16597
This commit is contained in:
@@ -45,6 +45,9 @@ public interface ReactiveHttpOutputMessage extends HttpMessage {
|
||||
|
||||
/**
|
||||
* Register an action to apply just before the HttpOutputMessage is committed.
|
||||
* <p><strong>Note:</strong> the supplied action must be properly deferred,
|
||||
* e.g. via {@link Mono#defer} or {@link Mono#fromRunnable}, to ensure it's
|
||||
* executed in the right order, relative to other actions.
|
||||
* @param action the action to apply
|
||||
*/
|
||||
void beforeCommit(Supplier<? extends Mono<Void>> action);
|
||||
|
||||
@@ -209,13 +209,13 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
this.commitActions.add(() -> {
|
||||
applyStatusCode();
|
||||
applyHeaders();
|
||||
applyCookies();
|
||||
this.state.set(State.COMMITTED);
|
||||
return Mono.empty();
|
||||
});
|
||||
this.commitActions.add(() ->
|
||||
Mono.fromRunnable(() -> {
|
||||
applyStatusCode();
|
||||
applyHeaders();
|
||||
applyCookies();
|
||||
this.state.set(State.COMMITTED);
|
||||
}));
|
||||
|
||||
if (writeAction != null) {
|
||||
this.commitActions.add(writeAction);
|
||||
@@ -224,7 +224,7 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse {
|
||||
List<? extends Mono<Void>> actions = this.commitActions.stream()
|
||||
.map(Supplier::get).collect(Collectors.toList());
|
||||
|
||||
return Flux.concat(actions).next();
|
||||
return Flux.concat(actions).then();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -111,28 +111,30 @@ class UndertowServerHttpResponse extends AbstractListenerServerHttpResponse impl
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeWith(File file, long position, long count) {
|
||||
return doCommit(() -> {
|
||||
FileChannel source = null;
|
||||
try {
|
||||
source = FileChannel.open(file.toPath(), StandardOpenOption.READ);
|
||||
StreamSinkChannel destination = this.exchange.getResponseChannel();
|
||||
Channels.transferBlocking(destination, source, position, count);
|
||||
return Mono.empty();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
finally {
|
||||
if (source != null) {
|
||||
return doCommit(() ->
|
||||
Mono.defer(() -> {
|
||||
FileChannel source = null;
|
||||
try {
|
||||
source.close();
|
||||
source = FileChannel.open(file.toPath(), StandardOpenOption.READ);
|
||||
StreamSinkChannel destination = this.exchange.getResponseChannel();
|
||||
Channels.transferBlocking(destination, source, position, count);
|
||||
return Mono.empty();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
return Mono.error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
finally {
|
||||
if (source != null) {
|
||||
try {
|
||||
source.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user