Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dd7085b

Browse files
committed
Merge branch 'mzeijen-issue-1916'
fixes springfox#1916
2 parents b9b2597 + 0c6526b commit dd7085b

24 files changed

Lines changed: 649 additions & 1006 deletions

springfox-spi/src/main/java/springfox/documentation/spi/service/contexts/OperationContext.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import com.google.common.base.Predicate;
2525
import com.google.common.collect.ImmutableSet;
2626
import com.google.common.collect.Iterables;
27-
import com.google.common.collect.Sets;
2827
import org.springframework.http.HttpMethod;
2928
import org.springframework.http.MediaType;
3029
import org.springframework.web.bind.annotation.RequestMethod;
@@ -43,7 +42,6 @@
4342

4443
import static com.google.common.collect.Lists.*;
4544
import static springfox.documentation.builders.BuilderDefaults.*;
46-
import static springfox.documentation.service.MediaTypes.*;
4745

4846
public class OperationContext {
4947
private final OperationBuilder operationBuilder;
@@ -119,14 +117,12 @@ public ResolvedType alternateFor(ResolvedType resolved) {
119117
return getAlternateTypeProvider().alternateFor(resolved);
120118
}
121119

122-
public Set<MediaType> produces() {
123-
return Sets.union(requestContext.produces(),
124-
toMediaTypes(getDocumentationContext().getProduces()));
120+
public Set<? extends MediaType> produces() {
121+
return requestContext.produces();
125122
}
126123

127-
public Set<MediaType> consumes() {
128-
return Sets.union(requestContext.consumes(),
129-
toMediaTypes(getDocumentationContext().getConsumes()));
124+
public Set<? extends MediaType> consumes() {
125+
return requestContext.consumes();
130126
}
131127

132128
public ImmutableSet<Class> getIgnorableParameterTypes() {

springfox-spring-web/src/main/java/springfox/documentation/spring/web/scanners/MediaTypeReader.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright 2015-2016 the original author or authors.
3+
* Copyright 2015-2018 the original author or authors.
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
3131
import springfox.documentation.spi.service.ApiListingBuilderPlugin;
3232
import springfox.documentation.spi.service.OperationBuilderPlugin;
3333
import springfox.documentation.spi.service.contexts.ApiListingContext;
34+
import springfox.documentation.spi.service.contexts.DocumentationContext;
3435
import springfox.documentation.spi.service.contexts.OperationContext;
3536

3637
import java.util.List;
@@ -47,21 +48,23 @@ public class MediaTypeReader implements OperationBuilderPlugin, ApiListingBuilde
4748
@Override
4849
public void apply(OperationContext context) {
4950

50-
Set<String> consumesList = toSet(context.consumes());
51-
Set<String> producesList = toSet(context.produces());
51+
DocumentationContext documentationContext = context.getDocumentationContext();
52+
53+
Set<String> operationConsumesList = toSet(context.consumes());
54+
Set<String> operationProducesList = toSet(context.produces());
5255

5356
if (handlerMethodHasFileParameter(context)) {
54-
consumesList = newHashSet(MediaType.MULTIPART_FORM_DATA_VALUE);
57+
operationConsumesList = newHashSet(MediaType.MULTIPART_FORM_DATA_VALUE);
5558
}
5659

57-
if (producesList.isEmpty()) {
58-
producesList.add(MediaType.ALL_VALUE);
60+
if (operationProducesList.isEmpty() && documentationContext.getProduces().isEmpty()) {
61+
operationProducesList.add(MediaType.ALL_VALUE);
5962
}
60-
if (consumesList.isEmpty()) {
61-
consumesList.add(MediaType.APPLICATION_JSON_VALUE);
63+
if (operationConsumesList.isEmpty() && documentationContext.getConsumes().isEmpty()) {
64+
operationConsumesList.add(MediaType.APPLICATION_JSON_VALUE);
6265
}
63-
context.operationBuilder().consumes(consumesList);
64-
context.operationBuilder().produces(producesList);
66+
context.operationBuilder().consumes(operationConsumesList);
67+
context.operationBuilder().produces(operationProducesList);
6568
}
6669

6770
@Override
@@ -93,7 +96,7 @@ private boolean handlerMethodHasFileParameter(OperationContext context) {
9396
return false;
9497
}
9598

96-
private Set<String> toSet(Set<MediaType> mediaTypeSet) {
99+
private Set<String> toSet(Set<? extends MediaType> mediaTypeSet) {
97100
Set<String> mediaTypes = newHashSet();
98101
for (MediaType mediaType : mediaTypeSet) {
99102
mediaTypes.add(mediaType.toString());

springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/readers/MediaTypeReaderSpec.groovy

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
*
3-
* Copyright 2015-2016 the original author or authors.
3+
* Copyright 2015-2018 the original author or authors.
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -33,7 +33,10 @@ import static com.google.common.collect.Sets.*
3333
@Mixin([RequestMappingSupport])
3434
class MediaTypeReaderSpec extends DocumentationContextSpec {
3535
MediaTypeReader sut
36-
@Shared Set<String> emptySet = newHashSet()
36+
37+
@Shared
38+
Set<String> emptySet = newHashSet()
39+
3740
def setup() {
3841
sut = new MediaTypeReader()
3942
}
@@ -42,31 +45,84 @@ class MediaTypeReaderSpec extends DocumentationContextSpec {
4245
def "should read media types"() {
4346

4447
given:
45-
RequestMappingInfo requestMappingInfo =
46-
requestMappingInfo('/somePath',
47-
[
48-
'consumesRequestCondition': consumesRequestCondition(consumes),
49-
'producesRequestCondition': producesRequestCondition(produces)
50-
]
51-
)
48+
RequestMappingInfo requestMappingInfo =
49+
requestMappingInfo('/somePath',
50+
[
51+
'consumesRequestCondition': consumesRequestCondition(consumes),
52+
'producesRequestCondition': producesRequestCondition(produces)
53+
]
54+
)
5255
OperationContext operationContext =
5356
operationContext(context(), handlerMethod, 0, requestMappingInfo)
5457

5558
when:
56-
sut.apply(operationContext)
57-
def operation = operationContext.operationBuilder().build()
59+
sut.apply(operationContext)
60+
def operation = operationContext.operationBuilder().build()
5861

5962
then:
60-
operation.consumes == newHashSet(consumes)
61-
operation.produces == newHashSet(produces)
63+
operation.consumes == newHashSet(consumes)
64+
operation.produces == newHashSet(produces)
6265

6366
where:
64-
consumes | produces | handlerMethod
65-
['application/json'] as String[] | ['application/json'] as String[] | dummyHandlerMethod()
66-
['application/json'] as String[] | ['application/xml'] as String[] | dummyHandlerMethod()
67-
['multipart/form-data'] as String[] | ['application/json'] as String[] | dummyHandlerMethod('methodWithMediaTypeAndFile', MultipartFile)
68-
['application/json', 'application/xml'] as String[] | ['application/xml'] as String[] | dummyHandlerMethod()
67+
consumes | produces | handlerMethod
68+
['application/json'] as String[] | ['application/json'] as String[] | dummyHandlerMethod()
69+
['application/json'] as String[] | ['application/xml'] as String[] | dummyHandlerMethod()
70+
['multipart/form-data'] as String[] | ['application/json'] as String[] | dummyHandlerMethod('methodWithMediaTypeAndFile', MultipartFile)
71+
['application/json', 'application/xml'] as String[] | ['application/xml'] as String[] | dummyHandlerMethod()
6972
}
7073

74+
@Unroll
75+
def "should only set default 'application/json' consumes if no consumes is set for the operation and document context"() {
76+
given:
77+
contextBuilder.consumes(newHashSet(documentConsumes))
78+
RequestMappingInfo requestMappingInfo =
79+
requestMappingInfo('/somePath',
80+
[
81+
'consumesRequestCondition': consumesRequestCondition(operationConsumes)
82+
]
83+
)
84+
OperationContext operationContext =
85+
operationContext(context(), dummyHandlerMethod(), 0, requestMappingInfo)
86+
87+
when:
88+
sut.apply(operationContext)
89+
def operation = operationContext.operationBuilder().build()
90+
91+
then:
92+
operation.consumes == newHashSet(expectedOperationConsumes)
93+
94+
where:
95+
documentConsumes | operationConsumes | expectedOperationConsumes
96+
[] as String[] | [] as String[] | ['application/json'] as String[]
97+
['application/xml'] as String[] | [] as String[] | [] as String[]
98+
[] as String[] | ['application/xml'] as String[] | ['application/xml'] as String[]
99+
}
100+
101+
@Unroll
102+
def "should only set default '*/*' produces if no produces is set for the operation and document context"() {
103+
given:
104+
contextBuilder.produces(newHashSet(documentProduces))
105+
RequestMappingInfo requestMappingInfo =
106+
requestMappingInfo('/somePath',
107+
[
108+
'producesRequestCondition': producesRequestCondition(operationProduces)
109+
]
110+
)
111+
OperationContext operationContext =
112+
operationContext(context(), dummyHandlerMethod(), 0, requestMappingInfo)
113+
114+
when:
115+
sut.apply(operationContext)
116+
def operation = operationContext.operationBuilder().build()
117+
118+
then:
119+
operation.produces == newHashSet(expectedOperationProduces)
120+
121+
where:
122+
documentProduces | operationProduces | expectedOperationProduces
123+
[] as String[] | [] as String[] | ['*/*'] as String[]
124+
['application/xml'] as String[] | [] as String[] | [] as String[]
125+
[] as String[] | ['application/xml'] as String[] | ['application/xml'] as String[]
126+
}
71127

72128
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
*
3+
* Copyright 2015-2018 the original author or authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*
18+
*/
19+
20+
package springfox.documentation.spring.web.dummy.controllers;
21+
22+
import io.swagger.annotations.Api;
23+
import io.swagger.annotations.ApiOperation;
24+
import org.springframework.http.MediaType;
25+
import org.springframework.stereotype.Controller;
26+
import org.springframework.web.bind.annotation.*;
27+
28+
@Controller
29+
@Api(description = "Services to demonstrate produces/consumes override behaviour on document and operation level")
30+
@RequestMapping(path = "/consumes-produces")
31+
public class ConsumesProducesService {
32+
33+
@GetMapping("/without-operation-produces")
34+
@ApiOperation("Does not have operation produces defined")
35+
public String withoutOperationProduces() {
36+
throw new UnsupportedOperationException();
37+
}
38+
39+
@GetMapping(value = "/with-operation-produces", produces = MediaType.APPLICATION_XML_VALUE)
40+
@ApiOperation("Does have operation produces defined")
41+
public String withOperationProduces() {
42+
throw new UnsupportedOperationException();
43+
}
44+
45+
@PostMapping("/without-operation-consumes")
46+
@ApiOperation("Does not have operation consumes defined")
47+
public void withoutOperationConsumes(@RequestBody String test) {
48+
throw new UnsupportedOperationException();
49+
}
50+
51+
@PostMapping(value = "/with-operation-consumes", consumes = MediaType.APPLICATION_XML_VALUE)
52+
@ApiOperation("Does have operation consumes defined")
53+
public void withOperationConsumes(@RequestBody String test) {
54+
throw new UnsupportedOperationException();
55+
}
56+
57+
@PostMapping(value = "/with-operation-consumes-produces", consumes = MediaType.APPLICATION_XML_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
58+
@ApiOperation("Does have operation consumes and produces defined")
59+
public void withOperationConsumesAndProduces(@RequestBody String test) {
60+
throw new UnsupportedOperationException();
61+
}
62+
}

0 commit comments

Comments
 (0)