Skip to content

Gateway Routes URI of localhost:port without http:// returns empty body with 200 status code #2919

@lomuto

Description

@lomuto

Version

  • java: 11
  • Spring Boot : 2.6.9
  • Spring Cloud : 2021.0.3

Describe the bug

Exact same issue #1764 report from Aug.2020 by @Bryksin

Since @spencergibb guided to update Spring Cloud version to hoxton.sr5 will solve the problem, BUT I am using the version 2021.0.3 which is further updated then hoxton.sr5 and still has the same issue.

Cloud Gateway is not forwarding requests, but even worse it just returns an empty body of status code 200 even for invalid or non-existing endpoints.

The reason for it is because I set the uri configuration without the URI scheme in it

# application.yml

spring:
  cloud:
    gateway:
      routes:
        - id: test
          uri: localhost:8080
          predicates:
            - Path=/api/v?/test

if I correct my configuration to

# fixed ver of application.yml

spring:
  cloud:
    gateway:
      routes:
        - id: test
          uri: http://localhost:8080  # prepended http://
          predicates:
            - Path=/api/v?/test

Then it works fine.

Sample

Screenshot 2023-04-08 at 5 55 12 PM

FYI.. took 6m40s to get response is because I set the breakpoint and debug, nothing related to performance issue

Trouble Shoot

As @cstraw01 said from #1764
while on bootstrap, URI in RouteDefinition gets initialized with scheme of localhost

Screenshot 2023-04-08 at 5 12 15 PM

After that, RouteToRequestUrlFilter merge an url from URL instance which has invalid scheme and put it as an attribute of exchange GATEWAY_REQUEST_URL_ATTR

Screenshot 2023-04-08 at 5 29 57 PM

Followed by filter chain, it will move on to NettyRoutingFilter from where request should be forwarded, but since GATEWAY_REQUEST_URL_ATTR in exchange attribute is in invalid format so it won't move on.

Screenshot 2023-04-08 at 7 16 48 PM

Screenshot 2023-04-08 at 7 19 05 PM

For now on, I added custom filter in my project to throws an error if http:// is not prepended on uri configuration of route to fix current problem, but is its just an temporarily solution.

@Component
public class RouteDefinitionFilter implements GlobalFilter, Ordered {

    private static final int ORDER = NettyRoutingFilter.ORDER - 1;
    private static final String LOCALHOST = "localhost";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);

        if (requestUrl.getScheme().equals(LOCALHOST)) {
            throw new IllegalArgumentException(
                    String.format("Unexpected uri scheme for path: \"%s\"", requestUrl.getPath())
            );
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return ORDER;
    }
}

Suggestion

I have checked that If uri configuration starts with localhost, host is always null

Screenshot 2023-04-10 at 12 10 56 PM

In RouteToRequestUrlFilter, if scheme of uri is lb it checks whether host is null or not

if ("lb".equalsIgnoreCase(routeUri.getScheme()) && routeUri.getHost() == null) {
// Load balanced URIs should always have a host. If the host is null it is
// most
// likely because the host name was invalid (for example included an
// underscore)
throw new IllegalStateException("Invalid host: " + routeUri.toString());
}

since valid URI must contains non-null host part so I would like to change code like...

/*
if ("lb".equalsIgnoreCase(routeUri.getScheme()) && routeUri.getHost() == null) {
	// Load balanced URIs should always have a host. If the host is null it is
	// most
	// likely because the host name was invalid (for example included an
	// underscore)
	throw new IllegalStateException("Invalid host: " + routeUri.toString());
}
*/
        
// not just when scheme is lb, always checks host is non-null
if (routeUri.getHost() == null) {
	throw new IllegalStateException("Invalid host: " + routeUri.toString());
}

If so, it could also filter my situation as when uri configuration is given as localhost:8080

thank you :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions