我使用的是 spring boot 版本 - 2.0.6.RELEASE 和 spring cloud 版本 - Finchley.SR2
我已经创建了我的自定义网关过滤器来修改请求正文。
但是在使用 Flux 将请求正文转换为字符串时,我得到了一个空字符串。我需要一种方法来获取与我的请求正文对应的字符串。
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = (ServerHttpRequest) exchange.getRequest();
String s = resolveBodyFromRequest(request);
/* s comes out to be "" */
return chain.filter(newExchange);
}
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest){
//Get the request body
Flux<DataBuffer> body = serverHttpRequest.getBody();
StringBuilder sb = new StringBuilder();
body.subscribe(buffer -> {
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
DataBufferUtils.release(buffer);
String bodyString = new String(bytes, StandardCharsets.UTF_8);
sb.append(bodyString);
});
return …Run Code Online (Sandbox Code Playgroud) 即使我能够使用给定的主机名直接访问应用程序,通过网关的 Api 调用也会抛出java.net.UnknownHostException
Spring Boot 版本:2.4.2
Spring-cloud.version:2020.0.1
Java 版本:11
注意: Samething 适用于 spring boot 2.3.8.RELEASE和云版本:Hoxton.SR9 with Java 8
日志:
2021-02-10 14:25:05.398 ERROR 12632 --- [ctor-http-nio-4] a.w.r.e.AbstractErrorWebExceptionHandler : [efcc81fd-3] 500 Server Error for HTTP GET "/sample-order-service/sample-order"
java.net.UnknownHostException: failed to resolve 'MY-COMPUTER-NAME' after 2 queries
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
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 "/sample-order-service/sample-order" [ExceptionHandlingWebHandler]
Stack trace:
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.58.Final.jar:4.1.58.Final]
at io.netty.resolver.dns.DnsResolveContext.tryToFinishResolve(DnsResolveContext.java:966) …Run Code Online (Sandbox Code Playgroud) 我在一个项目中使用 Spring Cloud Gateway 和 Spring 5、Spring Reactor 和 Netty。对于发送到网关的每个请求,我想在将响应发送到客户端之前执行一些操作。我发现最好的方法是使用 beforeCommit 方法向响应添加操作。
我首先尝试了这种方法:
exchange.getResponse().beforeCommit(() -> {
ServerHttpResponse response = exchange.getResponse();
try {
myActionDoneHere();
response.setStatusCode(OK);
return Mono.empty();
} catch (Exception ex) {
return Mono.error(new MyException(ex));
}
});
Run Code Online (Sandbox Code Playgroud)
并尝试在异常处理程序中处理异常:
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
if (isMyException(ex)) {
exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
exchange.getResponse().getHeaders().setContentLength(MSG.length());
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(MSG.getBytes())));
}
return Mono.error(ex);
}
Run Code Online (Sandbox Code Playgroud)
当我这样做时,当我尝试修改内容长度时出现异常。如果我了解清楚情况的话。我无法再在处理程序中修改响应,因为它已经提交了。因此,我尝试了其他解决方案,并尝试修改提交之前执行的操作中的响应:
exchange.getResponse().beforeCommit(() -> {
ServerHttpResponse response = exchange.getResponse();
try {
myActionDoneHere();
response.setStatusCode(OK);
return Mono.empty();
} catch (Exception ex) {
response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
response.getHeaders().setContentLength(MSG.length());
response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(MSG.getBytes()))); …Run Code Online (Sandbox Code Playgroud) 我希望开发一个基于 spring-cloud-gateway:2.0.2-RELEASE 的网关服务器,并希望利用 sleuth 进行日志记录。自从我写入日志时,我就开始运行 Sleuth,我看到 Sleuth 详细信息(跨度 ID 等),但我希望看到自动记录的消息正文。我需要做些什么才能让 Sleuth 使用 Spring-Cloud-Gateway 记录开箱即用的请求/响应吗?
这是到达我的下游服务的请求标头
标题:
{ 'x-request-foo': '2a9c5e36-2c0f-4ad3-926c-cb20d4428462',
转发: 'proto=http;host=localhost;for="0:0:0:0:0:0:0:1:51720"',
'x-forwarded-for': '0:0:0:0:0:0:0:1',
'x-forwarded-proto': 'http',
'x-转发端口': '80',
'x-转发主机': '本地主机',
'x-b3-traceid': '5bd33eb8050c7a32dfce6adfe68b06ca',
'x-b3-spanid': 'ba202a6d6f3e2893',
'x-b3-parentspanid': 'dfce6adfe68b06ca',
'x-b3-采样': '0',
主机:'本地主机:8080'},
网关服务中的 Gradle 文件..
构建脚本{
分机{
kotlin版本 = '1.2.61'
springBootVersion = '2.0.6.RELEASE'
springCloudVersion = 'Finchley.RELEASE'
}
}
依赖管理{
进口{
mavenBom“org.springframework.cloud:spring-cloud-sleuth:2.0.2.RELEASE”
mavenBom 'org.springframework.cloud:spring-cloud-gateway:2.0.2.RELEASE'
mavenBom“org.springframework.cloud:spring-cloud-dependency:$ {springCloudVersion}”
}
}
依赖项{
实现('org.springframework.cloud:spring-cloud-starter-sleuth')
实现('org.springframework.cloud:spring-cloud-starter-gateway')
实现(“org.jetbrains.kotlin:kotlin-stdlib-jdk8”)
实现(“org.jetbrains.kotlin:kotlin-reflect”)
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
最后是网关服务的 application.yml 文件...
服务器:
小服务程序:
上下文路径:/
端口:80
春天:
应用:
名称:api.gateway.ben.com … Spring Cloud Gateway 真的很新 - 但它“似乎”很容易。我真的很苦恼的一个问题。我的要求是为路径添加前缀,检查头变量,根据该变量查找 URI,然后继续前进。
问题是 uri 始终是下面的 DEFAULT_IMPLEMENTION,即使我在 idResolvingGatewayFilter 中更改了它。我怎样才能做到这一点?可以随时添加新 ID - 这就是“动态”部分。所以在网关过滤器中,我正在读取标题并查找 uri(我正在查看的数据源可以随时更新)。但是下面的代码似乎覆盖了我在过滤器中分配的任何内容 - 如果不提供 URI,您就无法做到这一点。例如:
header-id=123
uri= http://www.somedestination.com/something/services/v1.0
header-id=999
uri= http://www.anotherdestination.com/something/services/v1.0
@Bean
public RouteLocator rosterRouteLocator( RouteLocatorBuilder builder )
{
log.info( "Establishing Gateway Routes" );
return builder.routes()
.route( r -> r.path( "/**" ).filters( f -> f.prefixPath( "/something/services/v1.0" ).filter( idResolvingGatewayFilter() ) )
.uri( resolver.buildDestinationEndpoint( IdUrlResolver.DEFAULT_IMPLEMENTATION ) ) )
.build();
}
Run Code Online (Sandbox Code Playgroud)
在 idResolvingGatewatFilter 中,我进行了更改(并且日志语句看起来是正确的......它只是没有去那里!
public Mono<Void> filter( ServerWebExchange exchange, GatewayFilterChain chain )
{
try
{
URI newUri = …Run Code Online (Sandbox Code Playgroud) 我正在尝试将正在使用的网关迁移spring-cloud-starter-netflix-zuul到 Spring Cloud Gateway,但我遇到了请求路由问题。
我浏览了以下有关为 DiscoveryClient 路由配置谓词和过滤器的文档:
这是我的 Netflix Zuul 配置中的一个片段:
zuul:
routes:
account-service: /accounts/**
Run Code Online (Sandbox Code Playgroud)
这是 Spring Cloud Gateway 配置中的一个片段,我试图在其中配置等效路由:
spring:
cloud:
gateway:
routes:
- id: account-service-route
uri: lb://account-service
predicates:
- Path=/accounts/**
Run Code Online (Sandbox Code Playgroud)
我使用 Spring Cloud Eureka 作为我的发现服务器(在一个单独的微服务中),并且我目前没有配置DiscoveryClient 路由的谓词和过滤器中概述的任何配置
如果我向 发出请求/accounts/***,我会收到 404 响应。如果我将 Spring Cloud Gateway 配置更改为以下内容并向 发出相同的请求/account-service/***,则会收到 403 Forbidden 响应:
spring:
cloud:
gateway:
routes:
- id: account-service-route
uri: lb://account-service
predicates:
- Path=/account-service/**
Run Code Online (Sandbox Code Playgroud)
我怀疑这与 Spring Cloud Gateway 在配置 DiscoveryClient 路由方面的默认行为有关,但我在日志中没有看到足够的信息来指出正确的方向。 …
我在 Spring Cloud Gateway 应用程序中设置 CORS 配置时遇到问题。我已经设置了以下配置以允许所有内容:
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "authorization"
Run Code Online (Sandbox Code Playgroud)
然而,当我调用网关的端点时,我得到:
OPTIONS http://localhost:8080/api/spot/spots 403 (Forbidden)
localhost/:1 Access to XMLHttpRequest at 'http://localhost:8080/api/spot/spots' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Run Code Online (Sandbox Code Playgroud)
当我通过 UI 调用绕过网关的服务之一时,请求运行良好。但是,我没有看到任何选项请求。
一旦我将 UI 指向网关主机,就会发生错误。
同样在网络选项卡中,请求显示为“失败”,没有其他信息。任何应用程序日志中也没有任何内容。这些是响应头:
HTTP/1.1 200 OK
transfer-encoding: chunked
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
Vary: Origin
Vary: …Run Code Online (Sandbox Code Playgroud) spring:
cloud:
gateway:
default-filters:
- name: AuthFilter
args:
enabled: true
routes:
- id: route
uri: "${SERVICE1:http://localhost:8080}"
predicates:
- Path=/route-1/**
filters:
- name: AuthFilter
args:
enabled: false
Run Code Online (Sandbox Code Playgroud)
如何覆盖如上所示的默认配置参数?目前,路由级别参数被忽略。用例是我想默认启用过滤器,但仅跳过某些特定路由。
我有一个带有 Spring Boot 的简单微服务应用程序,我尝试添加 Spring Cloud Gateway 服务,但它不起作用。所有微服务,包括 Eureka 服务器,都运行良好,但是当我尝试使用网关路由访问某些微服务时,它找不到该微服务。
ApiGateway pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.futurex.microservices</groupId>
<artifactId>APIGateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>APIGateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId> …Run Code Online (Sandbox Code Playgroud) 我使用 Spring Cloud Gateway 进行如下路由配置:
spring:
cloud:
gateway:
routes:
- id: http
uri: http://kubernetes-ingres-controller
Run Code Online (Sandbox Code Playgroud)
换句话说,我将所有路径发送到其他地方,而该地方恰好是 K8s 入口控制器。Spring 添加了一些标头并处理会话 cookie 到承载令牌的转换。
我开始添加一些处理 websocket 的端点。但是,由于我们使用 websockets 进行 GraphQL 订阅,因此我们倾向于使用单个 /graphql 路径来处理普通 GraphQL 查询和用于订阅的 websocket。
有没有办法将 Spring Cloud Gateway 配置为在单个路径上支持 http 和 ws(或 https 和 wss)?
我可以做这个:
spring:
cloud:
gateway:
routes:
- id: http
uri: http://kubernetes-ingres-controller
- id: ws
uri: ws://kubernetes-ingres-controller
predicates:
- Path=/graphql
Run Code Online (Sandbox Code Playgroud)
然而,我不清楚普通的 HTTP 是否可以在 graphql 路径上工作——实际上有很多这样的路径;我不想一一列举。
某种允许 http 在单个路由上可选升级到 wss 的设置将是理想的。