标签: spring-cloud-gateway

从 ServerHttpRequest / Flux<DataBuffer> 获取请求正文字符串

我使用的是 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)

java spring-cloud spring-cloud-gateway

8
推荐指数
3
解决办法
5744
查看次数

Spring Boot API 网关无法解析名称

即使我能够使用给定的主机名直接访问应用程序,通过网关的 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-boot spring-cloud spring-cloud-gateway

8
推荐指数
3
解决办法
1971
查看次数

如何在提交之前修改 Spring Cloud Gateway 中的响应正文

我在一个项目中使用 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 project-reactor spring-cloud-gateway

7
推荐指数
1
解决办法
1万
查看次数

如何配置 spring-cloud-gateway 使用 sleuth 记录请求/响应正文

我希望开发一个基于 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-sleuth spring-cloud-gateway

7
推荐指数
1
解决办法
8768
查看次数

Spring Cloud Gateway 动态路由

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-gateway

7
推荐指数
1
解决办法
5778
查看次数

Spring Cloud Gateway 和 DiscoveryClient 路由

我正在尝试将正在使用的网关迁移spring-cloud-starter-netflix-zuul到 Spring Cloud Gateway,但我遇到了请求路由问题。

我浏览了以下有关为 DiscoveryClient 路由配置谓词和过滤器的文档:

为 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

7
推荐指数
1
解决办法
3515
查看次数

Spring Cloud Gateway Cors 问题

我在 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-security spring-cloud spring-cloud-gateway

7
推荐指数
1
解决办法
5788
查看次数

如何在Spring Cloud Gateway中的路由级别覆盖默认过滤器参数?

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

7
推荐指数
0
解决办法
734
查看次数

Spring Cloud Gateway 找不到微服务(未找到 404 错误)

我有一个带有 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)

java spring gateway spring-boot spring-cloud-gateway

7
推荐指数
1
解决办法
1万
查看次数

Spring Cloud Gateway:与 HTTP(S) 位于同一 URL 上的 Websockets

我使用 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 的设置将是理想的。

java spring spring-boot spring-cloud spring-cloud-gateway

7
推荐指数
1
解决办法
314
查看次数