Whenever a request hits Zuul, I got a 302 redirect to the host of the actual service to be called. So the url gets rewritten by Zuul. I want to prevent this. The user should only see the hostname of Zuul.
I have a Spring Cloud Zuul that I use as a routing server. It has the following configs:
zuul:
ignoredServices: '*'
routes:
service1:
path: /service1/**
serviceId: service1
stripPrefix: false
service2:
path: /service2/**
serviceId: service2
stripPrefix: false
login:
path: /login/**
sensitiveHeaders:
serviceId: login
stripPrefix: false
And Zuul is using Eureka for the service discovering. Suppose logingateway is running on localhost:8081 and Zuul on localhost:8080. If go to localhost:8080/login, I'll get a 302 first and then to localhost:8081/login. I don't want 302 redirect and I want the hostname to stay the same. I didn't find any related document on this issue. Thanks.
As #spencergibb commented Zuul doesn't do any rewrite of the HTTP response. There is an open issue around this as well: https://github.com/spring-cloud/spring-cloud-netflix/issues/8. The consensus is that Zuul won't provide that but the scope got narrowed to just rewriting the location header which is part of the 302 redirect response. You can follow that issue to see where it goes but as it stands right now that isn't possible with Zuul built-in filters.
You can always create your own Post filter for Zuul to do this yourself. Check out the Zuul documentation to understand when filters are executed: https://github.com/Netflix/zuul/wiki/How-it-Works then read on how to write your own filter: https://github.com/Netflix/zuul/wiki/Writing-Filters
Related
I have a Spring Cloud Gateway sitting in front of other microservices. The gateway is also used as an authentication layer. I have my gateway at localhost:9000 and my microservice I would like to direct traffic to that has the predicate path (/api/scd/secure/**) on localhost:8050. I would like to prefix /ms/platform to get to the actual rest endpoint that sits in my microservice (so /ms/platform/api/scd/secure/**). The problem I have is that even if I set my uri to localhost:8050, it is using the gateway uri as the final destination (so localhost:9000/ms/platform/api/scd/secure/**)
I have tried to do lots of reading on the spring cloud gateway about how the PrefixPath filter works but everything i read suggests my configuration should work.
spring:
cloud:
gateway:
routes:
- id: scd_secure
uri: http://localhost:8500
predicates:
- Path=/api/scd/secure/**
filters:
- PrefixPath=/ms/platform
- GatewaySecurityFilter
I would expect in my GatewaySecurityFilter, the exchange.getRequest uri to be localhost:8050/ms/platform/api/scd/secure/**, but it ends up with localhost:9000/ms/platform/api/scd/secure/**
In a spring-cloud-netflix setup (everything uses feign,ribbon,eureka,zuul), is there any simple/elegant/out-of-the-box way (i.e. discovery based on serviceId vs URL) for CompositeAB to communicate to ServiceA and ServiceB through Zuul? In all of the examples I've seen, CompositeAB discovers and calls ServiceA directly vs. via the Zuul route for ServiceA.
Put another way, if ServiceA registers itself in Eureka as service-a, is the automatically created Zuul proxy for service-a exposed in Eureka in any discoverable way?
For real world context, this relates to network topology and firewalls (there's no direct route between CompositeAB and ServiceA - everything needs to go through the gateway). Using URLs in CompositeAB isn't awful, but seems to defeat the purpose of having the registry present (ideally, Zuul would register the proxy for service-a as something like "zuul-service-a" in the registry). That said, i do get how this particular use case doesn't really fit Zuul's purpose as an edge gateway.
Finally, i think i know how to get my desired effect through code - just wanted to check that i wasn't reinventing any wheels first.
Make sure that your Zuul proxy is registering with Eureka and fetching the registry. Any service that registers with eureka will get a route.
You don't have to allow every service that registers with eureka to be accessible via the proxy either.
A sample application.yml for your Zuul proxy that only allows service-a and service-b:
eureka:
client:
fetchRegistry: true
zuul:
add-proxy-headers: true
ignored-services: "*"
routes:
service-a:
serviceId: service-a
service-b:
serviceId: service-b
I have a python web app, and registered with eureka using restfull api[https://github.com/Netflix/eureka/wiki/Eureka-REST-operations], and I found it status UP on the eureka web page, but my gateway server(also registered with eureka) can not find it, I call the url "gateway-server-host/myapp-url" and the following response is:
com.netflix.zuul.exception.ZuulException: Forwarding error at
org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:188)
at
org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:163)
at
org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:111)
...
Caused by: com.netflix.client.ClientException: Load balancer does not
have available server for client: test at
com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483)
at
com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184)
at
com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
any advise for this problem???
Have you looked over Spring Cloud's Sidecar ?
It basically a service over your non-jvm language service (in your case python) and with sidecar service (you have to deploy your python service and the sidecar service on the same host, if I am not mistaken) and you will include in your Zuul the endpoint to the sidecar service, which will try to handle things like eureka and such.
You spin up a new spring-boot app, with #EnableSidecar annotated, you configure the health-uri and port
example application.yml
server:
port: 5678
spring:
application:
name: sidecar
sidecar:
port: 8000
health-uri: http://localhost:8000/health.json
You can checkout Spring Cloud's documentation regarding Sidecar here for more details how to set it up
Since you are using Zuul you need to manually register routes. Its okay for them to just include the application name, from Eureka.
Example of Zuul route config:
zuul:
routes:
application1: /app1/**
application2: /app2/**
application3:
path: /app3/**
url: http://10.0.8.11:3000/
applicationN is the name registred in Eureka. The url will be resolved and load balanced automatically. For app3 the url is manually specified.
Adding Sidecar solves this problem to an extent where your Zuul /routes shows the registered Application Name.
You must have experienced , even if you do not have an actual app and just put any name with a payload following this document - [https://github.com/Netflix/eureka/wiki/Eureka-REST-operations] , that too gets registered in Eureka as an app.
I have a Spring Cloud app that serves as Zuul Server (with #EnableZuulProxy) annotation. At this stage I have /api/* requests routed to proper middletier services, while all other requests routed to the presentation service, so from the configuration pov it looks like below:
zuul:
ignoredServices: '*'
routes:
reservation-owner:
path: /api/service1
url: http://service1.net
--- here couple of other api mappings --
ui:
path: /**
url: http://presentation-service.net/
This works great until I want to check any of the Actuator endpoints on the zuul proxy. Since they fall under the /**, they get routed to the presentation service.
I tried already setting specific endpoints to route to back to the zuul server, but if I am right, I end up with infinite loop of zuul calling itself. So if I am right, I am looking for a way to define path for presentation service that would include everything except of e.g. /admin/* endpoints. Is it possible? Or there is another approach that should be taken?
As soon as you set /** zuul swallows all requests. The only way to do it at that point, is to set the management port.
management.port=8081
pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.yml:
management:
endpoints:
web:
exposure:
include: "*"
Actuator endpoints here
Modifying application.yaml worked for me to routes and filters endpoints:
management:
endpoints:
web:
exposure:
include: 'routes,filters'
We have an infrastructure with service discovery and load balancing (i.e. server side with STM and weblogic cluster). Now we are in the process of refactoring into micro-services. We would need an API gateway which does basic routing to other microservices. Netflix Zuul looks a good candidate however I could not get Zuul working without Eureka - but we do not need Eureka since we already have service discovery and load balancing in place.
Is it possible to use Zuul without Eureka and Ribbon?
If yes please provide some guild-lines since the there's no mention about in the wiki.
Thanks.
Yes, it is totally possible.You have to use #EnableZuulProxy on your config class and config it something like this :
zuul:
routes:
yourService:
path: /yourService/**
serviceId: yourService
ribbon:
eureka:
enabled: false
yourService:
ribbon:
listOfServers: localhost:8080
A sample usage can be like this:
shared.microservice.customer.service1.url=zttp://127.0.0.1:8080/shared/microservice/customer/
shared.microservice.customer.service2.url=zttp://127.0.0.1:8181/shared/microservice/customer/
ribbon.eureka.enabled = false
zuul.routes.customer-micro-service.path: /shared/microservice/customer/**
zuul.routes.customer-micro-service.serviceId: customers
customers.ribbon.listOfServers =
zttp://ip:port1/shared/microservice/customer/,zttp://ip2:port2/shared/microservice/customer/
Yes, Of course you can. Actually, by default, if you use #EnableZuulProxy with the Spring Boot Actuator, you enable two additional endpoints:
Routes
Filters
application.yaml
zuul:
routes:
users:
path: /myusers/**
url: https://example.com/users_service
These simple url-routes do not get executed as a HystrixCommand, nor do they load-balance multiple URLs with Ribbon.
Yo can get more information from here.