You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by xi...@apache.org on 2022/12/13 03:20:05 UTC

[shenyu] branch master updated: [type:refactor] decoupled sign plugin (#4261)

This is an automated email from the ASF dual-hosted git repository.

xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new e60d93ef4 [type:refactor] decoupled sign plugin (#4261)
e60d93ef4 is described below

commit e60d93ef426bc168435920e5e1f622ba6e74ceb9
Author: 愿凌飞 <ti...@foxmail.com>
AuthorDate: Tue Dec 13 11:19:56 2022 +0800

    [type:refactor] decoupled sign plugin (#4261)
    
    * [refactor] decoupled sign plugin
    
    * deleted unused class
    
    * fix
    
    * fix
---
 .../plugin/base/support/RequestDecorator.java}     |  9 ++--
 .../shenyu/plugin/base/utils/ResponseUtils.java    |  4 +-
 .../plugin/base/utils/ServerWebExchangeUtils.java  | 63 ++++++++++++++++++++++
 .../org/apache/shenyu/plugin/sign/SignPlugin.java  | 48 ++++++-----------
 .../plugin/sign/exception/SignPluginException.java | 35 ++++++++++++
 5 files changed, 121 insertions(+), 38 deletions(-)

diff --git a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/decorator/SignRequestDecorator.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/support/RequestDecorator.java
similarity index 83%
rename from shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/decorator/SignRequestDecorator.java
rename to shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/support/RequestDecorator.java
index ef61569af..e6f138d69 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/decorator/SignRequestDecorator.java
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/support/RequestDecorator.java
@@ -15,9 +15,8 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.sign.decorator;
+package org.apache.shenyu.plugin.base.support;
 
-import org.apache.shenyu.plugin.base.support.CachedBodyOutputMessage;
 import org.apache.shenyu.plugin.base.utils.ResponseUtils;
 import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.http.HttpHeaders;
@@ -29,14 +28,14 @@ import reactor.util.annotation.NonNull;
 /**
  * Build and modify the request class.
  */
-public class SignRequestDecorator extends ServerHttpRequestDecorator {
+public class RequestDecorator extends ServerHttpRequestDecorator {
 
     private final CachedBodyOutputMessage cachedBodyOutputMessage;
 
     private final ServerWebExchange exchange;
 
-    public SignRequestDecorator(final ServerWebExchange exchange,
-                                   final CachedBodyOutputMessage cachedBodyOutputMessage) {
+    public RequestDecorator(final ServerWebExchange exchange,
+                                final CachedBodyOutputMessage cachedBodyOutputMessage) {
         super(exchange.getRequest());
         this.cachedBodyOutputMessage = cachedBodyOutputMessage;
         this.exchange = exchange;
diff --git a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/ResponseUtils.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/ResponseUtils.java
index dd7df43c8..c4b04da41 100644
--- a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/ResponseUtils.java
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/ResponseUtils.java
@@ -22,6 +22,7 @@ import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.base.support.BodyInserterContext;
 import org.apache.shenyu.plugin.base.support.CachedBodyOutputMessage;
 import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
 import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.core.io.buffer.DataBufferUtils;
 import org.springframework.http.HttpHeaders;
@@ -96,10 +97,11 @@ public final class ResponseUtils {
      * release source.
      *
      * @param outputMessage CachedBodyOutputMessage
+     * @param <T> the reified {@link Subscriber} type
      * @param throwable     Throwable
      * @return Mono.
      */
-    public static Mono<Void> release(final CachedBodyOutputMessage outputMessage, final Throwable throwable) {
+    public static <T> Mono<T> release(final CachedBodyOutputMessage outputMessage, final Throwable throwable) {
         if (Boolean.TRUE.equals(outputMessage.getCache())) {
             return outputMessage.getBody().map(DataBufferUtils::release).then(Mono.error(throwable));
         }
diff --git a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/ServerWebExchangeUtils.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/ServerWebExchangeUtils.java
new file mode 100644
index 000000000..e90e0e0f4
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/ServerWebExchangeUtils.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.base.utils;
+
+import org.apache.shenyu.plugin.base.support.BodyInserterContext;
+import org.apache.shenyu.plugin.base.support.CachedBodyOutputMessage;
+import org.apache.shenyu.plugin.base.support.RequestDecorator;
+import org.springframework.http.ReactiveHttpOutputMessage;
+import org.springframework.http.codec.HttpMessageReader;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import org.springframework.web.reactive.function.BodyInserter;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+import java.util.function.Function;
+
+public class ServerWebExchangeUtils {
+
+    /**
+     * Rewrites Request Body.
+     * @param exchange serverWebExchange
+     * @param readers reader to read request-body
+     * @param convert convert body to new body
+     * @return Mono.
+     */
+    public static Mono<ServerWebExchange> rewriteRequestBody(final ServerWebExchange exchange,
+                                                             final List<HttpMessageReader<?>> readers,
+                                                             final Function<String, Mono<String>> convert) {
+
+        ServerRequest serverRequest = ServerRequest.create(exchange, readers);
+        CachedBodyOutputMessage outputMessage = ResponseUtils.newCachedBodyOutputMessage(exchange);
+
+        return serverRequest.bodyToMono(String.class)
+                .switchIfEmpty(Mono.defer(() -> Mono.just("")))
+                .flatMap(convert)
+                .flatMap(body -> {
+                    BodyInserter<String, ReactiveHttpOutputMessage> bodyInserter = BodyInserters.fromValue(body);
+                    return bodyInserter.insert(outputMessage, new BodyInserterContext());
+                }).then(Mono.defer(() -> {
+                    ServerHttpRequestDecorator decorator = new RequestDecorator(exchange, outputMessage);
+                    return Mono.just(exchange.mutate().request(decorator).build());
+                })).onErrorResume(throwable -> ResponseUtils.release(outputMessage, throwable));
+
+    }
+}
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java
index 6d0bd9eea..5c14b14d2 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java
+++ b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java
@@ -27,29 +27,21 @@ import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
 import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
 import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
 import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
-import org.apache.shenyu.plugin.base.support.BodyInserterContext;
-import org.apache.shenyu.plugin.base.support.CachedBodyOutputMessage;
 import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
-import org.apache.shenyu.plugin.base.utils.ResponseUtils;
+import org.apache.shenyu.plugin.base.utils.ServerWebExchangeUtils;
 import org.apache.shenyu.plugin.sign.api.SignService;
-import org.apache.shenyu.plugin.sign.decorator.SignRequestDecorator;
+import org.apache.shenyu.plugin.sign.api.VerifyResult;
+import org.apache.shenyu.plugin.sign.exception.SignPluginException;
 import org.apache.shenyu.plugin.sign.handler.SignPluginDataHandler;
 import org.apache.shenyu.plugin.sign.handler.SignRuleHandler;
-import org.apache.shenyu.plugin.sign.api.VerifyResult;
-import org.springframework.http.ReactiveHttpOutputMessage;
 import org.springframework.http.codec.HttpMessageReader;
-import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
 import org.springframework.util.MultiValueMap;
 import org.springframework.util.ObjectUtils;
-import org.springframework.web.reactive.function.BodyInserter;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.server.ServerRequest;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
 import java.util.List;
 import java.util.Map;
-import java.util.function.Function;
 
 /**
  * Sign Plugin.
@@ -92,16 +84,19 @@ public class SignPlugin extends AbstractShenyuPlugin {
             return chain.execute(exchange);
         }
 
-        ServerRequest serverRequest = ServerRequest.create(exchange, messageReaders);
-        return serverRequest.bodyToMono(String.class)
-                .switchIfEmpty(Mono.defer(() -> Mono.just("")))
-                .flatMap(originalBody -> {
-                    VerifyResult result = signBody(originalBody, exchange);
-                    if (result.isSuccess()) {
-                        return executeChain(originalBody, exchange, chain);
-                    }
-                    return handleSignFailed(exchange, result.getReason());
-                });
+        return ServerWebExchangeUtils.rewriteRequestBody(exchange, messageReaders, body -> {
+            VerifyResult result = signBody(body, exchange);
+            if (result.isSuccess()) {
+                return Mono.just(body);
+            }
+            throw new SignPluginException(result.getReason());
+        }).flatMap(chain::execute)
+          .onErrorResume(error -> {
+              if (error instanceof SignPluginException) {
+                  return handleSignFailed(exchange, error.getMessage());
+              }
+              return Mono.error(error);
+          });
     }
 
     private VerifyResult signBody(final String originalBody, final ServerWebExchange exchange) {
@@ -113,17 +108,6 @@ public class SignPlugin extends AbstractShenyuPlugin {
         return signService.signVerify(exchange, requestBody, queryParamsSingleValueMap);
     }
 
-    private Mono<Void> executeChain(final String requestBody, final ServerWebExchange exchange, final ShenyuPluginChain chain) {
-        BodyInserter<String, ReactiveHttpOutputMessage> bodyInserter = BodyInserters.fromValue(requestBody);
-        CachedBodyOutputMessage outputMessage = ResponseUtils.newCachedBodyOutputMessage(exchange);
-        return bodyInserter.insert(outputMessage, new BodyInserterContext())
-                .then(Mono.defer(() -> {
-                        ServerHttpRequestDecorator decorator = new SignRequestDecorator(exchange, outputMessage);
-                        return chain.execute(exchange.mutate().request(decorator).build());
-                    }
-                )).onErrorResume((Function<Throwable, Mono<Void>>) throwable -> ResponseUtils.release(outputMessage, throwable));
-    }
-
     private Mono<Void> handleSignFailed(final ServerWebExchange exchange, final String reason) {
         Object error = ShenyuResultWrap.error(exchange, ShenyuResultEnum.SIGN_IS_NOT_PASS.getCode(), reason, null);
         return WebFluxResultUtils.result(exchange, error);
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/exception/SignPluginException.java b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/exception/SignPluginException.java
new file mode 100644
index 000000000..03f486fb7
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/exception/SignPluginException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.sign.exception;
+
+import org.apache.shenyu.common.exception.ShenyuException;
+
+public class SignPluginException extends ShenyuException {
+
+    public SignPluginException(final Throwable e) {
+        super(e);
+    }
+
+    public SignPluginException(final String message) {
+        super(message);
+    }
+
+    public SignPluginException(final String message, final Throwable throwable) {
+        super(message, throwable);
+    }
+}