Skip to content

Commit db3bc07

Browse files
committed
openapi: asciidoc output
- curl support form parameter - curl support query parameter - added schema, json, yaml filters - ref #3820
1 parent bc0ac2e commit db3bc07

File tree

24 files changed

+1710
-547
lines changed

24 files changed

+1710
-547
lines changed

jooby/src/main/java/io/jooby/StatusCode.java

Lines changed: 81 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -917,9 +917,27 @@ public final class StatusCode {
917917

918918
private final String reason;
919919

920+
private final transient boolean unknown;
921+
920922
private StatusCode(final int value, final String reason) {
921923
this.value = value;
922924
this.reason = reason;
925+
this.unknown = false;
926+
}
927+
928+
private StatusCode(final int value) {
929+
this.value = value;
930+
this.reason = Integer.toString(value);
931+
this.unknown = true;
932+
}
933+
934+
/**
935+
* True for custom status code.
936+
*
937+
* @return True for custom status code.
938+
*/
939+
public boolean isUnknown() {
940+
return unknown;
923941
}
924942

925943
/**
@@ -971,129 +989,68 @@ public int hashCode() {
971989
* @throws IllegalArgumentException if this enum has no constant for the specified numeric value
972990
*/
973991
public static StatusCode valueOf(final int statusCode) {
974-
switch (statusCode) {
975-
case CONTINUE_CODE:
976-
return CONTINUE;
977-
case SWITCHING_PROTOCOLS_CODE:
978-
return SWITCHING_PROTOCOLS;
979-
case PROCESSING_CODE:
980-
return PROCESSING;
981-
case CHECKPOINT_CODE:
982-
return CHECKPOINT;
983-
case OK_CODE:
984-
return OK;
985-
case CREATED_CODE:
986-
return CREATED;
987-
case ACCEPTED_CODE:
988-
return ACCEPTED;
989-
case NON_AUTHORITATIVE_INFORMATION_CODE:
990-
return NON_AUTHORITATIVE_INFORMATION;
991-
case NO_CONTENT_CODE:
992-
return NO_CONTENT;
993-
case RESET_CONTENT_CODE:
994-
return RESET_CONTENT;
995-
case PARTIAL_CONTENT_CODE:
996-
return PARTIAL_CONTENT;
997-
case MULTI_STATUS_CODE:
998-
return MULTI_STATUS;
999-
case ALREADY_REPORTED_CODE:
1000-
return ALREADY_REPORTED;
1001-
case IM_USED_CODE:
1002-
return IM_USED;
1003-
case MULTIPLE_CHOICES_CODE:
1004-
return MULTIPLE_CHOICES;
1005-
case MOVED_PERMANENTLY_CODE:
1006-
return MOVED_PERMANENTLY;
1007-
case FOUND_CODE:
1008-
return FOUND;
1009-
case SEE_OTHER_CODE:
1010-
return SEE_OTHER;
1011-
case NOT_MODIFIED_CODE:
1012-
return NOT_MODIFIED;
1013-
case USE_PROXY_CODE:
1014-
return USE_PROXY;
1015-
case TEMPORARY_REDIRECT_CODE:
1016-
return TEMPORARY_REDIRECT;
1017-
case RESUME_INCOMPLETE_CODE:
1018-
return RESUME_INCOMPLETE;
1019-
case BAD_REQUEST_CODE:
1020-
return BAD_REQUEST;
1021-
case UNAUTHORIZED_CODE:
1022-
return UNAUTHORIZED;
1023-
case PAYMENT_REQUIRED_CODE:
1024-
return PAYMENT_REQUIRED;
1025-
case FORBIDDEN_CODE:
1026-
return FORBIDDEN;
1027-
case NOT_FOUND_CODE:
1028-
return NOT_FOUND;
1029-
case METHOD_NOT_ALLOWED_CODE:
1030-
return METHOD_NOT_ALLOWED;
1031-
case NOT_ACCEPTABLE_CODE:
1032-
return NOT_ACCEPTABLE;
1033-
case PROXY_AUTHENTICATION_REQUIRED_CODE:
1034-
return PROXY_AUTHENTICATION_REQUIRED;
1035-
case REQUEST_TIMEOUT_CODE:
1036-
return REQUEST_TIMEOUT;
1037-
case CONFLICT_CODE:
1038-
return CONFLICT;
1039-
case GONE_CODE:
1040-
return GONE;
1041-
case LENGTH_REQUIRED_CODE:
1042-
return LENGTH_REQUIRED;
1043-
case PRECONDITION_FAILED_CODE:
1044-
return PRECONDITION_FAILED;
1045-
case REQUEST_ENTITY_TOO_LARGE_CODE:
1046-
return REQUEST_ENTITY_TOO_LARGE;
1047-
case REQUEST_URI_TOO_LONG_CODE:
1048-
return REQUEST_URI_TOO_LONG;
1049-
case UNSUPPORTED_MEDIA_TYPE_CODE:
1050-
return UNSUPPORTED_MEDIA_TYPE;
1051-
case REQUESTED_RANGE_NOT_SATISFIABLE_CODE:
1052-
return REQUESTED_RANGE_NOT_SATISFIABLE;
1053-
case EXPECTATION_FAILED_CODE:
1054-
return EXPECTATION_FAILED;
1055-
case I_AM_A_TEAPOT_CODE:
1056-
return I_AM_A_TEAPOT;
1057-
case UNPROCESSABLE_ENTITY_CODE:
1058-
return UNPROCESSABLE_ENTITY;
1059-
case LOCKED_CODE:
1060-
return LOCKED;
1061-
case FAILED_DEPENDENCY_CODE:
1062-
return FAILED_DEPENDENCY;
1063-
case UPGRADE_REQUIRED_CODE:
1064-
return UPGRADE_REQUIRED;
1065-
case PRECONDITION_REQUIRED_CODE:
1066-
return PRECONDITION_REQUIRED;
1067-
case TOO_MANY_REQUESTS_CODE:
1068-
return TOO_MANY_REQUESTS;
1069-
case REQUEST_HEADER_FIELDS_TOO_LARGE_CODE:
1070-
return REQUEST_HEADER_FIELDS_TOO_LARGE;
1071-
case SERVER_ERROR_CODE:
1072-
return SERVER_ERROR;
1073-
case NOT_IMPLEMENTED_CODE:
1074-
return NOT_IMPLEMENTED;
1075-
case BAD_GATEWAY_CODE:
1076-
return BAD_GATEWAY;
1077-
case SERVICE_UNAVAILABLE_CODE:
1078-
return SERVICE_UNAVAILABLE;
1079-
case GATEWAY_TIMEOUT_CODE:
1080-
return GATEWAY_TIMEOUT;
1081-
case HTTP_VERSION_NOT_SUPPORTED_CODE:
1082-
return HTTP_VERSION_NOT_SUPPORTED;
1083-
case VARIANT_ALSO_NEGOTIATES_CODE:
1084-
return VARIANT_ALSO_NEGOTIATES;
1085-
case INSUFFICIENT_STORAGE_CODE:
1086-
return INSUFFICIENT_STORAGE;
1087-
case LOOP_DETECTED_CODE:
1088-
return LOOP_DETECTED;
1089-
case BANDWIDTH_LIMIT_EXCEEDED_CODE:
1090-
return BANDWIDTH_LIMIT_EXCEEDED;
1091-
case NOT_EXTENDED_CODE:
1092-
return NOT_EXTENDED;
1093-
case NETWORK_AUTHENTICATION_REQUIRED_CODE:
1094-
return NETWORK_AUTHENTICATION_REQUIRED;
1095-
default:
1096-
return new StatusCode(statusCode, Integer.toString(statusCode));
1097-
}
992+
return switch (statusCode) {
993+
case CONTINUE_CODE -> CONTINUE;
994+
case SWITCHING_PROTOCOLS_CODE -> SWITCHING_PROTOCOLS;
995+
case PROCESSING_CODE -> PROCESSING;
996+
case CHECKPOINT_CODE -> CHECKPOINT;
997+
case OK_CODE -> OK;
998+
case CREATED_CODE -> CREATED;
999+
case ACCEPTED_CODE -> ACCEPTED;
1000+
case NON_AUTHORITATIVE_INFORMATION_CODE -> NON_AUTHORITATIVE_INFORMATION;
1001+
case NO_CONTENT_CODE -> NO_CONTENT;
1002+
case RESET_CONTENT_CODE -> RESET_CONTENT;
1003+
case PARTIAL_CONTENT_CODE -> PARTIAL_CONTENT;
1004+
case MULTI_STATUS_CODE -> MULTI_STATUS;
1005+
case ALREADY_REPORTED_CODE -> ALREADY_REPORTED;
1006+
case IM_USED_CODE -> IM_USED;
1007+
case MULTIPLE_CHOICES_CODE -> MULTIPLE_CHOICES;
1008+
case MOVED_PERMANENTLY_CODE -> MOVED_PERMANENTLY;
1009+
case FOUND_CODE -> FOUND;
1010+
case SEE_OTHER_CODE -> SEE_OTHER;
1011+
case NOT_MODIFIED_CODE -> NOT_MODIFIED;
1012+
case USE_PROXY_CODE -> USE_PROXY;
1013+
case TEMPORARY_REDIRECT_CODE -> TEMPORARY_REDIRECT;
1014+
case RESUME_INCOMPLETE_CODE -> RESUME_INCOMPLETE;
1015+
case BAD_REQUEST_CODE -> BAD_REQUEST;
1016+
case UNAUTHORIZED_CODE -> UNAUTHORIZED;
1017+
case PAYMENT_REQUIRED_CODE -> PAYMENT_REQUIRED;
1018+
case FORBIDDEN_CODE -> FORBIDDEN;
1019+
case NOT_FOUND_CODE -> NOT_FOUND;
1020+
case METHOD_NOT_ALLOWED_CODE -> METHOD_NOT_ALLOWED;
1021+
case NOT_ACCEPTABLE_CODE -> NOT_ACCEPTABLE;
1022+
case PROXY_AUTHENTICATION_REQUIRED_CODE -> PROXY_AUTHENTICATION_REQUIRED;
1023+
case REQUEST_TIMEOUT_CODE -> REQUEST_TIMEOUT;
1024+
case CONFLICT_CODE -> CONFLICT;
1025+
case GONE_CODE -> GONE;
1026+
case LENGTH_REQUIRED_CODE -> LENGTH_REQUIRED;
1027+
case PRECONDITION_FAILED_CODE -> PRECONDITION_FAILED;
1028+
case REQUEST_ENTITY_TOO_LARGE_CODE -> REQUEST_ENTITY_TOO_LARGE;
1029+
case REQUEST_URI_TOO_LONG_CODE -> REQUEST_URI_TOO_LONG;
1030+
case UNSUPPORTED_MEDIA_TYPE_CODE -> UNSUPPORTED_MEDIA_TYPE;
1031+
case REQUESTED_RANGE_NOT_SATISFIABLE_CODE -> REQUESTED_RANGE_NOT_SATISFIABLE;
1032+
case EXPECTATION_FAILED_CODE -> EXPECTATION_FAILED;
1033+
case I_AM_A_TEAPOT_CODE -> I_AM_A_TEAPOT;
1034+
case UNPROCESSABLE_ENTITY_CODE -> UNPROCESSABLE_ENTITY;
1035+
case LOCKED_CODE -> LOCKED;
1036+
case FAILED_DEPENDENCY_CODE -> FAILED_DEPENDENCY;
1037+
case UPGRADE_REQUIRED_CODE -> UPGRADE_REQUIRED;
1038+
case PRECONDITION_REQUIRED_CODE -> PRECONDITION_REQUIRED;
1039+
case TOO_MANY_REQUESTS_CODE -> TOO_MANY_REQUESTS;
1040+
case REQUEST_HEADER_FIELDS_TOO_LARGE_CODE -> REQUEST_HEADER_FIELDS_TOO_LARGE;
1041+
case SERVER_ERROR_CODE -> SERVER_ERROR;
1042+
case NOT_IMPLEMENTED_CODE -> NOT_IMPLEMENTED;
1043+
case BAD_GATEWAY_CODE -> BAD_GATEWAY;
1044+
case SERVICE_UNAVAILABLE_CODE -> SERVICE_UNAVAILABLE;
1045+
case GATEWAY_TIMEOUT_CODE -> GATEWAY_TIMEOUT;
1046+
case HTTP_VERSION_NOT_SUPPORTED_CODE -> HTTP_VERSION_NOT_SUPPORTED;
1047+
case VARIANT_ALSO_NEGOTIATES_CODE -> VARIANT_ALSO_NEGOTIATES;
1048+
case INSUFFICIENT_STORAGE_CODE -> INSUFFICIENT_STORAGE;
1049+
case LOOP_DETECTED_CODE -> LOOP_DETECTED;
1050+
case BANDWIDTH_LIMIT_EXCEEDED_CODE -> BANDWIDTH_LIMIT_EXCEEDED;
1051+
case NOT_EXTENDED_CODE -> NOT_EXTENDED;
1052+
case NETWORK_AUTHENTICATION_REQUIRED_CODE -> NETWORK_AUTHENTICATION_REQUIRED;
1053+
default -> new StatusCode(statusCode);
1054+
};
10981055
}
10991056
}

