Zuul routing in microservices - spring

I am trying to access a microservice endpoint through a gateway using jhipster. The end point is from a legacy system and starts with "/d" and cannot be modified. I want the gateway to route all the requests that start with '/d/** ' to my microservice where I have a rest controller that will handle the requests that is mapped to '/api/d/**'
I'm trying to work using the documentation, so I have in my gateway the route:
zuul:
routes:
my-service-route:
path:/d/**
serviceId: serviceName
I saw that using url in zuul configuration you can specify the url directly, but I use jhipster registry so I can't approach the problem like that. As far as I understand I have to write a custom Zuul Filter or a Zuul Route Configuration that will route the requests to my service.
So I have 2 problems:
I can't access the gateway if I use a rest that begins with /d
I can't route the requests to my microservice in the way that I expect:
/d/service to be routed to my microservice where I have a restcontroller with a mapping to "/d/service".
Any info on how I should approach this is highly appreciated.
Thanks.
EDIT:
I already added my path in WebConfig source.registerCorsConfiguration("/d/**", config); and in SecurityConfiguration .antMatchers("/d/**").authenticated()

Can you try this below configuration in application.properties also you can change it to yml accordingly. so any request coming as /d/* will redirect to serviceName application instance.
zuul.routes.serviceName.serviceId=serviceName
zuul.routes.serviceName.path=/d/**
zuul.routes.serviceName.sensitive-headers=Set-Cookie,Authorization
hystrix.command.serviceName.execution.isolation.thread.timeoutInMilliseconds=600000

Related

How to detect new REST calls dynamically as and when they are available?

I am creating an API gateway using Netflix Zuul and Netflix Eureka doing the part of service registration for service discovery for a microservices framework.
I am trying to support a use case where new micro-services may come up which expose REST calls, or existing micro-services may get upgraded to expose new REST calls with version as part of their URL etc. Eureka runs as a dedicated springboot application and Zuul runs as a dedicated application. The application.prop or application.yml file of Zuul is where i am putting config for zuul.routes for each micro-services
My zuul's application.yml looks something like this to support one microservice config.
zuul:
routes:
example:
path: /example/**
stripPrefix: false
serviceId: zuul-service
If i bring down zuul add another such snippet of config under zuul:routes:
and then bring up zuul again, i will start seeing the new endpoint. But i want that to happen dynamically. Like Eureka will dynamically detect any new micro-services that come up or go down. If zuul can get in sync with Eureka then all my rest endpoints can be exposed perfectly through my Zuul api gateway.
Any suggestions on what i may be missing or add any other open source third party to achieve this will be helpful.

Zuul proxy that discovers routes dynamically

I have a simple Zuul app that has a single route in the application.yml to route to my microservice. It's working.
However, what I'm looking for is a more dynamic solution where I can wire up routes dynamically, either through code or perhaps by POSTing to some Zuul endpoints during a build (possibly by using springfox and a swagger definition from microservices). I could not find an API for Zuul.
I'm somewhat aware of Eureka and that seems like a solution to abstract away the routing by doing discovery. However, I'm curious if there's a solution without introducing Eureka. If there's a way to wire up these routes in Zuul during a build vs. having to edit the application.yml every time.
Thanks in advance.
If you go for Eureka this will actually work ootb. Zuul as packaged in spring cloud will automatically expose every service using its name. So if you register a service called users in Eureka, Zuul will automatically create a route /users forwarding to the instances by default. That will only allow simple url structures but should solve your problem.
Please see the official documentation for details:
By convention, a service with the ID "users", will receive requests from the proxy located at /users (with the prefix stripped). The proxy uses Ribbon to locate an instance to forward to via discovery, and all requests are executed in a hystrix command, …
I'm actually editing a blog post about this exact topic (Routing and Filtering using Spring Cloud Zuul Server) but the source code has been available and working for some time now. Feel free to use it as a reference:
https://bitbucket.org/asimio/zuulserver
https://bitbucket.org/asimio/discoveryserver (in case routes are configured with serviceIds)
https://bitbucket.org/asimio/demo-config-properties/src (Zuul-Server-refreshable.yml where routes are dynamically updated).
Look at the refreshable Spring profile settings. This Zuul setup works with both, hard-coding routes url or discovered using Eureka.
It also acting as a Spring Cloud Config client so that routes could be dynamically updated via Git, which is also covered in another blog post: Refreshable Configuration using Spring Cloud Config Server, Spring Cloud Bus, RabbitMQ and Git.

spring session sharing between zuul and resource servers

I was trying to search, but did not find an answer suited to our situation.
Basically, we have zuul server as API gateway which does following responsibilites
+ Autheticate user, and create and maintain session with users
+ Sessions will be stored in redis (we are using spring session with redis)
I want to have all of resource servers having access to session information created by zuul server. But I could not get session information from resource servers. its alway return null, I have checked redis server and seen session is created by zuul server already
Note that we are using Netflix service discovery to forward request from Zuul respective service.
highly appreciate for any advice
actually I was missing the following code.
context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.getId());
After adding above code to pass session_id in the cookie from zuul filter to respective micro-services, it is able to pickup the session_id from zuul filter.
I had the same problem. But after I have configured the application.yml to set "sensitiveHeaders" to empty. My problem is solved! :)
zuul:
routes:
users:
path: /myusers/**
sensitiveHeaders:
url: https://downstream
you can see more details at this link
Even though you're storing session in Redis, session id is stored in cookie and must be delivered to your resource servers. But the default configuration of zuul is filtering out all cookie related headers.
The below is default configuration of zuul for senstive-headers those are not passed to downstream servers.
zuul.sensitiveHeaders=Cookie,Set-Cookie,Authorization
To pass cookie related headers from zuul to your resources servers, You need to redefine it without cookie related headers like belows.
zuul.sensitiveHeaders=Authorization
The above example is using global configuration. You can define it for each route. Please refer to the section "Cookies and Sensitive Headers" in the the linked doc : http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html
If you also need to authorization header in your resources servers, you can define above configuration with blank list.
make sure your are using filter more than 5
#Override
public int filterOrder() {
return 10;
}
for more detail find the below example
https://stackoverflow.com/a/54833734/11103297
When using Spring Session and Spring Security to protect APIs in a Microservice application, it is easy to set up to use the request header to resolve the session, the usage is very similar to the OAuth2 opaque token.
Declare a bean HttpSessionIdResolver.
HeaderHttpSessionIdResolver.xAuthToken()
Note: this is for Spring MVC. It will resolve the HTTP header x-auth-token.
When a request is sent from client, in the gateway, pass the header x-auth-token to the downstream services/components.
An working example: hantsy/spring-microservice-sample (But I did not use Zuul like Gateway in this sample application, and simply I used Nginx as reserve proxy)

Spring Cloud Zuul: how to add route without restart

I am writing microservices with Spring Cloud.
I'm also using Zuul as the API Gateway which routes some URLs to destination services which are not registered into Eureka.
When a new route needed to be added to Zuul, we often edit the application.yml file and then restart the Zuul server.
I was wondering is there a way to add new route into Zuul without restarting the Zuul server?
I found this link useful but it only works for services registed in Erueka.

Cannot access the microservice through the gateway

I am not experienced in spring micro services and zuul configuration so I will need some help.
I have a microservice running on jhipster-registry and I am trying to access the microservice from my application through the gateway.
In my application I have this service in the current routes:
If I am accessing the service when my application is started as a spring boot app everything works fine; but when I deploy my application on tomcat the same request returns 404.
Here is the zuul config :
zuul:
routes:
assessmentapi:
path: /assessmentapi/**
serviceId: assessmentapi
url: http://192.168.80.44:8081/assessment-api
and http get request
$http.get('/assessmentapi/main/....)
You should not write the URL part in your configuration. As we can see on your gateway screenshot, the gateway already knows the service's IP thanks to Eureka and the Registry. IP addresses should never go into the config as those are determined dynamically.

Resources