Search in sources :

Example 1 with Hints

use of org.springframework.core.codec.Hints in project spring-framework by spring-projects.

the class MultipartHttpMessageWriter method writeMultipart.

private Mono<Void> writeMultipart(MultiValueMap<String, ?> map, ReactiveHttpOutputMessage outputMessage, @Nullable MediaType mediaType, Map<String, Object> hints) {
    byte[] boundary = generateMultipartBoundary();
    mediaType = getMultipartMediaType(mediaType, boundary);
    outputMessage.getHeaders().setContentType(mediaType);
    LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Encoding " + (isEnableLoggingRequestDetails() ? LogFormatUtils.formatValue(map, !traceOn) : "parts " + map.keySet() + " (content masked)"));
    DataBufferFactory bufferFactory = outputMessage.bufferFactory();
    Flux<DataBuffer> body = Flux.fromIterable(map.entrySet()).concatMap(entry -> encodePartValues(boundary, entry.getKey(), entry.getValue(), bufferFactory)).concatWith(generateLastLine(boundary, bufferFactory)).doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
    if (logger.isDebugEnabled()) {
        body = body.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger));
    }
    return outputMessage.writeWith(body);
}
Also used : CharSequenceEncoder(org.springframework.core.codec.CharSequenceEncoder) Arrays(java.util.Arrays) ResourceHttpMessageWriter(org.springframework.http.codec.ResourceHttpMessageWriter) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Hints(org.springframework.core.codec.Hints) ResolvableTypeProvider(org.springframework.core.ResolvableTypeProvider) Supplier(java.util.function.Supplier) ReactiveHttpOutputMessage(org.springframework.http.ReactiveHttpOutputMessage) ArrayList(java.util.ArrayList) CodecException(org.springframework.core.codec.CodecException) LogFormatUtils(org.springframework.core.log.LogFormatUtils) EncoderHttpMessageWriter(org.springframework.http.codec.EncoderHttpMessageWriter) Map(java.util.Map) DataBufferUtils(org.springframework.core.io.buffer.DataBufferUtils) Nullable(org.springframework.lang.Nullable) ResolvableType(org.springframework.core.ResolvableType) Resource(org.springframework.core.io.Resource) HttpHeaders(org.springframework.http.HttpHeaders) FormHttpMessageWriter(org.springframework.http.codec.FormHttpMessageWriter) Publisher(org.reactivestreams.Publisher) MediaType(org.springframework.http.MediaType) PooledDataBuffer(org.springframework.core.io.buffer.PooledDataBuffer) MultiValueMap(org.springframework.util.MultiValueMap) Mono(reactor.core.publisher.Mono) DataBuffer(org.springframework.core.io.buffer.DataBuffer) Flux(reactor.core.publisher.Flux) List(java.util.List) HttpEntity(org.springframework.http.HttpEntity) DataBufferFactory(org.springframework.core.io.buffer.DataBufferFactory) Optional(java.util.Optional) Collections(java.util.Collections) HttpMessageWriter(org.springframework.http.codec.HttpMessageWriter) Assert(org.springframework.util.Assert) DataBufferUtils(org.springframework.core.io.buffer.DataBufferUtils) DataBufferFactory(org.springframework.core.io.buffer.DataBufferFactory) PooledDataBuffer(org.springframework.core.io.buffer.PooledDataBuffer) DataBuffer(org.springframework.core.io.buffer.DataBuffer)

Example 2 with Hints

use of org.springframework.core.codec.Hints in project spring-framework by spring-projects.

the class ResourceHttpMessageWriter method writeResource.

