[SCB-2230]encoding project name for non english (#2307)

diff --git a/huawei-cloud/servicestage/pom.xml b/huawei-cloud/servicestage/pom.xml
index a5cfe69..ad3bcac 100644
--- a/huawei-cloud/servicestage/pom.xml
+++ b/huawei-cloud/servicestage/pom.xml
@@ -36,6 +36,10 @@
       <groupId>org.apache.servicecomb</groupId>
       <artifactId>registry-service-center</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>foundation-test-scaffolding</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java
index 06eb7b1..9e0da32 100644
--- a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java
+++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java
@@ -17,6 +17,8 @@
 
 package org.apache.servicecomb.huaweicloud.servicestage;
 
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
@@ -61,12 +63,21 @@
 
   private Map<String, String> headers = new HashMap<>();
 
-  private Configuration configuration = ConfigUtil.createLocalConfig();
+  private final Configuration configuration;
 
-  private boolean enabled = configuration.getBoolean(CONFIG_AKSK_ENABLED, true);
+  private boolean enabled;
 
   private boolean loaded = false;
 
+  public AKSKAuthHeaderProvider() {
+    this(ConfigUtil.createLocalConfig());
+  }
+
+  public AKSKAuthHeaderProvider(Configuration configuration) {
+    this.configuration = configuration;
+    this.enabled = configuration.getBoolean(CONFIG_AKSK_ENABLED, true);
+  }
+
   public Map<String, String> authHeaders() {
     if (!enabled) {
       return headers;
@@ -115,7 +126,15 @@
   }
 
   private String getProject() {
-    return configuration.getString(CONFIG_PROJECT, VALUE_DEFAULT_PROJECT);
+    String project = configuration.getString(CONFIG_PROJECT, VALUE_DEFAULT_PROJECT);
+    if (StringUtils.isEmpty(project)) {
+      return project;
+    }
+    try {
+      return URLEncoder.encode(project, "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      return project;
+    }
   }
 
   private Cipher findCipher() {
diff --git a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java
new file mode 100644
index 0000000..72935a5
--- /dev/null
+++ b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java
@@ -0,0 +1,52 @@
+/*
+ * 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.servicecomb.huaweicloud.servicestage;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.netflix.config.ConcurrentCompositeConfiguration;
+
+public class TestAKSKAuthHeaderProvider {
+  @Test
+  public void test_project_name_properly_encoded_en() {
+    ConcurrentCompositeConfiguration configuration = Mockito.mock(ConcurrentCompositeConfiguration.class);
+    Mockito.when(configuration.getBoolean("servicecomb.credentials.akskEnabled", true)).thenReturn(true);
+    Mockito.when(configuration.getString("servicecomb.credentials.project", "default")).thenReturn("hello");
+    Mockito.when(configuration.getString("servicecomb.credentials.accessKey", "")).thenReturn("access key");
+    Mockito.when(configuration.getString("servicecomb.credentials.secretKey", "")).thenReturn("secret key");
+    Mockito.when(configuration.getString("servicecomb.credentials.akskCustomCipher", "default")).thenReturn("default");
+
+    AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(configuration);
+    Assert.assertEquals("hello", provider.authHeaders().get("X-Service-Project"), "hello");
+  }
+
+  @Test
+  public void test_project_name_properly_encoded_cn() {
+    ConcurrentCompositeConfiguration configuration = Mockito.mock(ConcurrentCompositeConfiguration.class);
+    Mockito.when(configuration.getBoolean("servicecomb.credentials.akskEnabled", true)).thenReturn(true);
+    Mockito.when(configuration.getString("servicecomb.credentials.project", "default")).thenReturn("测试");
+    Mockito.when(configuration.getString("servicecomb.credentials.accessKey", "")).thenReturn("access key");
+    Mockito.when(configuration.getString("servicecomb.credentials.secretKey", "")).thenReturn("secret key");
+    Mockito.when(configuration.getString("servicecomb.credentials.akskCustomCipher", "default")).thenReturn("default");
+
+    AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(configuration);
+    Assert.assertEquals("hello", provider.authHeaders().get("X-Service-Project"), "%E6%B5%8B%E8%AF%95");
+  }
+}