DataBuffer fixes in View implementations
Closes gh-22754
This commit is contained in:
@@ -35,6 +35,7 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.codec.DecodingException;
|
||||
import org.springframework.core.codec.Hints;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.HttpMessageReader;
|
||||
@@ -200,7 +201,8 @@ public abstract class AbstractMessageReaderArgumentResolver extends HandlerMetho
|
||||
|
||||
HttpMethod method = request.getMethod();
|
||||
if (contentType == null && method != null && SUPPORTED_METHODS.contains(method)) {
|
||||
Flux<DataBuffer> body = request.getBody().doOnNext(o -> {
|
||||
Flux<DataBuffer> body = request.getBody().doOnNext(buffer -> {
|
||||
DataBufferUtils.release(buffer);
|
||||
// Body not empty, back to 415..
|
||||
throw new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -32,7 +32,6 @@ import freemarker.template.ObjectWrapper;
|
||||
import freemarker.template.SimpleHash;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.Version;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -42,6 +41,7 @@ import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.PooledDataBuffer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -184,30 +184,34 @@ public class FreeMarkerView extends AbstractUrlBasedView {
|
||||
protected Mono<Void> renderInternal(Map<String, Object> renderAttributes,
|
||||
@Nullable MediaType contentType, ServerWebExchange exchange) {
|
||||
|
||||
// Expose all standard FreeMarker hash models.
|
||||
SimpleHash freeMarkerModel = getTemplateModel(renderAttributes, exchange);
|
||||
return exchange.getResponse().writeWith(Mono
|
||||
.fromCallable(() -> {
|
||||
// Expose all standard FreeMarker hash models.
|
||||
SimpleHash freeMarkerModel = getTemplateModel(renderAttributes, exchange);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(exchange.getLogPrefix() + "Rendering [" + getUrl() + "]");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(exchange.getLogPrefix() + "Rendering [" + getUrl() + "]");
|
||||
}
|
||||
|
||||
Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext());
|
||||
DataBuffer dataBuffer = exchange.getResponse().bufferFactory().allocateBuffer();
|
||||
try {
|
||||
Charset charset = getCharset(contentType);
|
||||
Writer writer = new OutputStreamWriter(dataBuffer.asOutputStream(), charset);
|
||||
getTemplate(locale).process(freeMarkerModel, writer);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
String message = "Could not load FreeMarker template for URL [" + getUrl() + "]";
|
||||
return Mono.error(new IllegalStateException(message, ex));
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
return Mono.error(ex);
|
||||
}
|
||||
return exchange.getResponse().writeWith(Flux.just(dataBuffer));
|
||||
Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext());
|
||||
DataBuffer dataBuffer = exchange.getResponse().bufferFactory().allocateBuffer();
|
||||
try {
|
||||
Charset charset = getCharset(contentType);
|
||||
Writer writer = new OutputStreamWriter(dataBuffer.asOutputStream(), charset);
|
||||
getTemplate(locale).process(freeMarkerModel, writer);
|
||||
return dataBuffer;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
String message = "Could not load FreeMarker template for URL [" + getUrl() + "]";
|
||||
throw new IllegalStateException(message, ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
throw ex;
|
||||
}
|
||||
})
|
||||
.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release));
|
||||
}
|
||||
|
||||
private Charset getCharset(@Nullable MediaType mediaType) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -37,9 +37,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.scripting.support.StandardScriptEvalException;
|
||||
import org.springframework.scripting.support.StandardScriptUtils;
|
||||
@@ -301,8 +299,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
protected Mono<Void> renderInternal(
|
||||
Map<String, Object> model, @Nullable MediaType contentType, ServerWebExchange exchange) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
return exchange.getResponse().writeWith(Mono.fromCallable(() -> {
|
||||
try {
|
||||
ScriptEngine engine = getEngine();
|
||||
String url = getUrl();
|
||||
@@ -338,8 +335,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
}
|
||||
|
||||
byte[] bytes = String.valueOf(html).getBytes(StandardCharsets.UTF_8);
|
||||
DataBuffer buffer = response.bufferFactory().allocateBuffer(bytes.length).write(bytes);
|
||||
return response.writeWith(Mono.just(buffer));
|
||||
return exchange.getResponse().bufferFactory().wrap(bytes); // just wrapping, no allocation
|
||||
}
|
||||
catch (ScriptException ex) {
|
||||
throw new IllegalStateException("Failed to render script template", new StandardScriptEvalException(ex));
|
||||
@@ -347,7 +343,7 @@ public class ScriptTemplateView extends AbstractUrlBasedView {
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to render script template", ex);
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
protected String getTemplate(String path) throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user