I want to config zuul to route request to root / to a home page. I tried:
root:
path: /
url: http://hostname/home/index.jsp
and
root:
path: /**
url: http://hostname/home/index.jsp
But neither of them works. I just got a 404 NOT FOUND. I think the path match config should be similar to those with contexts, such as /service/**, but it's not.
This is what I have done to make this work.
Within Zuul -> controller:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String handleRequest() {
return "forward:/ux/";
}
Zuul Properties:
zuul:
addProxyHeaders: true
routes:
example-ux:
path: /ux/**
stripPrefix: false
Within example-ux Service properties:
server:
servlet-path: /*
context-path: /ux
This configuration also solves the problem of static resources resolution. i.e. /static/css static/js etc...
Related
I have the following configuration for request-based sticky session using Spring Cloud LoadBalancer
spring:
cloud:
discovery.client.simple.instances:
say-hello:
- instanceId: say-hello1
uri: http://localhost:8080
- instanceId: say-hello2
uri: http://localhost:8081
loadbalancer:
configurations: request-based-sticky-session
sticky-session:
add-service-instance-cookie: true
server.port:9090
the following call:
$ http :9090/hi 'Cookie:sc-lb-instance-id=say-hello1'
should go only to the say-hello1 instance based on the Request-based Sticky Session for LoadBalancer but instead is using round robin load balancing.
What do I miss here?
Here is the source code to try it: https://github.com/altfatterz/client-side-loadbalancing
There are 2 things to consider here:
In the sample, the cookie has to be passed on to the actual load-balanced request, for example like so:
#GetMapping("/hi")
public String hi(#RequestParam(value = "name", defaultValue = "Mary") String name) {
logger.info("Accessing /hi endpoint");
HttpHeaders headers = new HttpHeaders();
headers.set("Cookie", "sc-lb-instance-id=say-hello1");
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<String> greeting = restTemplate.exchange("http://say-hello/greeting", HttpMethod.GET, entity, String.class, new HashMap<>());
return greeting + " " + name;
}
This feature is only supported for WebClient-backed load-balancing. It was not properly documented. I have documented it here.
I have also created a GitHub issue for adding the non-reactive implementation, however, the decision to implement it will be dependant on larger community interest.
I would like to route traffic to pods based on headers - with a fallback.
The desired result would be a k8s cluster where multiple versions of the same service could be deployed and routed to using header values.
svcA
svcB
svcC
each of these services (the main branch of git repo) would be deployed either to default namespace or labelled 'main'. any feature branch of each service can also be deployed, either into its own namespace or labelled with the branch name.
Ideally by setting a header X-svcA to a value matching a branch name, we would route any traffic to the in matching namespace or label. If there is no such name space or label, route the traffic to the default (main) pod.
if HEADERX && svcX:label
route->svcX:label
else
route->svcX
The first question - is this (or something like) even possible with istio or linkerd
You can do that using Istio VirtualService
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
...
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
Read more here.
Yes you can rout the request based on a header with Istion & Linkerd
For istio there is nice article : https://dwdraju.medium.com/simplified-header-based-routing-with-istio-for-http-grpc-traffic-ff9be55f83ca
in istio's virtual service you can update the header like :
http:
- match:
- headers:
x-svc-env:
regex: v2
For linkerd :
Kind = "service-router"
Name = "service"
Routes = [
{
Match {
HTTP {
PathPrefix = "/api/service/com.example.com.PingService"
}
}
Destination {
Service = "pinging"
},
},
{
Match {
HTTP {
PathPrefix = "/api/service/com.example.com.PingService"
Header = [
{
Name = "x-version"
Exact = "2"
},
]
}
}
Destination {
Service = "pinging"
ServiceSubset = "v2"
},
}
How to achieve change servciceId based on request params ??
Below is our Zuul Config
zuul:
host:
connect-timeout-millis: 200000
connection-request-timeout-millis: 200000
socket-timeout-millis: 200000
ignored-services: "*"
routes:
route-1:
path: /path1/**
serviceId: ServiceA
route-2:
path: /path2/**
serviceId: ServiceB
Over here we are selecting serviceId based on path1/path2.
if http://localhost:8050/path1/endpointPath?requestParam=ParamValue1 this should call serviceA
if http://localhost:8050/path1/endpointPath?requestParam=ParamValue2 this should call serviceB
was able to achieve this by using route filter and config changes
Config :
routes:
route-1:
path: /**
serviceId: ServiceA
stripPrefix: true
RouteFilter:
Optional<String> parameter = Optional.ofNullable(ctx.getRequest().getParameter("requestparam"));
if (parameter.isPresent()) {
if (parameter.get().equalsIgnoreCase("ValueA")) {
ctx.set("serviceId", "ServiceA");
} else {
ctx.set("serviceId", "ServiceB");
}
}
Is this fine or do we have any simpler way to achieve ?
Here is there any we can limit not to define serviceId in properties file ?
We're using Spring Cloud Gateway in front of our backend services. We have a route similar to the following:
routes:
- id: foobar-service
uri: lb://foobar-service
predicates:
- Path=/foobar/**
filters:
- StripPrefix=1
We want to deny access to one particular subpath (e.g. /foobar/baz/**) but leave the rest open. Is it possible to do this using the YAML syntax? Perhaps we need to implement the routes using the Fluent API instead?
routes:
- id: foobar-baz-service
uri: no://op
predicates:
- Path=/foobar/baz/**
filters:
- SetStatus=403
- id: foobar-service
uri: lb://foobar-service
predicates:
- Path=/foobar/**
filters:
- StripPrefix=1
Sharing my experience with the API implementation with a single route.
#Bean
public RouteLocator routes( final RouteLocatorBuilder locatorBuilder ) {
RouteLocatorBuilder.Builder builder = locatorBuilder.routes();
builder.route(p -> p //
.path(getAllowedPaths()) //
.and() //
.not(n -> n.path(getRestrictedPaths()) //
.filters(f -> f //
//filters
.uri(uri)));
return builder.build();
}
I want to define the page language via url on a Symfony2 installation. My routing works via annotation inside the controller.
routing.yml
_index:
resource: "#MyMainBundle/Controller/SiteController.php"
type: annotation
siteController.php
/**
* #Route( "/{_locale}/{site}", name="_site_site", defaults={"_locale" = "en"}, requirements={"site" = "about|cities|download|blog", "_locale" = "en|de|fr|es"} )
*/
This works quiet well, but waht I want, is that the following url call the same action.
http://example.com/download
http://example.com/en/download
http://example.com/de/download
Without the languge-parameter, the page should switch back to the default language, but this is something I can handle inside my action.
I found this Answer, but could not get it to work at all.
Symfony2 default locale in routing
Just add another #Route annotation that does not include the locale.
/**
* #Route("/{_locale}/{site}/")
* #Route("/{site}/")
*/
This also works within annotations.yaml
frontend_controllers:
resource: ../../src/Controller/Frontend
type: annotation
prefix:
- /
- /{_locale}
defaults:
_locale: 'en'
Another simular solution for Symfony 5 that worked for me :
# config/routes/annotations.yaml
controllers:
resource: '../../src/Controller/'
type: annotation
prefix:
fr: ''
en: '/en'
Symfony documentation : https://symfony.com/doc/current/routing.html#localized-routes-i18n
Also if you have an api prefix you can use next config
controllers:
resource: ../../src/Controller/
type: annotation
prefix:
- api
- api/{_locale}
defaults:
_locale: en