1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.forgerock.json.resource.http.examples;
18
19 import static org.forgerock.http.routing.RoutingMode.*;
20 import static org.forgerock.json.resource.Applications.*;
21 import static org.forgerock.json.resource.Requests.*;
22 import static org.forgerock.json.resource.Resources.*;
23 import static org.forgerock.json.resource.RouteMatchers.*;
24 import static org.forgerock.json.resource.http.CrestHttp.*;
25
26 import org.asciidoctor.Asciidoctor;
27 import org.asciidoctor.AttributesBuilder;
28 import org.asciidoctor.OptionsBuilder;
29 import org.asciidoctor.Placement;
30 import org.asciidoctor.SafeMode;
31 import org.forgerock.api.markup.ApiDocGenerator;
32 import org.forgerock.api.models.ApiDescription;
33 import org.forgerock.http.DescribedHttpApplication;
34 import org.forgerock.http.Handler;
35 import org.forgerock.http.HttpApplicationException;
36 import org.forgerock.http.example.DescribedOauth2Endpoint;
37 import org.forgerock.http.header.ContentTypeHeader;
38 import org.forgerock.http.io.Buffer;
39 import org.forgerock.http.protocol.Request;
40 import org.forgerock.http.protocol.Response;
41 import org.forgerock.http.protocol.Status;
42 import org.forgerock.http.routing.RouteMatchers;
43 import org.forgerock.http.routing.RoutingMode;
44 import org.forgerock.http.swagger.SwaggerApiProducer;
45 import org.forgerock.http.util.Uris;
46 import org.forgerock.json.resource.MemoryBackend;
47 import org.forgerock.json.resource.ResourcePath;
48 import org.forgerock.json.resource.Router;
49 import org.forgerock.json.resource.descriptor.examples.handler.UserCollectionHandler;
50 import org.forgerock.http.ApiProducer;
51 import org.forgerock.services.context.Context;
52 import org.forgerock.services.routing.DelegatingRouteMatcher;
53 import org.forgerock.services.routing.RouteMatch;
54 import org.forgerock.util.Factory;
55 import org.forgerock.util.promise.NeverThrowsException;
56 import org.forgerock.util.promise.Promise;
57
58 import io.swagger.models.Info;
59 import io.swagger.models.Scheme;
60 import io.swagger.models.Swagger;
61
62
63
64
65 public class CrestHttpApplication implements DescribedHttpApplication {
66
67 private static final String SWAGGER_JSON_ROUTE = "../..?_api";
68
69 private static final ContentTypeHeader HTML_CONTENT_TYPE_HEADER =
70 ContentTypeHeader.valueOf("text/html; charset=UTF-8");
71
72 @Override
73 public Handler start() throws HttpApplicationException {
74 final Asciidoctor asciidoctor = Asciidoctor.Factory.create();
75
76 final Router crestRouter = new Router();
77 crestRouter.addRoute(requestUriMatcher(STARTS_WITH, "/users"), newHandler(new MemoryBackend()));
78 crestRouter.addRoute(requestUriMatcher(STARTS_WITH, "/groups"), newHandler(new MemoryBackend()));
79 crestRouter.addRoute(requestUriMatcher(STARTS_WITH, "/api/users"), UserCollectionHandler.getUsersRouter());
80 crestRouter.addRoute(requestUriMatcher(STARTS_WITH, "/api/admins"), UserCollectionHandler.getAdminsRouter());
81
82 Handler crestHandler = newHttpHandler(simpleCrestApplication(newInternalConnectionFactory(crestRouter),
83 "frapi:example", "1.0"));
84
85 final org.forgerock.http.routing.Router router = new org.forgerock.http.routing.Router();
86 router.setDefaultRoute(crestHandler);
87 router.addRoute(RouteMatchers.requestUriMatcher(RoutingMode.STARTS_WITH, "/chf/oauth2"),
88 new DescribedOauth2Endpoint());
89
90
91 router.addRoute(RouteMatchers.requestUriMatcher(RoutingMode.STARTS_WITH, "/docs/html"),
92 new Handler() {
93 @Override
94 public Promise<Response, NeverThrowsException> handle(Context context, Request request) {
95 ApiDescription apiDescription = crestRouter.handleApiRequest(context,
96 newApiRequest(ResourcePath.empty()));
97 final String asciiDocMarkup = ApiDocGenerator.execute("Users and Devices API", apiDescription,
98 null);
99
100 final String html;
101 synchronized (asciidoctor) {
102 html = asciidoctor.render(asciiDocMarkup,
103 OptionsBuilder.options()
104 .attributes(AttributesBuilder.attributes()
105 .tableOfContents(Placement.LEFT)
106 .sectNumLevels(5)
107 .attribute("toclevels", 5)
108 .get())
109 .safe(SafeMode.SAFE)
110 .headerFooter(true)
111 .get());
112 }
113
114 final Response response = new Response(Status.OK);
115 response.getHeaders().add(HTML_CONTENT_TYPE_HEADER);
116 response.setEntity(html);
117 return Response.newResponsePromise(response);
118 }
119 });
120
121
122 router.addRoute(RouteMatchers.requestUriMatcher(RoutingMode.EQUALS, "/docs/api"),
123 new Handler() {
124 @Override
125 public Promise<Response, NeverThrowsException> handle(Context context, Request request) {
126 final String uri = request.getUri().toString();
127 final String baseUrl = uri.substring(0, uri.indexOf("/docs/api"));
128 final String url = baseUrl + "/openapi/index.html?url="
129 + Uris.urlEncodeQueryParameterNameOrValue(SWAGGER_JSON_ROUTE)
130 + "&title=" + Uris.urlEncodeQueryParameterNameOrValue("Users and Devices API");
131
132 final Response response = new Response(Status.FOUND);
133 response.getHeaders().add("Location", url);
134 return Response.newResponsePromise(response);
135 }
136 });
137
138
139 router.addRoute(new DelegatingRouteMatcher<Request>(RouteMatchers.requestUriMatcher(RoutingMode.EQUALS, "/")) {
140 @Override
141 public RouteMatch evaluate(Context context, Request request) {
142 if (request.getForm().containsKey("_crestapi")) {
143 return null;
144 }
145 return super.evaluate(context, request);
146 }
147 }, new Handler() {
148 @Override
149 public Promise<Response, NeverThrowsException> handle(Context context, Request request) {
150 final String html = "<!DOCTYPE html><html><head><title>CREST Examples</title></head><body>"
151 + "<p><a href=\"?_api\">Users and Devices API OpenAPI JSON</a></p>"
152 + "<p><a href=\"?_crestapi\">Users and Devices API CREST Descriptor JSON</a></p>"
153 + "<p><a href=\"./docs/api\">Users and Devices API explorer</a></p>"
154 + "<p><a href=\"./docs/html\">Users and Devices API documentation</a></p>"
155 + "</body></html>";
156
157 final Response response = new Response(Status.OK);
158 response.getHeaders().add(HTML_CONTENT_TYPE_HEADER);
159 response.setEntity(html);
160 return Response.newResponsePromise(response);
161 }
162 });
163 return router;
164 }
165
166 @Override
167 public Factory<Buffer> getBufferFactory() {
168 return null;
169 }
170
171 @Override
172 public void stop() {
173
174 }
175
176 @Override
177 public ApiProducer<Swagger> getApiProducer() {
178 return new SwaggerApiProducer(new Info().title("CREST Examples"), null, null, Scheme.HTTP);
179 }
180 }