Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.x - named routing #7705

Merged
merged 1 commit into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/webserver/multiport/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

It is common when deploying a microservice to run your service on
multiple ports so that you can control the visibility of your
service's endpoints. For example you might want to use three ports:
service's endpoints. For example, you might want to use three ports:

- 8080: public REST endpoints of application
- 8081: private REST endpoints of application
Expand All @@ -16,7 +16,7 @@ as described above.

The ports are configured in `application.yaml` by using named sockets.

Seperate routing is defined for each named socket in `Main.java`
Separate routing is defined for each named socket in `Main.java`

## Build and run

Expand All @@ -32,7 +32,7 @@ curl -X GET http://localhost:8080/hello

curl -X GET http://localhost:8081/private/hello

curl -X GET http://localhost:8082/health
curl -X GET http://localhost:8082/observe/health

curl -X GET http://localhost:8082/metrics
curl -X GET http://localhost:8082/observe/metrics
```
6 changes: 4 additions & 2 deletions examples/webserver/multiport/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,21 @@
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.webserver.observe</groupId>
<artifactId>helidon-webserver-observe-health</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.health</groupId>
<artifactId>helidon-health-checks</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.webserver.observe</groupId>
<artifactId>helidon-webserver-observe-metrics</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.helidon.metrics</groupId>
<artifactId>helidon-metrics-system-meters</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.helidon.webserver.testing.junit5</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,8 @@ static void setup(WebServerConfig.Builder server) {
// Build server using three ports:
// default public port, admin port, private port
server.routing(Main::publicRouting)
// Add a set of routes on the named socket "admin"
.putSocket("admin", socket -> socket.from(server.sockets().get("admin"))
.routing(Main::adminSocket))
// Add a set of routes on the named socket "private"
.putSocket("private", socket -> socket.from(server.sockets().get("admin"))
.routing(Main::privateSocket));
.routing("admin", Main::adminSocket)
.routing("private", Main::privateSocket);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,24 @@ class LoomServer implements WebServer, Startable {
if (routing.isEmpty() && routings.isEmpty()) {
routerBuilder.addRouting(HttpRouting.create());
}
Router router = routerBuilder.build();

Timer idleConnectionTimer = new Timer("helidon-idle-connection-timer", true);
Map<String, ServerListener> listenerMap = new HashMap<>();
sockets.forEach((name, socketConfig) -> {
List<Routing> socketRoutings = serverConfig.namedRoutings().get(name);
Router socketRouter;
if (socketRoutings != null) {
socketRouter = Router.builder()
.update(b -> socketRoutings.forEach(b::addRouting))
.build();
} else {
socketRouter = router;
}
listenerMap.put(name,
new ServerListener(name,
socketConfig,
routerBuilder.build(),
socketRouter,
context,
idleConnectionTimer,
serverConfig.mediaContext().orElseGet(MediaContext::create),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.helidon.webserver;

import java.util.List;
import java.util.Map;
import java.util.Optional;

Expand All @@ -32,6 +33,7 @@
* See {@link WebServer#create(java.util.function.Consumer)}.
*/
@Prototype.Blueprint(decorator = WebServerConfigBlueprint.ServerConfigDecorator.class)
@Prototype.CustomMethods(WebServerConfigSupport.CustomMethods.class)
@Configured(root = true, prefix = "server")
@ConfigBean(wantDefault = true)
interface WebServerConfigBlueprint extends ListenerConfigBlueprint, Prototype.Factory<WebServer> {
Expand All @@ -56,6 +58,17 @@ interface WebServerConfigBlueprint extends ListenerConfigBlueprint, Prototype.Fa
@Option.Singular
Map<String, ListenerConfig> sockets();

/**
* Routing for additional sockets.
* Note that socket named {@value WebServer#DEFAULT_SOCKET_NAME} cannot be used,
* configure the routing on the server directly.
*
* @return map of routing
*/
@Option.Singular
@Option.Access("")
Map<String, List<Routing>> namedRoutings();

/**
* Context for the WebServer, if none defined, a new one will be created with global context as the root.
*
Expand All @@ -70,6 +83,10 @@ public void decorate(WebServerConfig.BuilderBase<?, ?> target) {
throw new ConfigException("Default socket must be configured directly on server config node, or through"
+ " \"ServerConfig.Builder\", not as a separated socket.");
}
if (target.namedRoutings().containsKey(WebServer.DEFAULT_SOCKET_NAME)) {
throw new ConfigException("Default routing must be configured directly on server config node, or through"
+ " \"ServerConfig.Builder\", not as a named routing.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.helidon.webserver;

import java.util.function.Consumer;

import io.helidon.builder.api.Prototype;
import io.helidon.webserver.http.HttpRouting;

class WebServerConfigSupport {

static class CustomMethods {

/**
* Add Http routing for an additional socket.
*
* @param builder builder to update
* @param socket name of the socket
* @param consumer HTTP Routing for the given socket name
*/
@Prototype.BuilderMethod
static void routing(WebServerConfig.BuilderBase<?, ?> builder,
String socket,
Consumer<HttpRouting.Builder> consumer) {
HttpRouting.Builder routingBuilder = HttpRouting.builder();
consumer.accept(routingBuilder);
builder.addNamedRouting(socket, routingBuilder.build());
}

/**
* Add Http routing for an additional socket.
*
* @param builder builder to update
* @param socket name of the socket
* @param routing HTTP Routing for the given socket name
*/
@Prototype.BuilderMethod
static void routing(WebServerConfig.BuilderBase<?, ?> builder,
String socket,
HttpRouting routing) {
builder.addNamedRouting(socket, routing);
}
}
}