private Mono<Void> writeResource(Resource resource, ResolvableType type, @Nullable MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints) {
    HttpHeaders headers = message.getHeaders();
    MediaType resourceMediaType = getResourceMediaType(mediaType, resource, hints);
    headers.setContentType(resourceMediaType);
    if (headers.getContentLength() < 0) {
        long length = lengthOf(resource);
        if (length != -1) {
            headers.setContentLength(length);
        }
    }
    return zeroCopy(resource, null, message, hints).orElseGet(() -> {
        Mono<Resource> input = Mono.just(resource);
        DataBufferFactory factory = message.bufferFactory();
        Flux<DataBuffer> body = this.encoder.encode(input, factory, type, resourceMediaType, hints);
        if (logger.isDebugEnabled()) {
            body = body.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger));
        }
        return message.writeWith(body);
    });
}
Also used : HttpLogging(org.springframework.http.HttpLogging) ZeroCopyHttpOutputMessage(org.springframework.http.ZeroCopyHttpOutputMessage) ServerHttpResponse(org.springframework.http.server.reactive.ServerHttpResponse) Hints(org.springframework.core.codec.Hints) ResourceRegion(org.springframework.core.io.support.ResourceRegion) ResourceRegionEncoder(org.springframework.core.codec.ResourceRegionEncoder) ReactiveHttpOutputMessage(org.springframework.http.ReactiveHttpOutputMessage) MediaTypeFactory(org.springframework.http.MediaTypeFactory) Map(java.util.Map) InputStreamResource(org.springframework.core.io.InputStreamResource) Nullable(org.springframework.lang.Nullable) ResolvableType(org.springframework.core.ResolvableType) ResourceDecoder(org.springframework.core.codec.ResourceDecoder) Resource(org.springframework.core.io.Resource) ServerHttpRequest(org.springframework.http.server.reactive.ServerHttpRequest) ResourceEncoder(org.springframework.core.codec.ResourceEncoder) HttpHeaders(org.springframework.http.HttpHeaders) Publisher(org.reactivestreams.Publisher) MediaType(org.springframework.http.MediaType) IOException(java.io.IOException) Mono(reactor.core.publisher.Mono) HttpRange(org.springframework.http.HttpRange) MimeTypeUtils(org.springframework.util.MimeTypeUtils) DataBuffer(org.springframework.core.io.buffer.DataBuffer) File(java.io.File) Flux(reactor.core.publisher.Flux) HttpStatus(org.springframework.http.HttpStatus) List(java.util.List) DataBufferFactory(org.springframework.core.io.buffer.DataBufferFactory) Optional(java.util.Optional) Log(org.apache.commons.logging.Log) HttpHeaders(org.springframework.http.HttpHeaders) InputStreamResource(org.springframework.core.io.InputStreamResource) Resource(org.springframework.core.io.Resource) MediaType(org.springframework.http.MediaType) DataBufferFactory(org.springframework.core.io.buffer.DataBufferFactory) DataBuffer(org.springframework.core.io.buffer.DataBuffer)

Example 3 with Hints

use of org.springframework.core.codec.Hints in project spring-framework by spring-projects.

the class EncoderHttpMessageWriter method write.

@Override
public Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType elementType, @Nullable MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints) {
    MediaType contentType = updateContentType(message, mediaType);
    Flux<DataBuffer> body = this.encoder.encode(inputStream, message.bufferFactory(), elementType, contentType, hints);
    if (inputStream instanceof Mono) {
        return body.singleOrEmpty().switchIfEmpty(Mono.defer(() -> {
            message.getHeaders().setContentLength(0);
            return message.setComplete().then(Mono.empty());
        })).flatMap(buffer -> {
            Hints.touchDataBuffer(buffer, hints, logger);
            message.getHeaders().setContentLength(buffer.readableByteCount());
            return message.writeWith(Mono.just(buffer).doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release));
        }).doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
    }
    if (isStreamingMediaType(contentType)) {
        return message.writeAndFlushWith(body.map(buffer -> {
            Hints.touchDataBuffer(buffer, hints, logger);
            return Mono.just(buffer).doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
        }));
    }
    if (logger.isDebugEnabled()) {
        body = body.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger));
    }
    return message.writeWith(body);
}
Also used : AbstractEncoder(org.springframework.core.codec.AbstractEncoder) HttpLogging(org.springframework.http.HttpLogging) ServerHttpResponse(org.springframework.http.server.reactive.ServerHttpResponse) Publisher(org.reactivestreams.Publisher) MediaType(org.springframework.http.MediaType) PooledDataBuffer(org.springframework.core.io.buffer.PooledDataBuffer) Hints(org.springframework.core.codec.Hints) Mono(reactor.core.publisher.Mono) DataBuffer(org.springframework.core.io.buffer.DataBuffer) ReactiveHttpOutputMessage(org.springframework.http.ReactiveHttpOutputMessage) Flux(reactor.core.publisher.Flux) List(java.util.List) Map(java.util.Map) DataBufferUtils(org.springframework.core.io.buffer.DataBufferUtils) Log(org.apache.commons.logging.Log) Nullable(org.springframework.lang.Nullable) ResolvableType(org.springframework.core.ResolvableType) Encoder(org.springframework.core.codec.Encoder) ServerHttpRequest(org.springframework.http.server.reactive.ServerHttpRequest) Assert(org.springframework.util.Assert) StringUtils(org.springframework.util.StringUtils) DataBufferUtils(org.springframework.core.io.buffer.DataBufferUtils) Mono(reactor.core.publisher.Mono) MediaType(org.springframework.http.MediaType) PooledDataBuffer(org.springframework.core.io.buffer.PooledDataBuffer) PooledDataBuffer(org.springframework.core.io.buffer.PooledDataBuffer) DataBuffer(org.springframework.core.io.buffer.DataBuffer)

