You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hugegraph.apache.org by va...@apache.org on 2023/03/01 09:20:00 UTC

[incubator-hugegraph] 01/01: fix: 401

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

vaughn pushed a commit to branch zy_dev
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph.git

commit 5d065c8e2f42117c3f8cf770ebe76d3d3c0e4786
Author: vaughn <va...@apache.org>
AuthorDate: Wed Mar 1 15:37:05 2023 +0800

    fix: 401
---
 .../hugegraph/api/filter/RedirectFilter.java       | 72 +++++++++++++++++++++-
 .../org/apache/hugegraph/api/job/GremlinAPI.java   |  1 +
 .../org/apache/hugegraph/api/job/RebuildAPI.java   |  3 +
 .../org/apache/hugegraph/api/raft/RaftAPI.java     |  3 +
 .../election/StandardStateMachineCallback.java     |  9 ++-
 5 files changed, 81 insertions(+), 7 deletions(-)

diff --git a/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/RedirectFilter.java b/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/RedirectFilter.java
index e6c7e2d98..92f5e0864 100644
--- a/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/RedirectFilter.java
+++ b/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/RedirectFilter.java
@@ -22,20 +22,43 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import jakarta.ws.rs.NameBinding;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation;
 import jakarta.ws.rs.container.ContainerRequestContext;
 import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.MultivaluedMap;
 import jakarta.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.http.client.utils.URIBuilder;
 import org.apache.hugegraph.election.GlobalMasterInfo;
 import org.apache.hugegraph.util.Log;
