Zuul api-gateway does not work with context root - netflix-zuul

I am using zuul api gateway.
org.springframework.cloud
spring-cloud-starter-netflix-zuul
2.2.1.RELEASE
This call with this path works fine:
http://PMCS-HOMI:8085/spatest/service-synchronization/service/message
path: /spatest/service-synchronization/**
url: ${spa.synchronization.url}/service-synchronization
This call with this path does not work. I get an http error 405.
http://PMCS-HOMI:8085/spa/service-synchronization/service/message
path: /spa/service-synchronization/**
url: ${spa.synchronization.url}/service-synchronization
/spa is too the context root of my application.
I will be very grateful if someone helps me.
Regards.

Related

Cannot access api-docs of microservice from spring cloud gateway. Failed to load API definition

I'm trying to link my microservices to my gateway. , but I'm not able to access the api-docs of my microservice through the gateway.
Error from Swagger-UI:
Failed to load API definition
Fetch error
Not Found http://localhost:8080/microservice/v2/api-docs
Swagger version:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
I can GET the api-docs through the the microservice directly (port 8081):
http://localhost:8081/v2/api-docs
But I'm not able to do it through the gateway (port 8080):
http://localhost:8080/microservice/v2/api-docs
Microservice's properties:
spring:
application:
name: microservice
server:
port: 5082
...
Gateway's properties:
server:
port: 2443
spring:
cloud:
gateway:
routes:
- id: microservice
uri: lb://microservice
predicates:
- Path=/microservice/**
...
The workaround that I've found is to add a #GetMapping in my Controller.java to point the URL specifically to the api-docs (but I'm pretty sure this is not the proper solution).
WebClient webClient;
#ResponseBody
#GetMapping(value = "/v2/api-docs")
public String getApiDocs()
{
factory = new DefaultUriBuilderFactory("http://localhost:8081");
factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
this.webClient = WebClient
.builder()
.uriBuilderFactory(factory)
.build();
return webClient.get()
.uri("/v2/api-docs")
.retrieve()
.bodyToMono(String.class)
.block();
}
FYI:
The microservice and gateway are both registered with Eureka.
I can access the api-docs of the gateway just fine, but not the api-docs of the microservice.
The issue is that the gateway is not configured to load swagger associated resources (UI, config files).
I will use in the explanation gateway config using #Configuration class, but probably it can be used in the properties file as well.
Specify for each service a custom Swagger API path. So it can be used to configure routing in the gateway in the next steps. It will add prefix /microservice1-api in the path for the swagger UI URL and swagger JSON configuration file.
springdoc:
api-docs:
path: /microservice1-api
swagger-ui:
path: /api.html
Specify the route to each prefix in the gateway config. So it will be properly route paths associated with service swagger resources.
RouteLocatorBuilder.Builder apiDocJsonRoutes(RouteLocatorBuilder.Builder builder) {
//uri can be actual URI or load balancer path
return builder
.route(p -> p.path( "/microservice1-api/**").uri("microservice1"))
.route(p -> p.path( "/microservice2-api/**").uri("microservice2"))
.route(p -> p.path("/microservice3-api/**").uri("microservice3"));
}
You have to define routing for /swagger-ui/index.html path to proper service. In this case path to service is recognized by URL parameter configUrl. After Step 1 if you open swagger in the browser, you will see that at the end of address line you have parameter ?configUrl=/microservice1-api/swagger-config. So if this parameter value has prefix associated with a specific service, you can use it for routing.
RouteLocatorBuilder.Builder apiDocUIRoutes(RouteLocatorBuilder.Builder builder) {
return builder
.route(p -> swaggerUi(p, "microservice1", "/microservice1-api/swagger-config"))
.route(p -> swaggerUi(p, "microservice2", "/microservice2-api/swagger-config"))
.route(p -> swaggerUi(p, "microservice3", "/microservice3-api/swagger-config"));
}
private Buildable<Route> swaggerUi(PredicateSpec p, String service, String expectedValue) {
return p.path("/swagger-ui/index.html").and().query("configUrl", expectedValue)
.uri(service);
}
Open API in the browser using http://gateway_path/microservice_route/api.html

Webpush::Unauthorized: host: fcm.googleapis.com, #<Net::HTTPForbidden 403 Forbidden readbody=true>

I am trying to integrate Web Push Notification on the Web Application I am maintaining. I am using this github repo https://github.com/zaru/webpush as my guide.
After following what is included in that guide, and run this command at my terminal:
Webpush.payload_send(message: "Test", endpoint: n.endpoint, p256dh: n.p256dh_key, auth: n.auth_key, vapid: {private_key: "gAdLtJoNQHDXsd1iYxrvttW3YybuJX4GkN8LDMbSIuw=", public_key: "BHByXuCTQs7UuoqBN2MeLjL_gUHfsuhxKkV_QOdhm9mw9Ohl3giAoxdwtwuoXqYnIbaa7UaTC1BvwS8yv_pNOAU="} )
Suddenly, I encountered this error, does someone here encountered the same error as I did? How did you resolved it? Thank you in advance.
Webpush::Unauthorized: host: fcm.googleapis.com, #<Net::HTTPForbidden 403 Forbidden readbody=true>
body:
the key in the authorization header does not correspond to the sender ID used to subscribe this user. Please ensure you are using the correct sender ID and server Key from the Firebase console.

Spring cloud gateway not routing web-socket based requests

In order to add a route for a websocket based micro-service I have
Configured my application as per Spring cloud gateway documentation
- id: sample_service_web_socket_handshake_url
uri: lb:ws://sample-service
predicates:
- Path=/notification-service-ws/**
above notification-service-ws is the handshake url of websocket-service
upon accessing this websocket endpoint directly( without spring-cloud-gateway ) session has been connected with no issue
but upon trying to connect using spring-cloud-gateway the gateway gives following warning log
2020-01-09 10:44:02.923 WARN 5155 --- [-server-epoll-5] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET http://192.168.10.44:4260/notification-service-ws]: Response status 400 with reason "Invalid 'Upgrade' header: {Sec-WebSocket-Version=[13], Sec-WebSocket-Key=[0EJxcMdBmRhZ5suS/INKnQ==], Sec-WebSocket-Extensions=[permessage-deflate; client_max_window_bits], Host=[192.168.10.44:4260]}"
I have verified no HTTP request is being sent to websocket service
Issue resolved after adding following properties to spring-cloud-gateway application.yml file:
spring:
application:
name: burraq-api-gateway
profiles:
active: dev
cloud:
gateway:
filter:
remove-non-proxy-headers:
headers:
- Proxy-Authenticate
- Proxy-Authorization
- Keep-Alive
- TE
- Trailer
- Transfer-Encoding
This issue occurred because spring cloud gateway by default request headers as mentioned here

haproxy redirect URL path to another path

haproxy version 1.5.18
I want to redirect:
/document/(.*)/(.*)/somefile => /anotherPath/somefile
For example: redirect
/document/20181/20182/a_good_pic.jpg => /anotherPath/a_good_pic.jpg
How to do that with haproxy?
I retried follow the example for reqirep like:
# replace "/static/" with "/" at the beginning of any request path.
reqrep ^([^\ :]*)\ /static/(.*) \1\ /\2
But my example has two parts in URL path that are different to the example, so I got confused.
Thanks!
You could declare an acl and then do a conditional use_backend statement. Like this:
frontend a-frontend-conf
# Declare an ACL using path_beg (Path Begins)
acl path_images path_beg /images
# Use backend server1 if acl condition path_images is fulfilled
use_backend server1 if path_images
backend server1
[...]
Source: https://serverfault.com/questions/659793/haproxy-how-to-balance-traffic-within-directory-reached

Zuul Proxy not able to route, resulting in com.netflix.zuul.exception.ZuulException: Forwarding error

I have simple services as:
transactions-core-service and transactions-api-service.
transactions-api-service invokes transactions-core-service to return a list of transactions. transactions-api-service is enabled with hystrix command.
Both are registered in Eureka server with below services ids:
TRANSACTIONS-API-SERVICE n/a (1) (1) UP (1) - 192.168.2.12:transactions-api-service:8083
TRANSACTIONS-CORE-SERVICE n/a (1) (1) UP (1) - 192.168.2.12:transactions-core-service:8087
Below is Zuul server:
#SpringBootApplication
#Controller
#EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ZuulApplication.class).web(true).run(args);
}
}
Zuul Configurations:
===============================================
info:
component: Zuul Server
server:
port: 8765
endpoints:
restart:
enabled: true
shutdown:
enabled: true
health:
sensitive: false
zuul:
ignoredServices: "*"
routes:
transactions-api-service:
path: transactions/accounts/**
serviceId: transactions-api-service
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
logging:
level:
ROOT: INFO
org.springframework.web: DEBUG
===============================================
When I try to invoke transactions-api-service with url (http://localhost:8765/transactions/accounts/123/transactions/786) I get Zuul Exception:
2016-02-13 11:29:29.050 WARN 4936 --- [nio-8765-exec-1]
o.s.c.n.z.filters.post.SendErrorFilter : Error during filtering
com.netflix.zuul.exception.ZuulException: Forwarding error
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:131)
~[spring-cloud-net flix-core-1.1.0.M3.jar:1.1.0.M3]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:76)
~[spring-cloud-netflix- core-1.1.0.M3.jar:1.1.0.M3] ......
If I invoke the transactions-api-service individually (with localhost /accounts/123/transactions/786), it works fine.
Am I missing any configurations on Zuul?
You need to change zuul execution timeout by adding this property in application.yml of zuul server:
# Increase the Hystrix timeout to 60s (globally)
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 60000
Please refer to this thread on netflix issues: https://github.com/spring-cloud/spring-cloud-netflix/issues/321
Faced same issue. In my case, zuul was using service discovery. As a solution, below configuration worked like a charm.
ribbon.ReadTimeout=60000
Reference to the property usage is here.
You have an incorrect indentation. Instead of:
zuul:
ignoredServices: "*"
routes:
transactions-api-service:
path: transactions/accounts/**
serviceId: transactions-api-service
It should be:
zuul:
ignoredServices: "*"
routes:
transactions-api-service:
path: transactions/accounts/**
serviceId: transactions-api-service
you can use this to avoid 500 error
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000000
zuul.host.connect-timeout-millis=10000
zuul.host.socket-timeout-millis=1000000
In case if your Zuul gateway uses discovery service for service lookup in that case you can disable the hystrix timeout or increase the hysterix timeout as below :
# Disable Hystrix timeout globally (for all services)
hystrix.command.default.execution.timeout.enabled: false
#To disable timeout foror particular service,
hystrix.command.<serviceName>.execution.timeout.enabled: false
# Increase the Hystrix timeout to 60s (globally)
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
# Increase the Hystrix timeout to 60s (per service)
hystrix.command.<serviceName>.execution.isolation.thread.timeoutInMilliseconds: 60000
I was having same issue with zuul server, it got resolved with below property
Let's say you have 2 clients clientA and clientB,
so for clientA, spring.application.name=clientA and server.port=1111
for clientB spring.application.name=clientB and server.port=2222 in there respective application.propeties files.
You want to connect this 2 servers to ZuulServer which is running on port 8087.
add below properties in you ZuulServer application.properties file
spring.application.name=gateway-service
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
clientA.ribbon.listOfServers=http://localhost:1111
clientB.ribbon.listOfServers=http://localhost:2222
server.port=8087
Note: I am using Eureka Client with my Zuul Server. you can skip that part. Adding this solution in case its helpful for someone.

Resources