Skip to content

spring-boot webflux RouterFunction handlers fails on request url ends with additional slash '/' #9133

@daggerok

Description

@daggerok

hi,
I'm not sure if this is a proper place for that issue, but...

I created from scratch spring-boot webflux project (version 2.0.0.BUILD-SNAPSHOT)
I'm expecting that at least one of my handlers should handle properly request http://localhost:3000//

@SpringBootApplication
public class ReactiveServiceApplication {

  @Bean
  public RouterFunction<ServerResponse> routes() {

    return

        route(
            GET("/"),
            request -> ok().body(Mono.just("hi"), String.class))

        .andRoute(
            GET("/{name}"),
            request -> ok().body(Mono.just("hello, " + request.pathVariable("name") + "!"), String.class))

        .andRoute(
            GET("/**"),
            request -> ok().body(Mono.just("fallback"), String.class))

        ;
  }

  public static void main(String[] args) {

    new SpringApplicationBuilder(ReactiveServiceApplication.class)
        .properties(singletonMap("server.port", "3000"))
        .run(args);
  }
}

but when I'm sending request which is ends at least with one additional '/' symbol

curl 'http://localhost:3000//'

server log is showing warning message and my terminal command is hangs (with httpie same behavior)

2017-05-08 23:30:21.770  WARN 24578 --- [ctor-http-nio-7] i.n.u.concurrent.AbstractEventExecutor   : A task raised an exception. Task: reactor.ipc.netty.channel.ContextHandler$$Lambda$159/430674510@75bc1117

java.lang.IllegalArgumentException: Expected authority at index 2: //
	at java.net.URI.create(URI.java:852) ~[na:1.8.0_102]
	at java.net.URI.resolve(URI.java:1036) ~[na:1.8.0_102]
	at org.springframework.http.server.reactive.ReactorServerHttpRequest.initUri(ReactorServerHttpRequest.java:62) ~[spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.springframework.http.server.reactive.ReactorServerHttpRequest.<init>(ReactorServerHttpRequest.java:52) ~[spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.springframework.http.server.reactive.ReactorHttpHandlerAdapter.apply(ReactorHttpHandlerAdapter.java:56) ~[spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.springframework.http.server.reactive.ReactorHttpHandlerAdapter.apply(ReactorHttpHandlerAdapter.java:37) ~[spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at reactor.ipc.netty.channel.ChannelOperations.applyHandler(ChannelOperations.java:381) ~[reactor-netty-0.6.3.RELEASE.jar:0.6.3.RELEASE]
	at reactor.ipc.netty.http.server.HttpServerOperations.onHandlerStart(HttpServerOperations.java:354) ~[reactor-netty-0.6.3.RELEASE.jar:0.6.3.RELEASE]
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.10.Final.jar:4.1.10.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:403) [netty-common-4.1.10.Final.jar:4.1.10.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462) [netty-transport-4.1.10.Final.jar:4.1.10.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) [netty-common-4.1.10.Final.jar:4.1.10.Final]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_102]
Caused by: java.net.URISyntaxException: Expected authority at index 2: //
	at java.net.URI$Parser.fail(URI.java:2848) ~[na:1.8.0_102]
	at java.net.URI$Parser.failExpecting(URI.java:2854) ~[na:1.8.0_102]
	at java.net.URI$Parser.parseHierarchical(URI.java:3102) ~[na:1.8.0_102]
	at java.net.URI$Parser.parse(URI.java:3063) ~[na:1.8.0_102]
	at java.net.URI.<init>(URI.java:588) ~[na:1.8.0_102]
	at java.net.URI.create(URI.java:850) ~[na:1.8.0_102]
	... 12 common frames omitted

I think it would be nice to have response with 404 or 400 code like, for example, github/google has:

curl 'https://api.github.com//'
{
  "message": "Not Found",
  "documentation_url": "https://developer.github.com/v3"
}

update: after reading rfc and some investigation, i can conclude next:

according to https://www.ietf.org/rfc/rfc2396.txt:

2.2. Reserved Characters

   Many URI include components consisting of or delimited by, certain
   special characters.  These characters are called "reserved", since
   their usage within the URI component is limited to their reserved
   purpose.  **If the data for a URI component would conflict with the
   reserved purpose, then the conflicting data must be escaped before
   forming the URI.**

      reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
                    "$" | ","

as far issued request has reserved character, that character should be properly escaped before URI creation, ie should be something like http://localhost:3000/%2F

then my fallback handler will properly handle such requests.

but in other handle we will have problems in URIs with path params

update 2:

I found that this issue can be easily fixed just with replacing redundants slashed with one
see org.springframework.http.server.reactive.ReactorServerHttpRequest#initUri:

	private static URI initUri(HttpServerRequest channel) {
		Assert.notNull(channel, "'channel' must not be null");
		InetSocketAddress address = channel.remoteAddress();
		// String requestUri = channel.uri(); // <-- this can be fixed for example in this way:
		String requestUri = channel.uri().replaceAll("/{2,}", "/");
		return (address != null ? getBaseUrl(address).resolve(requestUri) : URI.create(requestUri));
	}

BR

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions