|
|
|
@ -51,12 +51,14 @@ import org.springframework.lang.Nullable; |
|
|
|
import org.springframework.util.MimeTypeUtils; |
|
|
|
import org.springframework.util.MimeTypeUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* {@code HttpMessageWriter} that can write a {@link Resource}. |
|
|
|
* {@code HttpMessageWriter} that can write a {@link Resource} from both`` client |
|
|
|
|
|
|
|
* and server perspectives. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>Also an implementation of {@code HttpMessageWriter} with support for writing one |
|
|
|
* <p>From a server perspective, the server-side only write method supports |
|
|
|
* or more {@link ResourceRegion}'s based on the HTTP ranges specified in the request. |
|
|
|
* writing one or more {@link ResourceRegion}'s based on HTTP ranges specified |
|
|
|
|
|
|
|
* in the request. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>For reading to a Resource, use {@link ResourceDecoder} wrapped with |
|
|
|
* <p>To read a Resource, use {@link ResourceDecoder} wrapped with |
|
|
|
* {@link DecoderHttpMessageReader}. |
|
|
|
* {@link DecoderHttpMessageReader}. |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Arjen Poutsma |
|
|
|
* @author Arjen Poutsma |
|
|
|
@ -122,16 +124,19 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter<Resource> { |
|
|
|
if (result != null) { |
|
|
|
if (result != null) { |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
|
|
|
|
Mono<Resource> input = Mono.just(resource); |
|
|
|
Mono<Resource> input = Mono.just(resource); |
|
|
|
DataBufferFactory factory = message.bufferFactory(); |
|
|
|
DataBufferFactory factory = message.bufferFactory(); |
|
|
|
Flux<DataBuffer> body = this.encoder.encode(input, factory, type, message.getHeaders().getContentType(), hints) |
|
|
|
MediaType contentType = message.getHeaders().getContentType(); |
|
|
|
.subscribeOn(Schedulers.boundedElastic()); |
|
|
|
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
Flux<DataBuffer> body = this.encoder.encode(input, factory, type, contentType, hints) |
|
|
|
body = body.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger)); |
|
|
|
.subscribeOn(Schedulers.boundedElastic()); |
|
|
|
} |
|
|
|
|
|
|
|
return message.writeWith(body); |
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
|
|
|
body = body.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return message.writeWith(body); |
|
|
|
})); |
|
|
|
})); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -139,7 +144,10 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter<Resource> { |
|
|
|
* Adds the default headers for the given resource to the given message. |
|
|
|
* Adds the default headers for the given resource to the given message. |
|
|
|
* @since 6.1 |
|
|
|
* @since 6.1 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Mono<Void> addDefaultHeaders(ReactiveHttpOutputMessage message, Resource resource, @Nullable MediaType contentType, Map<String, Object> hints) { |
|
|
|
public Mono<Void> addDefaultHeaders( |
|
|
|
|
|
|
|
ReactiveHttpOutputMessage message, Resource resource, @Nullable MediaType contentType, |
|
|
|
|
|
|
|
Map<String, Object> hints) { |
|
|
|
|
|
|
|
|
|
|
|
return Mono.defer(() -> { |
|
|
|
return Mono.defer(() -> { |
|
|
|
HttpHeaders headers = message.getHeaders(); |
|
|
|
HttpHeaders headers = message.getHeaders(); |
|
|
|
MediaType resourceMediaType = getResourceMediaType(contentType, resource, hints); |
|
|
|
MediaType resourceMediaType = getResourceMediaType(contentType, resource, hints); |
|
|
|
@ -149,16 +157,15 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter<Resource> { |
|
|
|
headers.set(HttpHeaders.ACCEPT_RANGES, "bytes"); |
|
|
|
headers.set(HttpHeaders.ACCEPT_RANGES, "bytes"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (headers.getContentLength() < 0) { |
|
|
|
if (headers.getContentLength() >= 0) { |
|
|
|
return lengthOf(resource) |
|
|
|
|
|
|
|
.flatMap(contentLength -> { |
|
|
|
|
|
|
|
headers.setContentLength(contentLength); |
|
|
|
|
|
|
|
return Mono.empty(); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
return Mono.empty(); |
|
|
|
return Mono.empty(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return lengthOf(resource) |
|
|
|
|
|
|
|
.flatMap(contentLength -> { |
|
|
|
|
|
|
|
headers.setContentLength(contentLength); |
|
|
|
|
|
|
|
return Mono.empty(); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|