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

Spring Cloud Gateway Server MVC rateLimit filter(Bucket4jFilter) will got UnsupportedOperationException when response headers is ReadOnlyHttpHeaders #3345

Open
zzphyh opened this issue Apr 10, 2024 · 2 comments

Comments

@zzphyh
Copy link

zzphyh commented Apr 10, 2024

Describe the bug
I use rateLimit(Bucket4jFilter) filter with a handler, the handler will return response as below.

return ServerResponse.ok().body(result);

For that response, the serverResponse.headers() will return a ReadOnlyHttpHeaders. But the Bucket4jFilter will try to add a header into the serverResponse.headers(), that will cause java.lang.UnsupportedOperationException.

			if (allowed) {
				ServerResponse serverResponse = next.handle(request);
				serverResponse.headers().add(config.getHeaderName(), String.valueOf(remainingTokens));
				return serverResponse;
			}

I use Spring Cloud Gateway Server MVC version 4.1.2

org.springframework.cloud
spring-cloud-starter-gateway-mvc
4.1.2

@spencergibb
Copy link
Member

I don't understand your full configuration. Can you provide it. Where does return ServerResponse.ok().body(result); live?

@zzphyh
Copy link
Author

zzphyh commented Apr 17, 2024

I don't understand your full configuration. Can you provide it. Where does return ServerResponse.ok().body(result); live?

I have added a custom handler, the code in spring.factories is:

org.springframework.cloud.gateway.server.mvc.handler.HandlerSupplier=\
test.HandlerFunctions.MyHandlerSupplier

Custom handler code:

public abstract class HandlerFunctions {

    public static HandlerFunction<ServerResponse> dubbo() {
        return new DubboHandler();
    }

    public static class MyHandlerSupplier implements HandlerSupplier {

        @Override
        public Collection<Method> get() {
            return Arrays.asList(HandlerFunctions.class.getMethods());
        }
    }
}
public class DubboHandler implements HandlerFunction<ServerResponse> {
    @Override
    public ServerResponse handle(@Nonnull ServerRequest request) {
        try {
            final JSONObject result = callDubboRPC(request);
            return ServerResponse.ok().body(result);
        } catch (Exception e) {
            log.error("forward to rpc failed.", e);
            return ServerResponse.status(BAD_GATEWAY).body(new Result<>(HTTP_FORWARD_DUBBO_ERROR));
        }
    }
}

The routing configuration is similar to the following (excluding the rate-limiting part):

spring:
  cloud:
    gateway:
      mvc:
        routes:
          - id: im_route1
            uri: dubbo://dubboserviceaddress
            predicates:
              - Path=/calltodubbo
              - Method=POST

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants