Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
lomuto opened this issue Apr 8, 2023 · 2 comments
Labels
Milestone

Comments

@lomuto
Copy link

lomuto commented Apr 8, 2023

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 :)

@spencergibb
Copy link
Member

I'm unable to reproduce this with Spring Cloud 2023.0.0. The app fails to start with an error

java.lang.IllegalArgumentException: The parameter [httpbin.org] format is incorrect, scheme can not be empty

@spencergibb
Copy link
Member

spencergibb commented Mar 12, 2024

I see, localhost is the key. Because the scheme isn't http{s}, no request is ever sent.

@spencergibb spencergibb changed the title Gateway Routes URI without http:// prefix returns empty body with 200 status code Gateway Routes URI of localhost:port without http:// returns empty body with 200 status code Mar 12, 2024
@spencergibb spencergibb added this to the 4.1.2 milestone Mar 12, 2024
spencergibb added a commit that referenced this issue Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
No open projects
Status: Done
Development

No branches or pull requests

2 participants