spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.52k stars 3.32k forks source link

IndexOutOfBoundsException when use Filters without Predicate #1915

Closed wolf8334 closed 4 years ago

wolf8334 commented 4 years ago

Describe the bug I am using SpringCloud Gateway 2.2.1.RELEASE to create my own gateway application with SpringBoot 2.3.3.RELEASE and SpringCloud Hoxton.SR1 JDK 1.8. Here is what I am expecting. When I visit http://localhost:8800/search/1 which provides by the gateway,it guides me to http://localhost:8801/check/1,both forward and redirect are accepted.

Sample For this purpose,I use the configuration below.

{
    "refreshGatewayRoute":true,
    "routeList":[
        {
            "id":"auth_gateway",
            "predicates":[
                {
                    "name":"Path",
                    "args":{
                        "_genkey_0":"/searchEngine"
                    }
                }
            ],
            "filters":[

            ],
            "uri":"https://bing.com",
            "order":0
        },
        {
            "id":"auth_gateway1",
            "predicates":[                

            ],
            "filters":[
                {
                    "name":"RewritePath",
                    "args":{
                        "regexp":"/search/(?<remaining>^/)",
                        "replacement":"/check/$\\{remaining}"
                    }
                }
            ],
            "uri":"https://localhost:8801/",
            "order":1
        }
    ]
}

When I visit /searchEngine,everything is OK.But when I visit /search/1,my edge told me he finds the status code 500.and my eclipse says here is an exception.

2020-08-23 09:39:11.769 ERROR 7488 --- [ctor-http-nio-5] a.w.r.e.AbstractErrorWebExceptionHandler : [a1d63aa7-3]  500 Server Error for HTTP GET "/search/1"

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(Unknown Source) ~[na:1.8.0_112]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ HTTP GET "/search/1" [ExceptionHandlingWebHandler]
Stack trace:
        at java.util.ArrayList.rangeCheck(Unknown Source) ~[na:1.8.0_112]
        at java.util.ArrayList.get(Unknown Source) ~[na:1.8.0_112]
        at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.combinePredicates(RouteDefinitionRouteLocator.java:238) ~[spring-cloud-gateway-core-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.convertToRoute(RouteDefinitionRouteLocator.java:162) ~[spring-cloud-gateway-core-2.2.1.RELEASE.jar:2.2.1.RELEASE]
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:704) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmit(FluxFlatMap.java:561) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at reactor.core.publisher.FluxFlatMap$FlatMapInner.onNext(FluxFlatMap.java:999) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at reactor.core.publisher.FluxSubscribeOnValue$ScheduledScalar.run(FluxSubscribeOnValue.java:178) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) ~[reactor-core-3.3.9.RELEASE.jar:3.3.9.RELEASE]
        at java.util.concurrent.FutureTask.run(Unknown Source) ~[na:1.8.0_112]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[na:1.8.0_112]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[na:1.8.0_112]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:1.8.0_112]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:1.8.0_112]
        at java.lang.Thread.run(Unknown Source) ~[na:1.8.0_112]

I check the source code and found I need provide at least one Predicate,or the code below will throw exception:

AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,predicates.get(0));

But I do not need the Predicate.So what should I do?

sjmittal commented 4 years ago

I suggest add a predicate matching all the paths, because looks like you want the filter to execute in all the cases. I have also faced this problem, as I am building the routes in dsl, I use the following:

.route("rewrite_request_obj", r -> r
                .path("**")
                .filters(f -> f
                    .filter(...)
                )
                .uri(uri)
            )
            .build();

notice path("**")

spencergibb commented 4 years ago

IIRC there is an always true predicate or something similar

wolf8334 commented 4 years ago

sorry for interrupt again.I do not quiet understand the word 'IIRC' mean. where can I find the 'always true predicate' ?