Refactor MappingContentTypeResolver implementations

After the removal of suffix pattern matches, there is no longer a need
to expose the list of registered file extensions.

Also polish, refactor, and simplify the abstract base class
AbstractMappingContentTypeResolver and its sub-classes.

Issue: SPR-15639
This commit is contained in:
Rossen Stoyanchev
2017-06-07 12:17:49 -04:00
parent cb604738cf
commit b0e8e7f536
13 changed files with 73 additions and 467 deletions

View File

@@ -23,7 +23,6 @@ import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
import static org.junit.Assert.assertEquals;
@@ -80,17 +79,6 @@ public class CompositeContentTypeResolverBuilderTests {
assertEquals(Collections.singletonList(MediaType.IMAGE_GIF), resolver.resolveMediaTypes(exchange));
}
@Test(expected = NotAcceptableStatusException.class) // SPR-10170
public void favorPathWithIgnoreUnknownPathExtensionTurnedOff() throws Exception {
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder()
.favorPathExtension(true)
.ignoreUnknownPathExtensions(false)
.build();
ServerWebExchange exchange = MockServerHttpRequest.get("/flower.foobar?format=json").toExchange();
resolver.resolveMediaTypes(exchange);
}
@Test
public void favorParameter() throws Exception {
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder()
@@ -103,16 +91,6 @@ public class CompositeContentTypeResolverBuilderTests {
assertEquals(Collections.singletonList(MediaType.APPLICATION_JSON), resolver.resolveMediaTypes(exchange));
}
@Test(expected = NotAcceptableStatusException.class) // SPR-10170
public void favorParameterWithUnknownMediaType() throws Exception {
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder()
.favorParameter(true)
.build();
ServerWebExchange exchange = MockServerHttpRequest.get("/flower?format=xyz").toExchange();
resolver.resolveMediaTypes(exchange);
}
@Test
public void ignoreAcceptHeader() throws Exception {
RequestedContentTypeResolver resolver = new RequestedContentTypeResolverBuilder()

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -18,15 +18,16 @@ package org.springframework.web.reactive.accept;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Unit tests for {@link AbstractMappingContentTypeResolver}.
@@ -34,65 +35,46 @@ import static org.junit.Assert.assertTrue;
*/
public class MappingContentTypeResolverTests {
@Test
public void resolveExtensions() {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("", mapping);
Set<String> keys = resolver.getKeysFor(MediaType.APPLICATION_JSON);
assertEquals(1, keys.size());
assertEquals("json", keys.iterator().next());
}
@Test
public void resolveExtensionsNoMatch() {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("", mapping);
Set<String> keys = resolver.getKeysFor(MediaType.TEXT_HTML);
assertTrue(keys.isEmpty());
}
@Test // SPR-13747
public void lookupMediaTypeCaseInsensitive() {
public void resolveCaseInsensitive() {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("", mapping);
MediaType mediaType = resolver.getMediaType("JSoN");
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("JSoN", mapping);
List<MediaType> mediaTypes = resolver.resolve();
assertEquals(mediaType, MediaType.APPLICATION_JSON);
assertEquals(Collections.singletonList(MediaType.APPLICATION_JSON), mediaTypes);
}
@Test
public void resolveMediaTypes() throws Exception {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("json", mapping);
List<MediaType> mediaTypes = resolver.resolveMediaTypes((ServerWebExchange) null);
List<MediaType> mediaTypes = resolver.resolve();
assertEquals(1, mediaTypes.size());
assertEquals("application/json", mediaTypes.get(0).toString());
}
@Test
public void resolveMediaTypesNoMatch() throws Exception {
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("blah", null);
List<MediaType> mediaTypes = resolver.resolveMediaTypes((ServerWebExchange) null);
public void resolveNoMatch() throws Exception {
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("blah", Collections.emptyMap());
List<MediaType> mediaTypes = resolver.resolve();
assertEquals(0, mediaTypes.size());
}
@Test
public void resolveMediaTypesNoKey() throws Exception {
public void resolveNoKey() throws Exception {
Map<String, MediaType> mapping = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver(null, mapping);
List<MediaType> mediaTypes = resolver.resolveMediaTypes((ServerWebExchange) null);
List<MediaType> mediaTypes = resolver.resolve();
assertEquals(0, mediaTypes.size());
}
@Test
public void resolveMediaTypesHandleNoMatch() throws Exception {
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("xml", null);
List<MediaType> mediaTypes = resolver.resolveMediaTypes((ServerWebExchange) null);
TestMappingContentTypeResolver resolver = new TestMappingContentTypeResolver("xml", Collections.emptyMap());
List<MediaType> mediaTypes = resolver.resolve();
assertEquals(1, mediaTypes.size());
assertEquals("application/xml", mediaTypes.get(0).toString());
@@ -103,19 +85,18 @@ public class MappingContentTypeResolverTests {
private final String key;
public TestMappingContentTypeResolver(String key, Map<String, MediaType> mapping) {
TestMappingContentTypeResolver(@Nullable String key, Map<String, MediaType> mapping) {
super(mapping);
this.key = key;
}
@Override
protected String extractKey(ServerWebExchange exchange) {
return this.key;
public List<MediaType> resolve() throws NotAcceptableStatusException {
return super.resolveMediaTypes(MockServerHttpRequest.get("/").toExchange());
}
@Override
protected MediaType handleNoMatch(String mappingKey) {
return "xml".equals(mappingKey) ? MediaType.APPLICATION_XML : null;
protected String getKey(ServerWebExchange exchange) {
return this.key;
}
}

View File

@@ -23,7 +23,6 @@ import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
import static org.junit.Assert.assertEquals;
@@ -36,9 +35,9 @@ import static org.junit.Assert.assertEquals;
public class PathExtensionContentTypeResolverTests {
@Test
public void resolveMediaTypesFromMapping() throws Exception {
public void resolveFromRegistrations() throws Exception {
ServerWebExchange exchange = MockServerHttpRequest.get("/test.html").toExchange();
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
PathExtensionContentTypeResolver resolver = createResolver();
List<MediaType> mediaTypes = resolver.resolveMediaTypes(exchange);
assertEquals(Collections.singletonList(new MediaType("text", "html")), mediaTypes);
@@ -51,42 +50,34 @@ public class PathExtensionContentTypeResolverTests {
}
@Test
public void resolveMediaTypesFromJaf() throws Exception {
public void resolveFromMediaTypeFactory() throws Exception {
ServerWebExchange exchange = MockServerHttpRequest.get("test.xls").toExchange();
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
PathExtensionContentTypeResolver resolver = createResolver();
List<MediaType> mediaTypes = resolver.resolveMediaTypes(exchange);
assertEquals(Collections.singletonList(new MediaType("application", "vnd.ms-excel")), mediaTypes);
}
// SPR-9390
@Test
public void getMediaTypeFilenameWithEncodedURI() throws Exception {
@Test // SPR-9390
public void resolveFromFilenameWithEncodedURI() throws Exception {
ServerWebExchange exchange = MockServerHttpRequest.get("/quo%20vadis%3f.html").toExchange();
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
PathExtensionContentTypeResolver resolver = createResolver();
List<MediaType> result = resolver.resolveMediaTypes(exchange);
assertEquals("Invalid content type", Collections.singletonList(new MediaType("text", "html")), result);
}
// SPR-10170
@Test
public void resolveMediaTypesIgnoreUnknownExtension() throws Exception {
@Test // SPR-10170
public void resolveAndIgnoreUnknownExtension() throws Exception {
ServerWebExchange exchange = MockServerHttpRequest.get("test.foobar").toExchange();
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
PathExtensionContentTypeResolver resolver = createResolver();
List<MediaType> mediaTypes = resolver.resolveMediaTypes(exchange);
assertEquals(Collections.<MediaType>emptyList(), mediaTypes);
}
@Test(expected = NotAcceptableStatusException.class)
public void resolveMediaTypesDoNotIgnoreUnknownExtension() throws Exception {
ServerWebExchange exchange = MockServerHttpRequest.get("test.foobar").toExchange();
PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver();
resolver.setIgnoreUnknownExtensions(false);
resolver.resolveMediaTypes(exchange);
private PathExtensionContentTypeResolver createResolver() {
return new PathExtensionContentTypeResolver(Collections.emptyMap());
}
}

View File

@@ -22,8 +22,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
@@ -40,11 +38,13 @@ import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.reactive.accept.MappingContentTypeResolver;
import org.springframework.web.reactive.result.method.RequestMappingInfo;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Unit tests for {@link RequestMappingHandlerMapping}.
@@ -63,47 +63,6 @@ public class RequestMappingHandlerMappingTests {
this.handlerMapping.setApplicationContext(wac);
}
@Test
public void useRegisteredSuffixPatternMatch() {
assertTrue(this.handlerMapping.useSuffixPatternMatch());
assertTrue(this.handlerMapping.useRegisteredSuffixPatternMatch());
MappingContentTypeResolver contentTypeResolver = mock(MappingContentTypeResolver.class);
when(contentTypeResolver.getKeys()).thenReturn(Collections.singleton("json"));
this.handlerMapping.setContentTypeResolver(contentTypeResolver);
this.handlerMapping.afterPropertiesSet();
assertTrue(this.handlerMapping.useSuffixPatternMatch());
assertTrue(this.handlerMapping.useRegisteredSuffixPatternMatch());
assertEquals(Collections.singleton("json"), this.handlerMapping.getFileExtensions());
}
@Test
public void useRegisteredSuffixPatternMatchInitialization() {
MappingContentTypeResolver contentTypeResolver = mock(MappingContentTypeResolver.class);
when(contentTypeResolver.getKeys()).thenReturn(Collections.singleton("json"));
final Set<String> actualExtensions = new HashSet<>();
RequestMappingHandlerMapping localHandlerMapping = new RequestMappingHandlerMapping() {
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
actualExtensions.addAll(getFileExtensions());
return super.getMappingForMethod(method, handlerType);
}
};
this.wac.registerSingleton("testController", ComposedAnnotationController.class);
this.wac.refresh();
localHandlerMapping.setContentTypeResolver(contentTypeResolver);
localHandlerMapping.setUseRegisteredSuffixPatternMatch(true);
localHandlerMapping.setApplicationContext(this.wac);
localHandlerMapping.afterPropertiesSet();
assertEquals(Collections.singleton("json"), actualExtensions);
}
@Test
public void useSuffixPatternMatch() {
assertTrue(this.handlerMapping.useSuffixPatternMatch());