Я использую пружин-cloud-api-gateway и я хочу создать фильтр по умолчанию для добавления Header к ответу x-reuest-id или x-trace-id , чтобы удержать сгенерированный trace-id from spress-cloud--gate-id> /> Что пробует < /h3>
- pom.xml
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.5.3
com.youssef.gamal.microservices
spring-cloud-api-gateway
0.0.1-SNAPSHOT
spring-cloud-api-gateway
Demo project for Spring Boot
[*]
17
2025.0.0
org.springframework.boot
spring-boot-starter-logging
org.springframework.boot
spring-boot-starter-data-redis-reactive
org.springframework.cloud
spring-cloud-starter-circuitbreaker-reactor-resilience4j
org.springframework.cloud
spring-cloud-starter-gateway-server-webflux
org.springframework.boot
spring-boot-starter-actuator
io.micrometer
micrometer-tracing-bridge-brave
io.zipkin.reporter2
zipkin-reporter-brave
org.springframework.boot
spring-boot-docker-compose
runtime
true
org.springframework.boot
spring-boot-starter-test
test
io.projectreactor
reactor-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
< /code>
- application.yml
server:
port: 8080
# Spring Cloud API Gateway Configuration
spring:
application:
name: spring-cloud-api-gateway
cloud:
gateway:
# Global filters
default-filters:
- RequestIdFilter # Custom filter to add a unique request ID to each request
routes:
# CREATE: Allow only POST on /posts
- id: posts-service-create
uri: https://jsonplaceholder.typicode.com
predicates:
- Path=/posts
- Method=POST
# READ ALL: Allow only GET on /posts
- id: posts-service-list
uri: https://jsonplaceholder.typicode.com
predicates:
- Path=/posts
- Method=GET
# READ ONE: Allow only GET on /posts/{id}
- id: posts-service-get-by-id
uri: https://jsonplaceholder.typicode.com
predicates:
- Path=/posts/{segment}
- Method=GET
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@ipKeyResolver}"
redis-rate-limiter.replenishRate: 2
redis-rate-limiter.burstCapacity: 5
redis-rate-limiter.requestedTokens: 2
# Allow GET and PUT on /posts/{id} (get and update)
# UPDATE: Allow only PUT on /posts/{id}
- id: posts-service-update-by-id
uri: https://jsonplaceholder.typicode.com
predicates:
- Path=/posts/{segment}
- Method=PUT
# DELETE: Allow only DELETE on /posts/{id}
- id: posts-service-delete-by-id
uri: https://jsonplaceholder.typicode.com
predicates:
- Path=/posts/{segment}
- Method=DELETE
# Allow only GET on /posts/{id}/comments
- id: posts-service-get-comments-by-post
uri: https://jsonplaceholder.typicode.com
predicates:
- Path=/posts/{segment}/comments
- Method=GET
# Allow only GET on /comments with postId query param
- id: comments-service
uri: https://jsonplaceholder.typicode.com
predicates:
- Path=/comments
- Method=GET
- Query=postId, [0-9]+
# Redis Rate Limiter Configuration
data:
redis:
host: localhost
port: 6379
# Zipkin Tracing Configuration
management:
tracing:
sampling:
probability: 1.0 # 100% sampling, adjust as needed
enabled: true
zipkin:
tracing:
endpoint: http://localhost:9411/api/v2/spans # Default Zipkin endpoint
# Logging Configuration
logging:
level:
org.springframework.cloud.gateway: DEBUG
org.springframework.http.server.reactive: DEBUG
org.springframework.web.reactive: DEBUG
org.springframework.boot.autoconfigure.web: DEBUG
reactor.netty: DEBUG
redisratelimiter: DEBUG
< /code>
- RequestIdFilter.java
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import io.micrometer.tracing.Tracer;
import reactor.core.publisher.Mono;
@Component
public class RequestIdFilter implements GlobalFilter, Ordered {
public static final String REQUEST_ID_HEADER = "X-Request-Id";
private final Tracer tracer;
public RequestIdFilter(Tracer tracer) {
this.tracer = tracer;
}
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// Generate a unique request ID using the tracer
String requestId = tracer.currentSpan().context().traceId();
// Add the request ID to the response headers
exchange.getResponse().getHeaders().add(REQUEST_ID_HEADER, requestId);
return chain.filter(exchange);
}
@Override
public int getOrder() {
// Set the order of this filter to be executed after the default filters
return Ordered.LOWEST_PRECEDENCE;
}
}
Output From Codes Above
when i tried to call http --verbose GET :8080/posts/1 i got the followings:
- Response
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8080
User-Agent: HTTPie/3.2.2
HTTP/1.1 500 Internal Server Error
Content-Length: 133
Content-Type: application/json
X-RateLimit-Burst-Capacity: 5
X-RateLimit-Remaining: 3
X-RateLimit-Replenish-Rate: 2
X-RateLimit-Requested-Tokens: 2
{
"error": "Internal Server Error",
"path": "/posts/1",
"requestId": "dafe9904-1",
"status": 500,
"timestamp": "2025-07-04T21:40:18.198+00:00"
}
< /code>
- Console-Logs Exception
java.lang.NullPointerException: Cannot invoke "io.micrometer.tracing.Span.context()" because the return value of "io.micrometer.tracing.Tracer.currentSpan()" is null
at com.youssef.gamal.microservices.spring_cloud_api_gateway.filters.globals.RequestIdFilter.filter(RequestIdFilter.java:28) ~[classes/:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
*__checkpoint ⇢ HTTP GET "/posts/1" [ExceptionHandlingWebHandler]
Original Stack Trace:
at com.youssef.gamal.microservices.spring_cloud_api_gateway.filters.globals.RequestIdFilter.filter(RequestIdFilter.java:28) ~[classes/:na]
at org.springframework.cloud.gateway.handler.FilteringWebHandler$GatewayFilterAdapter.filter(FilteringWebHandler.java:178) ~[spring-cloud-gateway-server-4.3.0.jar:4.3.0]
at org.springframework.cloud.gateway.filter.OrderedGatewayFilter.filter(OrderedGatewayFilter.java:44) ~[spring-cloud-gateway-server-4.3.0.jar:4.3.0]
at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.lambda$filter$0(FilteringWebHandler.java:158) ~[spring-cloud-gateway-server-4.3.0.jar:4.3.0]
Подробнее здесь: https://stackoverflow.com/questions/796 ... api-gatewa