+import org.glassfish.jersey.message.internal.HeaderUtils;
 import org.slf4j.Logger;
 
 public class RedirectFilter implements ContainerRequestFilter {
 
     private static final Logger LOG = Log.logger(RedirectFilter.class);
+    public static final String X_HG_REDIRECT = "x-hg-redirect";
+
+    private static volatile Client client = null;
+
+    private static final Set<String> MUST_BE_NULL = new HashSet<>();
+
+    static {
+        MUST_BE_NULL.add("DELETE");
+        MUST_BE_NULL.add("GET");
+        MUST_BE_NULL.add("HEAD");
+        MUST_BE_NULL.add("TRACE");
+    }
 
     @Override
     public void filter(ContainerRequestContext requestContext) throws IOException {
@@ -44,6 +67,11 @@ public class RedirectFilter implements ContainerRequestFilter {
             return;
         }
 
+        String redirectTag = requestContext.getHeaderString(X_HG_REDIRECT);
+        if (StringUtils.isNotEmpty(redirectTag)) {
+            return;
+        }
+
         String url = "";
         synchronized (instance) {
             if (instance.isMaster() || StringUtils.isEmpty(instance.url())) {
@@ -54,7 +82,7 @@ public class RedirectFilter implements ContainerRequestFilter {
 
         URI redirectUri = null;
         try {
-            URIBuilder redirectURIBuilder = new URIBuilder(requestContext.getUriInfo().getAbsolutePath());
+            URIBuilder redirectURIBuilder = new URIBuilder(requestContext.getUriInfo().getRequestUri());
             String[] host = url.split(":");
             redirectURIBuilder.setHost(host[0]);
             if (host.length == 2 && StringUtils.isNotEmpty(host[1].trim())) {
@@ -66,7 +94,47 @@ public class RedirectFilter implements ContainerRequestFilter {
             LOG.error("Redirect request exception occurred", e);
             return;
         }
-        requestContext.abortWith(Response.temporaryRedirect(redirectUri).build());
+        this.initClientIfNeeded();
+        Response response = this.forwardRequest(requestContext, redirectUri);
+        requestContext.abortWith(response);
+    }
+
+    private Response forwardRequest(ContainerRequestContext requestContext, URI redirectUri) {
+        MultivaluedMap<String, String> headers = requestContext.getHeaders();
+        MultivaluedMap<String, Object> newHeaders = HeaderUtils.createOutbound();
+        if (headers != null) {
+            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
+                for (String value : entry.getValue()) {
+                    newHeaders.add(entry.getKey(), value);
+                }
+            }
+        }
+        newHeaders.add(X_HG_REDIRECT, new Date().getTime());
+        Invocation.Builder builder = client.target(redirectUri)
+                                           .request()
+                                           .headers(newHeaders);
+        Response response = null;
+        if (MUST_BE_NULL.contains(requestContext.getMethod())) {
+            response = builder.method(requestContext.getMethod());
+        } else {
+            response = builder.method(requestContext.getMethod(),
+                                      Entity.json(requestContext.getEntityStream()));
+        }
+        return response;
+    }
+
+    private void initClientIfNeeded() {
+        if (client != null) {
+            return;
+        }
+
+        synchronized (RedirectFilter.class) {
+            if (client != null) {
+                return;
+            }
+
+            client = ClientBuilder.newClient();
+        }
     }
 
     @NameBinding
diff --git a/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java b/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java
index 62e791367..aacfc2bb9 100644
--- a/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java
+++ b/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/GremlinAPI.java
@@ -74,6 +74,7 @@ public class GremlinAPI extends API {
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON_WITH_CHARSET)
     @RolesAllowed({"admin", "$owner=$graph $action=gremlin_execute"})
+    @RedirectFilter.RedirectMasterRole
     public Map<String, Id> post(@Context GraphManager manager,
                                 @PathParam("graph") String graph,
                                 GremlinRequest request) {
diff --git a/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java b/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java
index 0fe87ee0f..7d00d63f0 100644
--- a/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java
+++ b/hugegraph-api/src/main/java/org/apache/hugegraph/api/job/RebuildAPI.java
@@ -53,6 +53,7 @@ public class RebuildAPI extends API {
     @Status(Status.ACCEPTED)
     @Produces(APPLICATION_JSON_WITH_CHARSET)
     @RolesAllowed({"admin", "$owner=$graph $action=index_write"})
+    @RedirectFilter.RedirectMasterRole
     public Map<String, Id> vertexLabelRebuild(@Context GraphManager manager,
                                               @PathParam("graph") String graph,
                                               @PathParam("name") String name) {
@@ -69,6 +70,7 @@ public class RebuildAPI extends API {
     @Status(Status.ACCEPTED)
     @Produces(APPLICATION_JSON_WITH_CHARSET)
     @RolesAllowed({"admin", "$owner=$graph $action=index_write"})
+    @RedirectFilter.RedirectMasterRole
     public Map<String, Id> edgeLabelRebuild(@Context GraphManager manager,
                                             @PathParam("graph") String graph,
                                             @PathParam("name") String name) {
@@ -85,6 +87,7 @@ public class RebuildAPI extends API {
     @Status(Status.ACCEPTED)
     @Produces(APPLICATION_JSON_WITH_CHARSET)
     @RolesAllowed({"admin", "$owner=$graph $action=index_write"})
+    @RedirectFilter.RedirectMasterRole
     public Map<String, Id> indexLabelRebuild(@Context GraphManager manager,
                                              @PathParam("graph") String graph,
                                              @PathParam("name") String name) {
diff --git a/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java b/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java
index 44d5b6587..dcf6cbb0d 100644
--- a/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java
+++ b/hugegraph-api/src/main/java/org/apache/hugegraph/api/raft/RaftAPI.java
@@ -34,6 +34,7 @@ import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.QueryParam;
 import jakarta.ws.rs.core.Context;
 
+import org.apache.hugegraph.api.filter.RedirectFilter;
 import org.apache.hugegraph.core.GraphManager;
 import org.slf4j.Logger;
 
@@ -151,6 +152,7 @@ public class RaftAPI extends API {
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON_WITH_CHARSET)
     @RolesAllowed({"admin"})
+    @RedirectFilter.RedirectMasterRole
     public Map<String, Id> addPeer(@Context GraphManager manager,
                                    @PathParam("graph") String graph,
                                    @QueryParam("group") @DefaultValue("default")
@@ -180,6 +182,7 @@ public class RaftAPI extends API {
     @Consumes(APPLICATION_JSON)
     @Produces(APPLICATION_JSON_WITH_CHARSET)
     @RolesAllowed({"admin"})
+    @RedirectFilter.RedirectMasterRole
     public Map<String, Id> removePeer(@Context GraphManager manager,
                                       @PathParam("graph") String graph,
                                       @QueryParam("group")
diff --git a/hugegraph-core/src/main/java/org/apache/hugegraph/election/StandardStateMachineCallback.java b/hugegraph-core/src/main/java/org/apache/hugegraph/election/StandardStateMachineCallback.java
index d72172c8d..edca35880 100644
--- a/hugegraph-core/src/main/java/org/apache/hugegraph/election/StandardStateMachineCallback.java
+++ b/hugegraph-core/src/main/java/org/apache/hugegraph/election/StandardStateMachineCallback.java
@@ -41,9 +41,9 @@ public class StandardStateMachineCallback implements StateMachineCallback {
     public void onAsRoleMaster(StateMachineContext context) {
         if (!isMaster) {
             this.taskManager.onAsRoleMaster();
-            this.initGlobalMasterInfo(context);
             LOG.info("Server {} change to master role", context.config().node());
         }
+        this.initGlobalMasterInfo(context);
         this.isMaster = true;
     }
 
@@ -51,10 +51,9 @@ public class StandardStateMachineCallback implements StateMachineCallback {
     public void onAsRoleWorker(StateMachineContext context) {
         if (isMaster) {
             this.taskManager.onAsRoleWorker();
-            this.initGlobalMasterInfo(context);
             LOG.info("Server {} change to worker role", context.config().node());
         }
-
+        this.initGlobalMasterInfo(context);
         this.isMaster = false;
     }
 
@@ -66,9 +65,9 @@ public class StandardStateMachineCallback implements StateMachineCallback {
     public void unknown(StateMachineContext context) {
         if (isMaster) {
             this.taskManager.onAsRoleWorker();
-            this.initGlobalMasterInfo(context);
             LOG.info("Server {} change to worker role", context.config().node());
         }
+        this.initGlobalMasterInfo(context);
 
         isMaster = false;
     }
@@ -77,9 +76,9 @@ public class StandardStateMachineCallback implements StateMachineCallback {
     public void onAsRoleAbdication(StateMachineContext context) {
         if (isMaster) {
             this.taskManager.onAsRoleWorker();
-            this.initGlobalMasterInfo(context);
             LOG.info("Server {} change to worker role", context.config().node());
         }
+        this.initGlobalMasterInfo(context);
 
         isMaster = false;
     }