@Override
    public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction exchangeFunction) {
        HttpHeaders readOnlyHttpHeaders = request.headers();
        RequestTag requestTag = ThreadLocalUtils.getRequestTag();
        if (requestTag == null) {
            ThreadLocalUtils.setRequestData(new RequestData(readOnlyHttpHeaders, request.url().getPath(),
                    request.method().name()));
            return exchangeFunction.exchange(request);
        }
        Builder newRequestBuilder = ClientRequest.from(request);
        requestTag.getTag().forEach((key, value) -> newRequestBuilder.header(key, value.toArray(new String[0])));
        ClientRequest newRequest = newRequestBuilder.build();
        ThreadLocalUtils.setRequestData(new RequestData(newRequest.headers(), newRequest.url().getPath(),
                newRequest.method().name()));
        return exchangeFunction.exchange(newRequest);
    }
@Test
    public void testFilterWithoutRequestTag() {
        // when requestTag is null
        ClientResponse response = function.filter(request, exchangeFunction).block();
        Assert.assertNotNull(response);
        HttpHeaders httpHeaders = response.headers().asHttpHeaders();
        Assert.assertEquals(1, httpHeaders.size());
        List<String> foos = httpHeaders.get("foo");
        Assert.assertNotNull(foos);
        Assert.assertEquals("foo1", foos.get(0));
        RequestData requestData = ThreadLocalUtils.getRequestData();
        Map<String, List<String>> tag = requestData.getTag();
        Assert.assertEquals("foo1", tag.get("foo").get(0));
        Assert.assertEquals("/foo", requestData.getPath());
        Assert.assertEquals("GET", requestData.getHttpMethod());
    }