Search code examples
javaspring-booturlnetflix-zuulapi-gateway

Spring boot zuul wrong redirection of request


I am developing an API Gateway to redirect a request to some microservice. This is part of the application.properties file:

#     _____                                       _____.__
#    /  _  \ ______ ______     ____  ____   _____/ ____\__| ____
#   /  /_\  \\____ \\____ \  _/ ___\/  _ \ /    \   __\|  |/ ___\
#  /    |    \  |_> >  |_> > \  \__(  <_> )   |  \  |  |  / /_/  >
#  \____|__  /   __/|   __/   \___  >____/|___|  /__|  |__\___  /
#          \/|__|   |__|          \/           \/        /_____/

server.port=8088
server.servlet.context-path=/PetApp

#  __________           .__    _________                _____.__
#  \____    /__ __ __ __|  |   \_   ___ \  ____   _____/ ____\__| ____
#    /     /|  |  \  |  \  |   /    \  \/ /  _ \ /    \   __\|  |/ ___\
#   /     /_|  |  /  |  /  |__ \     \___(  <_> )   |  \  |  |  / /_/  >
#  /_______ \____/|____/|____/  \______  /\____/|___|  /__|  |__\___  /
#          \/                          \/            \/        /_____/

#Routes for Auth
zuul.routes.tokenGenerator.path=/auth/login
zuul.routes.tokenGenerator.url=http://localhost:8086/PetApp_Auth/auth/generateToken
zuul.routes.tokenGenerator.stripPrefix=false

I am trying to redirect the request from the API gateway (http://localhost:8080/PetApp/auth/login) to the service running in (http://localhost:8086/PetApp_Auth/auth/generateToken) I have sent with postman the request directly to the microservice and it works perfectly.

IMPORTANT: I am not adding any authorization header because this endpoint is not securitized (And it works perfectly) but the rest of the API in my auth microservice is securitized

but when I try to send the request through the API gateway I get the following:

As can be seen, the request is being redirected to the right microservice (Auth service) but not to the right URL, because I have an exception for the rest of the endpoints and URL that is being shown.

I have also tried to put the authorization token previously generated and send in the header, but I get the same not authorized

What I am doing wrong?


Solution

  • I have already solve it by adding a filter. Zuul build the full URL like service service defined URL + PATH, so I implemented a filter that deletes the path and now the request are perfectly received in the other microservices. Anyway I am planing to change end points definitions to have the same endpoints Path than in the ones defined in the microservices, because with variable paths I thinks it is imposible to solve that. I will also check to use another solutions like nginx or varnish as @Maxim Sagaydachny suggested

    @Component
    public class PathConfigFilter extends ZuulFilter {
    
        @Autowired
        private ZuulProperties zuulProperties;
    
        @Override
        public String filterType() {
            return FilterConstants.PRE_TYPE;
        }
    
        @Override
        public int filterOrder() {
            return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
        }
    
        @Override
        public boolean shouldFilter() {
            return RequestContext.getCurrentContext().getFilterExecutionSummary().toString()
                .contains( "PreDecorationFilter[SUCCESS]" );
        }
    
        @Override
        public Object run() {
    
            RequestContext context = RequestContext.getCurrentContext();
    
            String originalRequestPath = (String) context.get(FilterConstants.REQUEST_URI_KEY);
    
            //PathVariable change
            URL routeHost = (URL) context.get( "routeHost");
            String modifiedPathVariable = processPathVariableRoutes( routeHost.getPath(), originalRequestPath );
            if(modifiedPathVariable != null){
                try {
                    URL newUrl = new URL(routeHost,modifiedPathVariable);
                    context.put("routeHost", newUrl);
                } catch (MalformedURLException e) {
                    throw new ApiGatewayException( ApiGatewayErrorCodes.PATH_VARIABLE_ERROR );
                }
            }
    
            //Delete the path because the full path is defined in properties
            context.put(FilterConstants.REQUEST_URI_KEY, "");
    
            return null;
        }
    
        private String processPathVariableRoutes(String routeHost, String requestPath){
    
            if(!routeHost.contains( "*" )){
                return null;
            }
    
            ArrayList<String> splitedRoute = new ArrayList<>(Arrays.asList(routeHost.split( "/" )));
            splitedRoute.remove( 0 );
            String context = "/" + splitedRoute.get( 0 );
            String realPath = context + requestPath;
    
            return realPath;
        }
    }
    

    Thank you very much.