modules/jooby-openapi/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
<version>${jooby.version}</version>
1919
</dependency>
2020

21+
<dependency>
22+
<groupId>net.datafaker</groupId>
23+
<artifactId>datafaker</artifactId>
24+
<version>2.5.3</version>
25+
</dependency>
26+
2127
<!-- JAXRS -->
2228
<dependency>
2329
<groupId>jakarta.ws.rs</groupId>

modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/AsciiDocGenerator.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.HashMap;
1212
import java.util.List;
1313
import java.util.Map;
14+
import java.util.Optional;
1415

1516
import io.jooby.internal.openapi.asciidoc.Filters;
1617
import io.jooby.internal.openapi.asciidoc.Functions;
@@ -22,6 +23,12 @@
2223
import io.pebbletemplates.pebble.operator.BinaryOperator;
2324
import io.pebbletemplates.pebble.operator.UnaryOperator;
2425
import io.pebbletemplates.pebble.tokenParser.TokenParser;
26+
import io.swagger.v3.core.util.Json;
27+
import io.swagger.v3.core.util.Json31;
28+
import io.swagger.v3.core.util.Yaml;
29+
import io.swagger.v3.core.util.Yaml31;
30+
import io.swagger.v3.oas.models.SpecVersion;
31+
import io.swagger.v3.oas.models.servers.Server;
2532

