/** * Apply {@link #beforeCommit(Supplier) beforeCommit} actions, apply the * response status and headers/cookies, and write the response body. * @param writeAction the action to write the response body (may be {@code null}) * @return a completion publisher */ protected Mono<Void> doCommit(@Nullable Supplier<? extends Mono<Void>> writeAction) { if (!this.state.compareAndSet(State.NEW, State.COMMITTING)) { return Mono.empty(); } this.commitActions.add(() -> Mono.fromRunnable(() -> { applyStatusCode(); applyHeaders(); applyCookies(); this.state.set(State.COMMITTED); })); if (writeAction != null) { this.commitActions.add(writeAction); } List<? extends Mono<Void>> actions = this.commitActions.stream() .map(Supplier::get).collect(Collectors.toList()); return Flux.concat(actions).then(); }
@Override public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { return new ChannelSendOperator<>(body, writePublisher -> doCommit(() -> writeWithInternal(writePublisher))) .doOnError(t -> removeContentLength()); }
@Override public void addCookie(ResponseCookie cookie) { Assert.notNull(cookie, "ResponseCookie must not be null"); if (this.state.get() == State.COMMITTED) { throw new IllegalStateException("Can't add the cookie " + cookie + "because the HTTP response has already been committed"); } else { getCookies().add(cookie.getName(), cookie); } }
@Override public Mono<Void> setComplete() { return !isCommitted() ? doCommit(null) : Mono.empty(); }
private void removeContentLength() { if (!this.isCommitted()) { this.getHeaders().remove(HttpHeaders.CONTENT_LENGTH); } }
@Override public final Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) { return new ChannelSendOperator<>(body, writePublisher -> doCommit(() -> writeAndFlushWithInternal(writePublisher))) .doOnError(t -> removeContentLength()); }
/** * A variant of {@link #doCommit(Supplier)} for a response without no body. * @return a completion publisher */ protected Mono<Void> doCommit() { return doCommit(null); }
@Override @SuppressWarnings("ConstantConditions") public HttpStatus getStatusCode() { HttpStatus httpStatus = super.getStatusCode(); if (httpStatus == null) { HttpResponseStatus status = this.response.status(); httpStatus = status != null ? HttpStatus.resolve(status.code()) : null; } return httpStatus; }
@Override public final Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) { return new ChannelSendOperator<>(body, writePublisher -> doCommit(() -> writeAndFlushWithInternal(writePublisher))) .doOnError(t -> removeContentLength()); }
private void removeContentLength() { if (!this.isCommitted()) { this.getHeaders().remove(HttpHeaders.CONTENT_LENGTH); } }
@Override public Mono<Void> setComplete() { return !isCommitted() ? doCommit(null) : Mono.empty(); }
/** * A variant of {@link #doCommit(Supplier)} for a response without no body. * @return a completion publisher */ protected Mono<Void> doCommit() { return doCommit(null); }
@Override @SuppressWarnings("ConstantConditions") public HttpStatus getStatusCode() { HttpStatus httpStatus = super.getStatusCode(); if (httpStatus == null) { HttpResponseStatus status = this.response.status(); httpStatus = status != null ? HttpStatus.resolve(status.code()) : null; } return httpStatus; }
@Override public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { return new ChannelSendOperator<>(body, writePublisher -> doCommit(() -> writeWithInternal(writePublisher))) .doOnError(t -> removeContentLength()); }
@Override public final Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) { return new ChannelSendOperator<>(body, writePublisher -> doCommit(() -> writeAndFlushWithInternal(writePublisher))) .doOnError(t -> removeContentLength()); }
/** * Apply {@link #beforeCommit(Supplier) beforeCommit} actions, apply the * response status and headers/cookies, and write the response body. * @param writeAction the action to write the response body (may be {@code null}) * @return a completion publisher */ protected Mono<Void> doCommit(@Nullable Supplier<? extends Mono<Void>> writeAction) { if (!this.state.compareAndSet(State.NEW, State.COMMITTING)) { return Mono.empty(); } this.commitActions.add(() -> Mono.fromRunnable(() -> { applyStatusCode(); applyHeaders(); applyCookies(); this.state.set(State.COMMITTED); })); if (writeAction != null) { this.commitActions.add(writeAction); } List<? extends Mono<Void>> actions = this.commitActions.stream() .map(Supplier::get).collect(Collectors.toList()); return Flux.concat(actions).then(); }
private void removeContentLength() { if (!this.isCommitted()) { this.getHeaders().remove(HttpHeaders.CONTENT_LENGTH); } }
@Override public Mono<Void> setComplete() { return !isCommitted() ? doCommit(null) : Mono.empty(); }
@Override public void addCookie(ResponseCookie cookie) { Assert.notNull(cookie, "ResponseCookie must not be null"); if (this.state.get() == State.COMMITTED) { throw new IllegalStateException("Can't add the cookie " + cookie + "because the HTTP response has already been committed"); } else { getCookies().add(cookie.getName(), cookie); } }
/** * A variant of {@link #doCommit(Supplier)} for a response without no body. * @return a completion publisher */ protected Mono<Void> doCommit() { return doCommit(null); }