Example 4 with Hints

use of org.springframework.core.codec.Hints in project spring-framework by spring-projects.

the class AbstractMessageReaderArgumentResolver method readBody.

/**
 * Read the body from a method argument with {@link HttpMessageReader}.
 * @param bodyParam represents the element type for the body
 * @param actualParam the actual method argument type; possibly different
 * from {@code bodyParam}, e.g. for an {@code HttpEntity} argument
 * @param isBodyRequired true if the body is required
 * @param bindingContext the binding context to use
 * @param exchange the current exchange
 * @return a Mono with the value to use for the method argument
 * @since 5.0.2
 */
protected Mono<Object> readBody(MethodParameter bodyParam, @Nullable MethodParameter actualParam, boolean isBodyRequired, BindingContext bindingContext, ServerWebExchange exchange) {
    ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParam);
    ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
    Class<?> resolvedType = bodyType.resolve();
    ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
    ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType);
    isBodyRequired = isBodyRequired || (adapter != null && !adapter.supportsEmpty());
    ServerHttpRequest request = exchange.getRequest();
    ServerHttpResponse response = exchange.getResponse();
    MediaType contentType = request.getHeaders().getContentType();
    MediaType mediaType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
    Object[] hints = extractValidationHints(bodyParam);
    if (mediaType.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Form data is accessed via ServerWebExchange.getFormData() in WebFlux.");
        }
        return Mono.error(new ResponseStatusException(HttpStatus.UNSUPPORTED_MEDIA_TYPE));
    }
    if (logger.isDebugEnabled()) {
        logger.debug(exchange.getLogPrefix() + (contentType != null ? "Content-Type:" + contentType : "No Content-Type, using " + MediaType.APPLICATION_OCTET_STREAM));
    }
    for (HttpMessageReader<?> reader : getMessageReaders()) {
        if (reader.canRead(elementType, mediaType)) {
            Map<String, Object> readHints = Hints.from(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix());
            if (adapter != null && adapter.isMultiValue()) {
                if (logger.isDebugEnabled()) {
                    logger.debug(exchange.getLogPrefix() + "0..N [" + elementType + "]");
                }
                Flux<?> flux = reader.read(actualType, elementType, request, response, readHints);
                flux = flux.onErrorResume(ex -> Flux.error(handleReadError(bodyParam, ex)));
                if (isBodyRequired) {
                    flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(bodyParam)));
                }
                if (hints != null) {
                    flux = flux.doOnNext(target -> validate(target, hints, bodyParam, bindingContext, exchange));
                }
                return Mono.just(adapter.fromPublisher(flux));
            } else {
                // Single-value (with or without reactive type wrapper)
                if (logger.isDebugEnabled()) {
                    logger.debug(exchange.getLogPrefix() + "0..1 [" + elementType + "]");
                }
                Mono<?> mono = reader.readMono(actualType, elementType, request, response, readHints);
                mono = mono.onErrorResume(ex -> Mono.error(handleReadError(bodyParam, ex)));
                if (isBodyRequired) {
                    mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
                }
                if (hints != null) {
                    mono = mono.doOnNext(target -> validate(target, hints, bodyParam, bindingContext, exchange));
                }
                return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
            }
        }
    }
    // No compatible reader but body may be empty..
    HttpMethod method = request.getMethod();
    if (contentType == null && SUPPORTED_METHODS.contains(method)) {
        Flux<DataBuffer> body = request.getBody().doOnNext(buffer -> {
            DataBufferUtils.release(buffer);
            // Body not empty, back toy 415..
            throw new UnsupportedMediaTypeStatusException(mediaType, getSupportedMediaTypes(elementType), elementType);
        });
        if (isBodyRequired) {
            body = body.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
        }
        return (adapter != null ? Mono.just(adapter.fromPublisher(body)) : Mono.from(body));
    }
    return Mono.error(new UnsupportedMediaTypeStatusException(mediaType, getSupportedMediaTypes(elementType), elementType));
}
Also used : ServerHttpResponse(org.springframework.http.server.reactive.ServerHttpResponse) Validator(org.springframework.validation.Validator) Conventions(org.springframework.core.Conventions) WebExchangeDataBinder(org.springframework.web.bind.support.WebExchangeDataBinder) ServerWebInputException(org.springframework.web.server.ServerWebInputException) DecodingException(org.springframework.core.codec.DecodingException) Hints(org.springframework.core.codec.Hints) HttpMessageReader(org.springframework.http.codec.HttpMessageReader) BindingContext(org.springframework.web.reactive.BindingContext) ArrayList(java.util.ArrayList) ServerWebExchange(org.springframework.web.server.ServerWebExchange) HandlerMethodArgumentResolverSupport(org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport) UnsupportedMediaTypeStatusException(org.springframework.web.server.UnsupportedMediaTypeStatusException) Map(java.util.Map) MethodParameter(org.springframework.core.MethodParameter) DataBufferUtils(org.springframework.core.io.buffer.DataBufferUtils) Nullable(org.springframework.lang.Nullable) ResolvableType(org.springframework.core.ResolvableType) ReactiveAdapterRegistry(org.springframework.core.ReactiveAdapterRegistry) WebExchangeBindException(org.springframework.web.bind.support.WebExchangeBindException) ServerHttpRequest(org.springframework.http.server.reactive.ServerHttpRequest) ReactiveAdapter(org.springframework.core.ReactiveAdapter) ResponseStatusException(org.springframework.web.server.ResponseStatusException) MediaType(org.springframework.http.MediaType) HttpMethod(org.springframework.http.HttpMethod) ValidationAnnotationUtils(org.springframework.validation.annotation.ValidationAnnotationUtils) Set(java.util.Set) Mono(reactor.core.publisher.Mono) DataBuffer(org.springframework.core.io.buffer.DataBuffer) Flux(reactor.core.publisher.Flux) HttpStatus(org.springframework.http.HttpStatus) List(java.util.List) Annotation(java.lang.annotation.Annotation) Assert(org.springframework.util.Assert) ServerHttpRequest(org.springframework.http.server.reactive.ServerHttpRequest) ServerHttpResponse(org.springframework.http.server.reactive.ServerHttpResponse) UnsupportedMediaTypeStatusException(org.springframework.web.server.UnsupportedMediaTypeStatusException) MediaType(org.springframework.http.MediaType) ResolvableType(org.springframework.core.ResolvableType) ResponseStatusException(org.springframework.web.server.ResponseStatusException) ReactiveAdapter(org.springframework.core.ReactiveAdapter) HttpMethod(org.springframework.http.HttpMethod) DataBuffer(org.springframework.core.io.buffer.DataBuffer)

Aggregations

List (java.util.List)4 Map (java.util.Map)4 ResolvableType (org.springframework.core.ResolvableType)4 Hints (org.springframework.core.codec.Hints)4 DataBuffer (org.springframework.core.io.buffer.DataBuffer)4 MediaType (org.springframework.http.MediaType)4 Nullable (org.springframework.lang.Nullable)4 Flux (reactor.core.publisher.Flux)4 Mono (reactor.core.publisher.Mono)4 Publisher (org.reactivestreams.Publisher)3 DataBufferUtils (org.springframework.core.io.buffer.DataBufferUtils)3 ReactiveHttpOutputMessage (org.springframework.http.ReactiveHttpOutputMessage)3 ArrayList (java.util.ArrayList)2 Optional (java.util.Optional)2 Log (org.apache.commons.logging.Log)2 Resource (org.springframework.core.io.Resource)2 DataBufferFactory (org.springframework.core.io.buffer.DataBufferFactory)2 PooledDataBuffer (org.springframework.core.io.buffer.PooledDataBuffer)2 HttpHeaders (org.springframework.http.HttpHeaders)2 HttpLogging (org.springframework.http.HttpLogging)2