org.springframework.web.reactive.function.server.DefaultServerRequest Maven / Gradle / Ivy
/*
* Copyright 2002-2018 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.reactive.function.server;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Function;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.codec.Hints;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRange;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractor;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.UnsupportedMediaTypeException;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import org.springframework.web.server.WebSession;
import org.springframework.web.util.UriBuilder;
import org.springframework.web.util.UriComponentsBuilder;
/**
* {@code ServerRequest} implementation based on a {@link ServerWebExchange}.
*
* @author Arjen Poutsma
* @since 5.0
*/
class DefaultServerRequest implements ServerRequest {
private static final Function ERROR_MAPPER =
ex -> (ex.getContentType() != null ?
new UnsupportedMediaTypeStatusException(
ex.getContentType(), ex.getSupportedMediaTypes(), ex.getBodyType()) :
new UnsupportedMediaTypeStatusException(ex.getMessage()));
private final ServerWebExchange exchange;
private final Headers headers;
private final List> messageReaders;
DefaultServerRequest(ServerWebExchange exchange, List> messageReaders) {
this.exchange = exchange;
this.messageReaders = Collections.unmodifiableList(new ArrayList<>(messageReaders));
this.headers = new DefaultHeaders();
}
@Override
public String methodName() {
return request().getMethodValue();
}
@Override
public URI uri() {
return request().getURI();
}
@Override
public UriBuilder uriBuilder() {
return UriComponentsBuilder.fromUri(uri());
}
@Override
public PathContainer pathContainer() {
return request().getPath();
}
@Override
public Headers headers() {
return this.headers;
}
@Override
public MultiValueMap cookies() {
return request().getCookies();
}
@Override
public Optional remoteAddress() {
return Optional.ofNullable(request().getRemoteAddress());
}
@Override
public List> messageReaders() {
return this.messageReaders;
}
@Override
public T body(BodyExtractor extractor) {
return bodyInternal(extractor, Hints.from(Hints.LOG_PREFIX_HINT, exchange().getLogPrefix()));
}
@Override
public T body(BodyExtractor extractor, Map hints) {
hints = Hints.merge(hints, Hints.LOG_PREFIX_HINT, exchange().getLogPrefix());
return bodyInternal(extractor, hints);
}
private T bodyInternal(BodyExtractor extractor, Map hints) {
return extractor.extract(request(),
new BodyExtractor.Context() {
@Override
public List> messageReaders() {
return messageReaders;
}
@Override
public Optional serverResponse() {
return Optional.of(exchange().getResponse());
}
@Override
public Map hints() {
return hints;
}
});
}
@Override
public Mono bodyToMono(Class elementClass) {
Mono mono = body(BodyExtractors.toMono(elementClass));
return mono.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
}
@Override
public Mono bodyToMono(ParameterizedTypeReference typeReference) {
Mono mono = body(BodyExtractors.toMono(typeReference));
return mono.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
}
@Override
public Flux bodyToFlux(Class elementClass) {
Flux flux = body(BodyExtractors.toFlux(elementClass));
return flux.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
}
@Override
public Flux bodyToFlux(ParameterizedTypeReference typeReference) {
Flux flux = body(BodyExtractors.toFlux(typeReference));
return flux.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER);
}
@Override
public Map attributes() {
return this.exchange.getAttributes();
}
@Override
public MultiValueMap queryParams() {
return request().getQueryParams();
}
@Override
public Map pathVariables() {
return this.exchange.getAttributeOrDefault(
RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, Collections.emptyMap());
}
@Override
public Mono session() {
return this.exchange.getSession();
}
@Override
public Mono principal() {
return this.exchange.getPrincipal();
}
@Override
public Mono> formData() {
return this.exchange.getFormData();
}
@Override
public Mono> multipartData() {
return this.exchange.getMultipartData();
}
private ServerHttpRequest request() {
return this.exchange.getRequest();
}
@Override
public ServerWebExchange exchange() {
return this.exchange;
}
@Override
public String toString() {
return String.format("HTTP %s %s", method(), path());
}
private class DefaultHeaders implements Headers {
private HttpHeaders delegate() {
return request().getHeaders();
}
@Override
public List accept() {
return delegate().getAccept();
}
@Override
public List acceptCharset() {
return delegate().getAcceptCharset();
}
@Override
public List acceptLanguage() {
return delegate().getAcceptLanguage();
}
@Override
public OptionalLong contentLength() {
long value = delegate().getContentLength();
return (value != -1 ? OptionalLong.of(value) : OptionalLong.empty());
}
@Override
public Optional contentType() {
return Optional.ofNullable(delegate().getContentType());
}
@Override
public InetSocketAddress host() {
return delegate().getHost();
}
@Override
public List range() {
return delegate().getRange();
}
@Override
public List header(String headerName) {
List headerValues = delegate().get(headerName);
return (headerValues != null ? headerValues : Collections.emptyList());
}
@Override
public HttpHeaders asHttpHeaders() {
return HttpHeaders.readOnlyHttpHeaders(delegate());
}
@Override
public String toString() {
return delegate().toString();
}
}
}