Zuul routing doesn't work, gives 404 : Spring Boot+ Cloud+ Zuul - rest

I am working on a flow where I have ng4+boot app running on https://host_a:8080 and a backend service at https://host_b:8080 with some APIs.
I have RestController/Path at both the hosts, i.e. I need some urls to hit localhost (host_a) and others to host_b.
In application.yml, I have tried almost all possible combinations of Zuul routes but still getting 404 for all host_b rest APIs. host_a APIs work well.
Note: We have this working when there is no rest API on host_a and no custom filter on host_a.
Is there something wrong working with filter? I don't see any log from zuul filter now after I added this controller to host_a
I am aware that I can use forward property to route to localhost which works well. But somehow host_b rest all gives 404 error.
My implementation requirements-
http://host_a:8080/api/abc/user to hit at localhost i.e. host_a
http://host_a:8080/api/xyz/getall to hit at host_b
Important- Need a custom zuul filter which adds certain headers to request before it's routed to host_b as explained in point 2. - Already at place, but cannot see logs inside it now.
What I tried already-
zuul:
routes:
xyz:
path: /api/xyz/**
url: http://host_b:8080/api/xyz
I tried almost everything, using prefix, strip-prefix, only host in url, using forward for local routing, etc. Nothing works.
Kindly help me with the possible causes I may be ignoring or if missing something?
Thanks in advance.

Finally, I was able to resolve issues.
1. I had to change jersey #Path to spring #RestController
2. Changed Zuul Filter order from 1 to 999.
Works well now.

Related

Cors and database uri problem in scaling out architecture

I have react frontend and spring boot backend with mongodb behind.
I have issues with setting 2 parameters in the spring boot service.
First is address of the mongodb which is now set as localhost:27017 in the application.properties
It works at localhost but since I plan to scale out using kubernetes and docker images i would like to know how to define
It and where for the case in which I have mongo1 mongo2 and mongo3 database hosts and would like to pass all 3 URIs ?
Second issues is more tricky! React frontend doesnt work in chrome until I put allow cross origin anotation over my spring rest endpoint . I used hardcoded localhost:3000 here but when I scale it out using kubernetes this wont work if it gets data from another host in the cluster.What to do here?
To answer your first question, you can configure multi data sources, see here documentation how you can configure more than one data sources (80.2 Configure Two DataSources.
For second question you can simply wildcard CORS URL or if you know all of your front end server urls which are load balanced you can pass as list of cors url.
– * – means that all origins are allowed.
– If undefined, all origins are allowed.
RECOMMENDATION
Run your react via yarn to deploy on Apache or ngnix. Once you seted up your domain or sub domain for front end, load balanced your front end so not required to run your front end on ports..

Setting up load-balancer based on authenticated users

I'm trying to set up a loadbalancer that would redirect to specific version of an application certein users. So far i was using Blue/Green deployment strategy (so once i made new version of an app i created new environment and redirected traffic there). Now i would like to change this approach. I want to be able to specify users (more experienced or whatever) that would see new site after authentication while the others would still be redirected to old one. If something goes wrong with new version all users will see old version. Currently my loadbalancing is made in apache and authentication is done on application level. So is this even possible? I know i could hardcode it in application but what if there is a bug in new feature and new users are still being redirected there? I would then need to stop application for all users and rollback to old version and that's bad i guess. I was thinking about using external CAS however didnt find any information if it would be possible then. So i would like to ask is it possible and are there any tools (maybe some apache plugin) for that purpose?
Here's a working solution with nginx
create conf.d/balancer.conf
put the code into it (see below)
docker run -p8080:8080 -v ~/your_path/conf.d:/etc/nginx/conf.d openresty/openresty:alpine
use curl to play with it
balancer.conf:
map $cookie_is_special_user $upstream {
default http://example.com;
~^1$ http://scooterlabs.com/echo;
}
server {
listen 8080;
resolver 8.8.8.8;
location / {
proxy_pass $upstream;
}
}
testing
curl --cookie "is_special_user=1" http://localhost:8080
It would return the contents of scooterlabs.com dumping the request it receives
curl http://localhost:8080
Produces the contents of example.com
explanation
the idea is that you set a special cookie to the users you treat as special by the backend app after they get authorized as usual
of course it would only work if both app versions are served on the same domain so that the cookie is seen by both versions
after that you balance them to a desired server depending on the cookie value
you can easily disable such routing by tweaking your nginx config file
with this approach you can come up with even more complex scenarios like setting random cookie values in the range 1-10 and then gradually switching some of the special users in your config file i.e. start with those having value 1, after that 1-2 etc

Mulesoft - Uh-oh spaghettios! There's nothing here

This error is driving me nuts...
Situation:
I am trying to create a REST api and use a api-gateway proxy to access it. Proxy URL is HTTPS.
The deployment goes through fine. No errors reported in the logs. Worker assigned.
However when I try to access through browser get the "Uh-oh spaghettios! There's nothing here.".
Have tried all the usual things like making the https port dynamic using ${https.port} and using 0.0.0.0 instead of localhost in the http-listener config. But that does not help. Has this something to got to do with the proxy version ?
Any help or pointers will be great!
Make sure you follow Steps 2 from below link
Getting Started with Connectors
All,
Got the resolution. The problem was with the certificate chain. The keystore did not contain intermediate certificates. When added to the keystore the connectivity worked fine.
Only if Mulesoft provided correct errors or detailed logging, I would have saved lot of time over this.
Thanks for your inputs.

Upgrading to Spring cloud 1.0.1 zuul url encoded parameters not working

We use zuul as an gateway to dispatch incoming requests to services.
When we upgraded from 1.0.0, we noticed two issues, one of which we got a workaround to.
The second issue is that in some of the incoming have encoded uris to deal with special characters in the request, e.g. ....rovi//45846 which needs to be changed to rovi%2F%2F45846 in order to pass in.
So for a rest uri like the following POST http://localhost:8902/contentservice/content/subscriptionPackages/624460160/channels/rovi%252F%252F45846
If I make this request directly to the service, it works correctly.
But if I route it through zuul as POST http://localhost:8765/contentservice/content/subscriptionPackages/624460160/channels/rovi%252F%252F45846 then it disappears.
Now if I take the % out it is passed in and treated as an error in the contentservice when I step through the content service front end controller (off course).
What has changed between spring cloud 1.0.0 to 1.0.1 in the zuul functionality to stop this from working. As it definitely was working in 1.0.0.
So the spring cloud team has fixed this in the snapshot releases and you can fixed more detail here
https://github.com/spring-cloud/spring-cloud-netflix/issues/366#issuecomment-106363315

Does Feign retry require some sort of configuration?

I just tried to do a attempted a seamless upgrade of a service in a test setup. The service is being accessed by a Feign client. And naively I was under the impression that with multiple instances available of the service, the client would retry another instance if it failed to connect to one.
That, however, did not happen. But I cannot find any mention of how Feign in Spring Cloud is supposed to be configured to do this? Although I have seen mentions of it supporting it (as opposed to using RestTemplate where you would use something like Spring Retry?)
If you are using ribbon you can set properties similar to the following (substituting "localapp" for your serviceid):
localapp.ribbon.MaxAutoRetries=5
localapp.ribbon.MaxAutoRetriesNextServer=5
localapp.ribbon.OkToRetryOnAllOperations=true
ps underneath Feign has a Retryer interface, which was made to support things like Ribbon.
https://github.com/Netflix/feign/blob/master/core/src/main/java/feign/Retryer.java
see if property works - OkToRetryOnAllOperations: true
You can refer application ->
https://github.com/spencergibb/spring-cloud-sandbox/blob/master/spring-cloud-sandbox-sample-frontend/src/main/resources/application.yml
Spencer was quick...was late by few minutes :-)