Skip to content

Commit c7ea34a

Browse files
thcedclaude
andcommitted
refactor(http): Rewrite OpenApiServer against new Spec/Validator/Router types
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0ca140d commit c7ea34a

1 file changed

Lines changed: 47 additions & 69 deletions

File tree

Lines changed: 47 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
package com.retailsvc.http;
22

3-
import static com.retailsvc.http.Handlers.notFoundHandler;
43
import static java.lang.Thread.ofVirtual;
5-
import static java.util.Objects.isNull;
64
import static java.util.Objects.requireNonNull;
75
import static java.util.concurrent.Executors.newThreadPerTaskExecutor;
86

9-
import com.retailsvc.http.openapi.OpenApiValidationFilter;
10-
import com.retailsvc.http.openapi.RequestDispatchingHandler;
11-
import com.retailsvc.http.openapi.model.JsonMapper;
12-
import com.retailsvc.http.openapi.model.OpenApi;
13-
import com.sun.net.httpserver.Filter;
7+
import com.retailsvc.http.internal.DispatchHandler;
8+
import com.retailsvc.http.internal.ExceptionFilter;
9+
import com.retailsvc.http.internal.RequestPreparationFilter;
10+
import com.retailsvc.http.internal.Router;
11+
import com.retailsvc.http.spec.Spec;
12+
import com.retailsvc.http.validate.DefaultValidator;
1413
import com.sun.net.httpserver.HttpContext;
1514
import com.sun.net.httpserver.HttpHandler;
1615
import com.sun.net.httpserver.HttpServer;
1716
import java.io.IOException;
1817
import java.net.InetSocketAddress;
19-
import java.util.List;
2018
import java.util.Map;
2119
import java.util.Optional;
2220
import org.slf4j.Logger;
@@ -30,96 +28,76 @@
3028
public class OpenApiServer implements AutoCloseable {
3129

3230
private static final Logger LOG = LoggerFactory.getLogger(OpenApiServer.class);
33-
private static final int PORT = 8080;
31+
private static final int DEFAULT_PORT = 8080;
3432

3533
private final HttpServer httpServer;
3634

3735
/**
38-
* @param specification The {@link OpenApi} specification
39-
* @param requestHandlers The mappings between operationId and {@link HttpHandler}
40-
* @param exceptionHandler Error handler receiving exception being thrown from a handler
41-
* @throws IOException If an error occur during server start
36+
* @param spec The parsed {@link Spec}
37+
* @param jsonMapper Body deserializer
38+
* @param handlers Mappings between operationId and {@link HttpHandler}
39+
* @param exceptionHandler Error handler receiving exceptions thrown from a handler
40+
* @throws IOException If an error occurs during server start
4241
*/
4342
public OpenApiServer(
44-
OpenApi specification,
43+
Spec spec,
4544
JsonMapper jsonMapper,
46-
Map<String, HttpHandler> requestHandlers,
45+
Map<String, HttpHandler> handlers,
4746
ExceptionHandler exceptionHandler)
4847
throws IOException {
49-
this(specification, jsonMapper, requestHandlers, exceptionHandler, PORT);
48+
this(spec, jsonMapper, handlers, exceptionHandler, DEFAULT_PORT);
5049
}
5150

5251
/**
53-
* @param specification The {@link OpenApi} specification
54-
* @param requestHandlers The mappings between operationId and {@link HttpHandler}
55-
* @param exceptionHandler Error handler receiving exception being thrown from a handler
56-
* @param httpPort The server port to use
57-
* @throws IOException If an error occur during server start
52+
* @param spec The parsed {@link Spec}
53+
* @param jsonMapper Body deserializer
54+
* @param handlers Mappings between operationId and {@link HttpHandler}
55+
* @param exceptionHandler Error handler receiving exceptions thrown from a handler
56+
* @param port The server port to use
57+
* @throws IOException If an error occurs during server start
5858
*/
5959
public OpenApiServer(
60-
OpenApi specification,
60+
Spec spec,
6161
JsonMapper jsonMapper,
62-
Map<String, HttpHandler> requestHandlers,
62+
Map<String, HttpHandler> handlers,
6363
ExceptionHandler exceptionHandler,
64-
int httpPort)
64+
int port)
6565
throws IOException {
6666

67-
long t0 = System.currentTimeMillis();
68-
LOG.debug("Starting server...");
69-
70-
requireNonNull(specification, "OpenAPI specification must not be null");
71-
requireNonNull(jsonMapper, "Request body mapper must not be null");
72-
requireNonNull(requestHandlers, "Request handlers must not be null");
73-
74-
if (isNull(exceptionHandler)) {
75-
LOG.warn("No exception handler set, using default.");
67+
requireNonNull(spec, "Spec must not be null");
68+
requireNonNull(jsonMapper, "JsonMapper must not be null");
69+
requireNonNull(handlers, "handlers must not be null");
70+
if (exceptionHandler == null) {
71+
LOG.warn("No ExceptionHandler set, using default");
7672
exceptionHandler = Handlers.defaultExceptionHandler();
7773
}
7874

79-
httpServer =
80-
initializeServer(
81-
httpPort, specification, jsonMapper, requestHandlers, exceptionHandler, t0);
82-
}
83-
84-
public int listenPort() {
85-
return httpServer.getAddress().getPort();
86-
}
87-
88-
private HttpServer initializeServer(
89-
int port,
90-
OpenApi specification,
91-
JsonMapper jsonMapper,
92-
Map<String, HttpHandler> requestHandlers,
93-
ExceptionHandler errorHandler,
94-
long t0)
95-
throws IOException {
96-
97-
HttpServer server = createHttpServer(port);
98-
HttpContext context = server.createContext(specification.basePath());
75+
long t0 = System.currentTimeMillis();
76+
Router router = new Router(spec.operations());
77+
DefaultValidator validator = new DefaultValidator(spec::resolveSchema);
9978

100-
List<Filter> filters = context.getFilters();
101-
filters.add(new ExceptionHandlingFilter(errorHandler));
102-
filters.add(new BodyHandler());
103-
filters.add(new OpenApiValidationFilter(specification, jsonMapper));
79+
this.httpServer = HttpServer.create(new InetSocketAddress(port), 0);
80+
httpServer.setExecutor(newThreadPerTaskExecutor(ofVirtual().name("http-", 0).factory()));
10481

105-
context.setHandler(new RequestDispatchingHandler(requestHandlers));
82+
HttpContext ctx = httpServer.createContext(Optional.ofNullable(spec.basePath()).orElse("/"));
83+
ctx.getFilters().add(new ExceptionFilter(exceptionHandler));
84+
ctx.getFilters().add(new RequestPreparationFilter(spec, router, validator, jsonMapper));
85+
ctx.setHandler(new DispatchHandler(handlers));
10686

107-
server.createContext("/", notFoundHandler());
108-
server.start();
87+
httpServer.createContext("/", Handlers.notFoundHandler());
88+
httpServer.start();
10989

110-
LOG.info("Server started (port {}) in {}ms", PORT, System.currentTimeMillis() - t0);
90+
LOG.info("Server started (port {}) in {}ms", port, System.currentTimeMillis() - t0);
91+
}
11192

112-
return server;
93+
public int listenPort() {
94+
return httpServer.getAddress().getPort();
11395
}
11496

11597
@Override
11698
public void close() {
117-
Optional.ofNullable(httpServer).ifPresent(server -> server.stop(0));
118-
}
119-
120-
private HttpServer createHttpServer(int port) throws IOException {
121-
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
122-
server.setExecutor(newThreadPerTaskExecutor(ofVirtual().name("http-", 0).factory()));
123-
return server;
99+
if (httpServer != null) {
100+
httpServer.stop(0);
101+
}
124102
}
125103
}

0 commit comments

Comments
 (0)