Remove Content-* response headers for error handling

Prior to this commit, when WebFlux handlers added `"Content-*"` response
headers and an error happened while handling the request, all those
headers would not be cleared from the response before error handling.

This commit clears those headers from the response in two places:
* when invoking the handler and adapting the response
* when writing the response body

Not removing those headers might break HTTP clients since they're given
wrong information about how to interpret the HTTP response body: the
error response body might be very different from the original one.

Fixes gh-24238
This commit is contained in:
Brian Clozel
2020-01-06 16:39:14 +01:00
parent 59ade91694
commit f9c1565f4e
4 changed files with 53 additions and 21 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -1827,6 +1827,22 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
return new String(encodedBytes, charset);
}
/**
* Remove the well-known {@code "Content-*"} HTTP headers from the given instance.
* <p>Such headers should be cleared, if possible, from the response if the intended
* body can't be written due to errors.
* @since 5.2.3
*/
public static void clearContentHeaders(HttpHeaders headers) {
headers.remove(HttpHeaders.CONTENT_DISPOSITION);
headers.remove(HttpHeaders.CONTENT_ENCODING);
headers.remove(HttpHeaders.CONTENT_LANGUAGE);
headers.remove(HttpHeaders.CONTENT_LENGTH);
headers.remove(HttpHeaders.CONTENT_LOCATION);
headers.remove(HttpHeaders.CONTENT_RANGE);
headers.remove(HttpHeaders.CONTENT_TYPE);
}
// Package-private: used in ResponseCookie
static String formatDate(long date) {
Instant instant = Instant.ofEpochMilli(date);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -181,21 +181,22 @@ public abstract class AbstractServerHttpResponse implements ServerHttpResponse {
if (body instanceof Mono) {
return ((Mono<? extends DataBuffer>) body).flatMap(buffer ->
doCommit(() -> writeWithInternal(Mono.just(buffer)))
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release));
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release))
.doOnError(t -> clearContentHeaders());
}
return new ChannelSendOperator<>(body, inner -> doCommit(() -> writeWithInternal(inner)))
.doOnError(t -> removeContentLength());
.doOnError(t -> clearContentHeaders());
}
@Override
public final Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
return new ChannelSendOperator<>(body, inner -> doCommit(() -> writeAndFlushWithInternal(inner)))
.doOnError(t -> removeContentLength());
.doOnError(t -> clearContentHeaders());
}
private void removeContentLength() {
private void clearContentHeaders() {
if (!this.isCommitted()) {
this.getHeaders().remove(HttpHeaders.CONTENT_LENGTH);
HttpHeaders.clearContentHeaders(this.getHeaders());
}
}