org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder 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
*
* https://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.accept;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
/**
* Builder for a composite {@link RequestedContentTypeResolver} that delegates
* to other resolvers each implementing a different strategy to determine the
* requested content type -- e.g. Accept header, query parameter, or other.
*
* Use builder methods to add resolvers in the desired order. For a given
* request he first resolver to return a list that is not empty and does not
* consist of just {@link MediaType#ALL}, will be used.
*
*
By default, if no resolvers are explicitly configured, the builder will
* add {@link HeaderContentTypeResolver}.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
public class RequestedContentTypeResolverBuilder {
private final List> candidates = new ArrayList<>();
/**
* Add a resolver to get the requested content type from a query parameter.
* By default the query parameter name is {@code "format"}.
*/
public ParameterResolverConfigurer parameterResolver() {
ParameterResolverConfigurer parameterBuilder = new ParameterResolverConfigurer();
this.candidates.add(parameterBuilder::createResolver);
return parameterBuilder;
}
/**
* Add resolver to get the requested content type from the
* {@literal "Accept"} header.
*/
public void headerResolver() {
this.candidates.add(HeaderContentTypeResolver::new);
}
/**
* Add resolver that returns a fixed set of media types.
* @param mediaTypes the media types to use
*/
public void fixedResolver(MediaType... mediaTypes) {
this.candidates.add(() -> new FixedContentTypeResolver(Arrays.asList(mediaTypes)));
}
/**
* Add a custom resolver.
* @param resolver the resolver to add
*/
public void resolver(RequestedContentTypeResolver resolver) {
this.candidates.add(() -> resolver);
}
/**
* Build a {@link RequestedContentTypeResolver} that delegates to the list
* of resolvers configured through this builder.
*/
public RequestedContentTypeResolver build() {
List resolvers = (!this.candidates.isEmpty() ?
this.candidates.stream().map(Supplier::get).collect(Collectors.toList()) :
Collections.singletonList(new HeaderContentTypeResolver()));
return exchange -> {
for (RequestedContentTypeResolver resolver : resolvers) {
List mediaTypes = resolver.resolveMediaTypes(exchange);
if (mediaTypes.equals(RequestedContentTypeResolver.MEDIA_TYPE_ALL_LIST)) {
continue;
}
return mediaTypes;
}
return RequestedContentTypeResolver.MEDIA_TYPE_ALL_LIST;
};
}
/**
* Helper to create and configure {@link ParameterContentTypeResolver}.
*/
public static class ParameterResolverConfigurer {
private final Map mediaTypes = new HashMap<>();
@Nullable
private String parameterName;
/**
* Configure a mapping between a lookup key (extracted from a query
* parameter value) and a corresponding {@code MediaType}.
* @param key the lookup key
* @param mediaType the MediaType for that key
*/
public ParameterResolverConfigurer mediaType(String key, MediaType mediaType) {
this.mediaTypes.put(key, mediaType);
return this;
}
/**
* Map-based variant of {@link #mediaType(String, MediaType)}.
* @param mediaTypes the mappings to copy
*/
public ParameterResolverConfigurer mediaType(Map mediaTypes) {
this.mediaTypes.putAll(mediaTypes);
return this;
}
/**
* Set the name of the parameter to use to determine requested media types.
* By default this is set to {@literal "format"}.
*/
public ParameterResolverConfigurer parameterName(String parameterName) {
this.parameterName = parameterName;
return this;
}
/**
* Private factory method to create the resolver.
*/
private RequestedContentTypeResolver createResolver() {
ParameterContentTypeResolver resolver = new ParameterContentTypeResolver(this.mediaTypes);
if (this.parameterName != null) {
resolver.setParameterName(this.parameterName);
}
return resolver;
}
}
}