I\'ve been trying to find a way to set the context path for a webflux application. I know I can configure it using
server.servlet.context-path
Here is an example of configuring the context path for WebFlux using Netty server based on a comment by @Dmytro Boichenko. You can also include customizers to configure the port and other properties.
@Configuration
public class NettyServerConfig {
@Value("${server.port}")
private int port;
@Value("${server.context.path}")
private String contextPath;
@Bean
public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {
NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory() {
@Override
public WebServer getWebServer(HttpHandler httpHandler) {
Map<String, HttpHandler> handlerMap = new HashMap<>();
handlerMap.put(contextPath, httpHandler);
return super.getWebServer(new ContextPathCompositeHandler(handlerMap));
}
};
webServerFactory.addServerCustomizers(portCustomizer());
return webServerFactory;
}
public NettyServerCustomizer portCustomizer() {
return new NettyServerCustomizer() {
@Override
public HttpServer apply(HttpServer httpServer) {
return httpServer.port(port);
}
};
}
}
Here's my way of doing it with Tomcat Reactive:
@Configuration
public class TomcatReactiveWebServerConfig extends TomcatReactiveWebServerFactory {
@Value("${server.servlet.context-path}")
private String contextPath;
/**
* {@inheritDoc}
*/
@Override
protected void configureContext(final Context context) {
super.configureContext(context);
if (StringUtils.isNotBlank(this.contextPath)) {
context.setPath(this.contextPath);
}
}
}
You can use web Filter, as mentioned in above answers, but you can do one more thing. Write a Base Controller and Extend every class to that Base Controller. For example:
Base Controller.java
@RestController
@RequestMapping("/{base_url}")
public abstract class BaseController {
}
NewController.java
@RestController
public class NewController extends BaseController{
@Autowired
DatabaseClient databaseClient;
@GetMapping("/status")
public Mono<Map<String, String>> status() {
return databaseClient.execute("SELECT 'ok'").
map(row -> singletonMap("status", row.get(0, String.class)))
.one();
}
}
So now you can hit /{base_url}/status
If you are configuring yourself the server (if you’re not using Spring Boot), you can setup a ContextPathCompositeHandler that wraps several handlers itself.
If you are using Spring Boot, this feature is not supported currently.
I was having the same issue since the loader balancer bases on the context path to route to different back end apps. One way to get around Spring Boot Webflux w/ the context path is using variables in the @XXXXMapping annotations. For instance @RequestMapping(value = "${server.servlet.context-path}/subpath")
According to this
There is servlet in the name of the property which should be a hint that won't work with webflux.
With springboot v2.3, you can put this in your properties file
spring.webflux.base-path=/your-path
release-notes reference: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#configurable-base-path-for-webflux-applications