Spring Cloud Gateway to modify HREF static HTML - spring

I have a Spring Gateway and a Webflux service behind it. The route is;
server:
port: 9999
spring:
application:
name: discovery-service
cloud:
gateway:
routes:
- id: route1
predicates:
- Path=/1/**
uri: http://localhost:8081
filters:
- RewritePath=/1/(?<myPath>.*), /$\{myPath}
If I request localhost:9999/1/index.html, it translates to localhost:8081/index.html and the page is correctly returned.
However, in the HTML I have links and references, for example
test1
How would I get the Gateway to return the HTML with corrected HREF? (i.e. return the HTML as);
test1
On a side note; is it common or accepted practice to host static HTML, CSS and JS in the Webflux/Netty server containing the microservices, or should they be placed somewhere else?

You just need to remove the first / in your href
test1
Or add a .
test1

Related

Applying regex in Spring Cloud Gateway Path predicate

I'm using 3.1.0 version for Spring Cloud Gateway and I need help in checking and fixing the Path predicate filter for my route configuration.
I'm trying to use regex in between a path, the route looks something like this in my config:
- id: Route1
uri: https://example.com
predicates:
- Path=/random/path/\d+/update
- Method=POST
Though this is a valid regex, I'm getting 404 error code for requests for path :
/random/path/12/update
Hence I need help to figure out the correct configs for this usecase
It requires a named path segment. See the syntax here. You can then use {mynum} in filters like SetPath
- id: Route1
uri: https://example.com
predicates:
- Path=/random/path/{mynum:\d+}/update
- Method=POST

How to prevent springboot gateway to forward to last element in the chain

I am using springboot gateway for load balancing requests between my microservice
spring:
application:
name: gateway-service
cloud:
gateway:
routes:
- id: baeldung
uri: question.com/questions/444/ask
- id: myOtherRouting
uri: answer.com/answers/333/answer
my problem is, if i send a wrong request like "question.com/questions/dasldkjasdas"
then the request is forwarded to answer.com/answers/333/answer
since this is the last chain in my config, how can i prevent this, and send notfound statuscode as response. I used
filters:
- SetStatus=NOT_FOUND
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.0.RELEASE/reference/html/#setstatus-gatewayfilter-factory
but this is not the best approuch i think.
You don't have any predicate specified for your route definitions - which means both of them match any incoming request. From Spring Cloud Gateway:
Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a Route, it is sent to the Gateway Web Handler.
and
Route: Route the basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates and a collection of filters. A route is matched if aggregate predicate is true.
Since you don't have any predicate specified - your route matches the incoming request and the last one is winning.

Spring cloud gateway default routing doesn't work

I want enable default routing in my spring cloud gateway (no zuul) by service ids registered in eureka (application names) but I always got 404 error.
In my chat service's bootstrap.yml
I have defined application name
spring:
application:
name: chat-service
and in application properties:
eureka:
instance:
preferIpAddress: true
client:
healthcheck:
enabled: true
serviceUrl:
defaultZone: http://${EUREKA_HOST:localhost}:${EUREKA_PORT:8761}/eureka/
when I go to eureka's dashboard I can see registered my chat service and gateway as well.
Eureka's configuration in gateway application is same as chat service, but I also have this:
spring:
application:
name: gateway
cloud:
gateway:
discovery:
locator:
enabled: true
and next I also tried add explicit routes which din't work as well, but if I have discovery locator enabled set to true this shouldn't be needed right?
routes:
- id: chat-service-route
uri: lb://chat-service
predicates:
- Path=**
I created test endpoint which I tried call directly on chat service and also with gateway. Direct call works fine so issue will be with routing.
#RestController
#RequestMapping
public class TestController {
#GetMapping
public String test() {
return "chat-service ready";
}
}
What I did wrong? I am little desperate. I am using spring boot 2.2.2 and Hoxton.RELEASE cloud dependencies version
Try removing explicit routes and add below property to application yml. This works for me.
spring:
cloud:
gateway:
discovery:
locator:
lower-case-service-id: true

Swagger UI try It! does not work with Kubernetes ingress

We have a Java Spring Boot project with Swagger and docker. We deploy it on kubernetes behind an ingress controller.
It works properly in localhost (using postman and swagger-ui try button).
Problem comes when we deploy it.
Rest Controller:
#ApiOperation(value = "Operation",
notes = "it does something<br />")
#RequestMapping(value="/operation", method=RequestMethod.POST)
#ApiResponses({
#ApiResponse(code = 200, message = "OK")
})
#ResponseBody public ResponseEntity<String> operation(#RequestBody BodyThing thing) {
return new ResponseEntity<>("OK", HttpStatus.OK);
} //operation
Now the ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myapp-ingress
namespace: __NAMESPACE__
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- test.host.com
secretName: key-pair
rules:
- host: test.host.com
http:
paths:
- path: /myapp
backend:
serviceName: myapp-service
servicePort: 8080
Then, with the app online deployed on K8S, usign an app like postman we must call:
https://test.host.com/myapp/operation in order to call the API. It works OK.
The problem comes if we enter in Swagger UI portal: https://test.host.com/myapp/swagger-ui.html
If we try the API call inside the swagger UI, it tries to call to https://test.host.com/operation and it fails with 404 code.
Swagger-UI makes the Endpoint URL with: host + basepath + operation_path and that is: test.host.com + / + operation
It doesnt aggregate ingress path.
How can we deal with it?
Of course is something that only happends if we deploy it with the ingress controller because, we add the /myapp path.
Thanks!
The problem is how to get swagger's base path to match to the one that is being used behind the proxy. There is more than one solution as per https://github.com/springfox/springfox/issues/1443
Since you have a specific host, I'd suggest going with the one to change the base path that swagger knows about based upon the host the request goes to. This way you can set it differently for localhost vs in the remote host. You'd need to set a RelativePathProvider for your host in your custom docket section of your Swagger #Configuration class like in https://github.com/springfox/springfox/issues/1443#issuecomment-274540681

How do I wire up spring oauth using spring eureka?

I have created a Single Page Application using the Spring Tutorial for making one with AngularJS and OAuth and such found here:
https://spring.io/guides/tutorials/spring-security-and-angular-js/#_multiple_ui_applications_and_a_gateway_single_page_application_with_spring_and_angular_js_part_vi
This is the application.yml files for the SPA application:
security:
user:
password: none
oauth2:
client:
accessTokenUri: localhost:7777/uaa/oauth/token
userAuthorizationUri: localhost:7777/uaa/oauth/authorize
clientId: acme
clientSecret: acmesecret
resource:
user-info-uri: localhost:7777/uaa/user
zuul:
routes:
resource:
path: /resource/**
url: localhost:9000/resource
user:
path: /user/**
url: localhost:7777/uaa/user
eureka:
client:
serviceUrl:
defaultZone: ${vcap.services.eureka-service.credentials.uri:127.0.0.1:8761}/eureka/
---
spring:
profiles: cloud
eureka:
instance:
hostname: ${APPLICATION_DOMAIN}
nonSecurePort: 80
I want to know how I would change the zuul routes and the user-info-uri so that I don't have to specify the urls and all this can be done by using the service-id. I looked at the tutorial for using eureka here:
https://spring.io/blog/2015/01/20/microservice-registration-and-discovery-with-spring-cloud-and-netflix-s-eureka
but I don't quite understand how I can achieve my goal without adding all the java to my code, because the basic eureka server already seems to register all my services.
Had issue with using eureka service id, userInfoUri used to throw UnknownHost Exception all the time, #LoadBallanced restTemplate did not solve my issue, solution was to set prefer-token-info to false ( if true - no load ballancing for oauth )
security.oauth2.resource.service-id={Service ID as at eureka server registered}
security.oauth2.resource.userInfoUri= http://${security.oauth2.resource.service-id}/user/me
security.oauth2.resource.loadBalanced=true
security.oauth2.resource.prefer-token-info=false
no port number needed if service ID used , but needed if ip or host used
If I do understand your question correct you can just use the config file in this pattern:
zuul:
routes:
<service_id>:
path: /path/**
For example (if your oauth-service is registered as auth):
zuul:
routes:
auth:
path: /user/**
Zuul will leverage Eureka and find the endpoints for the services. In addition to that it will provide client-side load-balancing.

Resources