Reputation: 2274
I have a Spring Boot application that is attempting to use Spring Cloud Gateway to access some microservices. The code I am using is based on instructions read at:
https://betterjavacode.com/programming/how-to-use-api-gateway-with-spring-cloud
Basically, my application duplicates the code provided on that site, including the two test microservices that the author created:
@RestController
@RequestMapping("/vendor")
public class VendorController
{
@GetMapping("/total")
public List vendors()
{
List list = new ArrayList<>();
list.add("CJI Consultants");
list.add("Signature Consultants");
list.add("Deloitte");
return list;
}
}
and
@RestController
@RequestMapping("/customer")
public class CustomerController
{
@GetMapping("/total")
public List customers()
{
List list = new ArrayList<>();
list.add("Microsoft");
list.add("Amazon");
list.add("Apple");
return list;
}
}
My actual gateway code is similar to the author's:
package com.betterjavacode.apigatewaydemo.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringCloudConfig
{
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder routeLocatorBuilder)
{
return routeLocatorBuilder.routes()
.route("customerModule", rt -> rt.path("/customer/**")
.uri("http://localhost:8081/"))
.route("vendorModule", rt -> rt.path("/vendor/**")
.uri("http://localhost:8082/"))
.build();
}
}
Unfortunately, when I run this application, enter the correct URLs:
http://localhost:8080/vendor/total
and
http://localhost:8080/customer/total
I get 404 errors!
The only way I seem able to access the two microservices through the gateway is to change the path to "/**". For example, in order to access the customer microservice I have to change:
.route("customerModule", rt -> rt.path("/customer/**") .uri("http://localhost:8081/"))
to
v.route("customerModule", rt -> rt.path("/**") .uri("http://localhost:8081/"))
then I can see the customer microservice output without problems. Of course, I cannot use the same path for both routes. It looks like this gateway is only able to handle one route using the "/**" path.
Am I missing something here? Can someone give some idea of why this isn't working properly? How can I get this gateway to forward to the paths it should be going to?
Upvotes: 1
Views: 5763
Reputation: 2274
I believe I have resolved the problem. It turns out that, for reasons unknown, whenever a route other than "/**" is used in the Gateway, the URI must not contain the HTTP prefix.
In other words, instead of having a route:
route("customerModule", rt -> rt.path("/customer/**")
.uri("http://localhost:8081/"))
The route should be without the HTTP prefix:
.route("customerModule", rt -> rt.path("/customer/**")
.uri("localhost:8081/"))
I do not know why this works, but it does. I can access the microservices as long as I format the uri without the prefix.
I discovered this by accident. I would be curious to know why it works that way, but at least this requirement should be documented.
Upvotes: 4
Reputation: 189
you can try to use StripPrefix
parameter.
return routeLocatorBuilder.routes()
.route("customerModule", rt -> rt.path("/customer/**")
.filters(f -> f.stripPrefix(0))
.uri("http://localhost:8081/"))
.route("vendorModule", rt -> rt.path("/vendor/**")
.filters(f -> f.stripPrefix(0))
.uri("http://localhost:8082/"))
.build();
or you can remove the @RequestMapping("/customer") and @RequestMapping("/vendor") because it deletes the prefix path before sending it downstream.
Upvotes: 0