2633
public class AsciiDocGenerator {
2734

@@ -34,14 +41,33 @@ public static String generate(OpenAPIExt openAPI, Path index) throws IOException
3441
return writer.toString();
3542
}
3643

37-
private static PebbleEngine newEngine(OpenAPIExt openAPI, Path baseDir) {
44+
@SuppressWarnings("unchecked")
45+
private static PebbleEngine newEngine(OpenAPIExt openapi, Path baseDir) {
46+
var json = (openapi.getSpecVersion() == SpecVersion.V30 ? Json.mapper() : Json31.mapper());
47+
var yaml = (openapi.getSpecVersion() == SpecVersion.V30 ? Yaml.mapper() : Yaml31.mapper());
3848
var snippetResolver = new SnippetResolver(baseDir.resolve("snippet"));
39-
var engine =
40-
newEngine(
41-
new OpenApiSupport(Map.of("openapi", openAPI, "snippetResolver", snippetResolver)));
49+
var serverUrl =
50+
Optional.ofNullable(openapi.getServers())
51+
.map(List::getFirst)
52+
.map(Server::getUrl)
53+
.orElse("");
54+
var openapiRoot = json.convertValue(openapi, Map.class);
55+
openapiRoot.put(
56+
"internal",
57+
Map.of(
58+
"openapi",
59+
openapi,
60+
"resolver",
61+
snippetResolver,
62+
"serverUrl",
63+
serverUrl,
64+
"json",
65+
json,
66+
"yaml",
67+
yaml));
68+
var engine = newEngine(new OpenApiSupport(openapiRoot));
4269
snippetResolver.setEngine(engine);
43-
return newEngine(
44-
new OpenApiSupport(Map.of("openapi", openAPI, "snippetResolver", snippetResolver)));
70+
return engine;
4571
}
4672

4773
private static PebbleEngine newEngine(OpenApiSupport extension) {
@@ -67,7 +93,7 @@ public OpenApiSupport(Map<String, Object> vars) {
6793

6894
@Override
6995
public Map<String, Filter> getFilters() {
70-
return Filters.fn();
96+
return Filters.allFilters();
7197
}
7298

7399
@Override

modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/RouteParser.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,11 @@ private void checkRequestBody(ParserContext ctx, OperationExt operation) {
164164
if (requestBody != null) {
165165
if (requestBody.getContent() == null) {
166166
// default content
167-
io.swagger.v3.oas.models.media.MediaType mediaType =
168-
new io.swagger.v3.oas.models.media.MediaType();
167+
var mediaType = new io.swagger.v3.oas.models.media.MediaType();
169168
mediaType.setSchema(ctx.schema(requestBody.getJavaType()));
170169
String mediaTypeName =
171170
operation.getConsumes().stream().findFirst().orElseGet(requestBody::getContentType);
172-
Content content = new Content();
171+
var content = new Content();
173172
content.addMediaType(mediaTypeName, mediaType);
174173
requestBody.setContent(content);
175174
}

0 commit comments

Comments
 (0)