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?
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.