-
-
Notifications
You must be signed in to change notification settings - Fork 545
Closed
Description
Describe the bug
My config (api-docs.yaml.txt):
openapi: 3.0.1
paths:
/api/users/self:
get:
tags:
- users
operationId: getMe
responses:
"200":
description: OK
content:
'*/*':
schema:
type: string
default:
$ref: '#/components/responses/default'
components:
schemas:
ErrorResponse:
type: object
properties:
code:
type: integer
format: int32
message:
type: string
responses:
default:
description: other error responses
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
$ref: '#/components/responses/default'
I noticed that componenets.responses[0].$ref
is included in the yaml which is not supposed to be there.
Here's my java code (Spring Boot 2.4.0, Springdoc 1.5.0):
public static final String JWT_SECURITY_SCHEME = "jwt";
private final List<CommonResponse> commonResponses = new LinkedList<>();
@Bean
public OpenAPI openApi() {
val components = new Components();
components.addSecuritySchemes(JWT_SECURITY_SCHEME,
new SecurityScheme()
.type(Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
);
addCommonSecurityResponses(components);
addDefaultErrorResponse(components);
return new OpenAPI()
.components(components)
.addSecurityItem(new SecurityRequirement().addList(JWT_SECURITY_SCHEME));
}
private void addDefaultErrorResponse(Components components) {
val schema = createSchema(components, ErrorResponse.class);
val key = ApiResponses.DEFAULT;
val response = new ApiResponse()
.$ref(key)
.description("other error responses")
.content(new Content().addMediaType(
org.springframework.http.MediaType.APPLICATION_JSON_VALUE,
new MediaType().schema(schema)
));
components.addResponses(key, response);
commonResponses.add(new CommonResponse(key, response.get$ref()));
}
private Schema<?> createSchema(Components components, Class<?> clazz) {
val type = new AnnotatedType(clazz).resolveAsRef(true);
val context = new ModelConverterContextImpl(ModelConverters.getInstance().getConverters());
val schema = context.resolve(type);
context.getDefinedModels().forEach(components::addSchemas);
return schema;
}
@Value
private static class CommonResponse {
String httpStatusCode;
String reference;
}
private void addCommonSecurityResponses(Components components) {
Stream.of(HttpStatus.UNAUTHORIZED, HttpStatus.FORBIDDEN).forEach(securityError -> {
val httpCodeStr = String.valueOf(securityError.value());
val response = new ApiResponse()
.$ref(httpCodeStr)
.description(securityError.getReasonPhrase())
.addHeaderObject(
HttpHeaders.WWW_AUTHENTICATE,
new Header().description("https://tools.ietf.org/html/rfc6750#section-3")
)
.content(new Content());
components.addResponses(httpCodeStr, response);
commonResponses.add(new CommonResponse(httpCodeStr, response.get$ref()));
}
);
}
/**
* see https://swagger.io/docs/specification/describing-responses/#reuse
*/
@Bean
OperationCustomizer defaultResponsesOperationCustomizer() {
return ((operation, handlerMethod) -> {
commonResponses.forEach(commonResponse -> {
val response = new ApiResponse().$ref(commonResponse.getReference());
operation.getResponses().addApiResponse(commonResponse.getHttpStatusCode(), response);
});
return operation;
});
}
Metadata
Metadata
Assignees
Labels
No labels