feat: support tsf gw. (#1697)
Co-authored-by: shedfreewu <49236872+shedfreewu@users.noreply.github.com>pull/1698/head
parent
2e5bb9f65a
commit
da9b66f8d8
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.cloud.metadata.core;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
|
||||||
|
public class HttpServletRequestHeaderWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
private Map<String, String> addHeaders;
|
||||||
|
|
||||||
|
public HttpServletRequestHeaderWrapper(HttpServletRequest request, Map<String, String> addHeaders) {
|
||||||
|
super(request);
|
||||||
|
this.addHeaders = addHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHeader(String name) {
|
||||||
|
if (addHeaders.containsKey(name)) {
|
||||||
|
return addHeaders.get(name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return super.getHeader(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.cloud.common.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.constant.MetadataConstant;
|
||||||
|
import com.tencent.cloud.common.tsf.TsfContextUtils;
|
||||||
|
import com.tencent.polaris.api.utils.CollectionUtils;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.polaris.metadata.core.constant.MetadataConstants;
|
||||||
|
import com.tencent.polaris.metadata.core.constant.TsfMetadataConstants;
|
||||||
|
import com.tencent.polaris.plugins.connector.consul.service.common.TagConstant;
|
||||||
|
import com.tencent.polaris.plugins.router.lane.LaneRouter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.tsf.core.entity.Metadata;
|
||||||
|
import org.springframework.tsf.core.entity.Tag;
|
||||||
|
|
||||||
|
public final class TsfTagUtils {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(TsfTagUtils.class);
|
||||||
|
|
||||||
|
private TsfTagUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Tag> deserializeTagList(String buffer) {
|
||||||
|
if (StringUtils.isEmpty(buffer)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Arrays.asList(JacksonUtils.deserialize(UrlUtils.decode(buffer), Tag[].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Metadata deserializeMetadata(String buffer) {
|
||||||
|
if (StringUtils.isEmpty(buffer)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JacksonUtils.deserialize(UrlUtils.decode(buffer), Metadata.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> getTsfMetadataMap(Map<String, String> calleeTransitiveHeaders, Map<String, String> disposableMetadata,
|
||||||
|
Map<String, String> customMetadata, Map<String, String> applicationMetadata) {
|
||||||
|
|
||||||
|
Map<String, String> tsfMetadataMap = new HashMap<>();
|
||||||
|
Set<String> tsfUserTagKeys = new HashSet<>();
|
||||||
|
// user tags
|
||||||
|
List<Tag> tsfUserTags = new ArrayList<>();
|
||||||
|
List<Tag> tsfSystemTags = new ArrayList<>();
|
||||||
|
Tag laneTag = null;
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : customMetadata.entrySet()) {
|
||||||
|
if (tsfUserTagKeys.contains(entry.getKey())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Tag tag = new Tag(entry.getKey(), entry.getValue(), Tag.ControlFlag.TRANSITIVE);
|
||||||
|
tsfUserTags.add(tag);
|
||||||
|
tsfUserTagKeys.add(entry.getKey());
|
||||||
|
if (LaneRouter.TRAFFIC_STAIN_LABEL.equals(entry.getKey()) && entry.getValue().contains("/")) {
|
||||||
|
String lane = entry.getValue().split("/")[1];
|
||||||
|
laneTag = new Tag("lane", lane, Tag.ControlFlag.TRANSITIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, String> entry : disposableMetadata.entrySet()) {
|
||||||
|
if (tsfUserTagKeys.contains(entry.getKey())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Tag tag = new Tag(entry.getKey(), entry.getValue());
|
||||||
|
tsfUserTags.add(tag);
|
||||||
|
tsfUserTagKeys.add(entry.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : calleeTransitiveHeaders.entrySet()) {
|
||||||
|
if (entry.getKey().startsWith(MetadataConstant.POLARIS_TRANSITIVE_HEADER_PREFIX)) {
|
||||||
|
String key = entry.getKey().substring(MetadataConstant.POLARIS_TRANSITIVE_HEADER_PREFIX_LENGTH);
|
||||||
|
String value = entry.getValue();
|
||||||
|
if (tsfUserTagKeys.contains(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag tag = new Tag(key, value, Tag.ControlFlag.TRANSITIVE);
|
||||||
|
tsfUserTags.add(tag);
|
||||||
|
tsfUserTagKeys.add(key);
|
||||||
|
if (LaneRouter.TRAFFIC_STAIN_LABEL.equals(key) && value.contains("/")) {
|
||||||
|
String lane = value.split("/")[1];
|
||||||
|
laneTag = new Tag("lane", lane, Tag.ControlFlag.TRANSITIVE);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (laneTag != null) {
|
||||||
|
tsfSystemTags.add(laneTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(tsfUserTags)) {
|
||||||
|
tsfMetadataMap.put(MetadataConstant.HeaderName.TSF_TAGS, JacksonUtils.serialize2Json(tsfUserTags));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(tsfSystemTags)) {
|
||||||
|
tsfMetadataMap.put(MetadataConstant.HeaderName.TSF_SYSTEM_TAG, JacksonUtils.serialize2Json(tsfSystemTags));
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata metadata = new Metadata();
|
||||||
|
for (Map.Entry<String, String> entry : applicationMetadata.entrySet()) {
|
||||||
|
switch (entry.getKey()) {
|
||||||
|
case MetadataConstants.LOCAL_SERVICE:
|
||||||
|
metadata.setServiceName(entry.getValue());
|
||||||
|
break;
|
||||||
|
case MetadataConstants.LOCAL_IP:
|
||||||
|
metadata.setLocalIp(entry.getValue());
|
||||||
|
break;
|
||||||
|
case TsfMetadataConstants.TSF_GROUP_ID:
|
||||||
|
metadata.setGroupId(entry.getValue());
|
||||||
|
break;
|
||||||
|
case TsfMetadataConstants.TSF_APPLICATION_ID:
|
||||||
|
metadata.setApplicationId(entry.getValue());
|
||||||
|
break;
|
||||||
|
case TsfMetadataConstants.TSF_INSTNACE_ID:
|
||||||
|
metadata.setInstanceId(entry.getValue());
|
||||||
|
break;
|
||||||
|
case TsfMetadataConstants.TSF_PROG_VERSION:
|
||||||
|
metadata.setApplicationVersion(entry.getValue());
|
||||||
|
break;
|
||||||
|
case TsfMetadataConstants.TSF_NAMESPACE_ID:
|
||||||
|
metadata.setNamespaceId(entry.getValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tsfMetadataMap.put(MetadataConstant.HeaderName.TSF_METADATA, JacksonUtils.serialize2Json(metadata));
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug("calleeTransitiveHeaders:{}, disposableMetadata: {}, customMetadata: {}, applicationMetadata: {}, tsfMetadataMap:{}",
|
||||||
|
calleeTransitiveHeaders, disposableMetadata, customMetadata, applicationMetadata, tsfMetadataMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tsfMetadataMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateTsfMetadata(Map<String, String> mergedTransitiveMetadata,
|
||||||
|
Map<String, String> mergedDisposableMetadata, Map<String, String> mergedApplicationMetadata, Map<String, String> addHeaders,
|
||||||
|
AtomicReference<String> callerIp, String encodedUserTagList, String encodedSystemTagList, String encodedMetadata) {
|
||||||
|
|
||||||
|
if (!TsfContextUtils.isOnlyTsfConsulEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Tag> tsfUserTagList = TsfTagUtils.deserializeTagList(encodedUserTagList);
|
||||||
|
int tagSize = Optional.ofNullable(tsfUserTagList).map(List::size).orElse(0);
|
||||||
|
Map<String, String> tsfTransitiveMetadata = new HashMap<>(tagSize);
|
||||||
|
Map<String, String> tsfDisposableMetadata = new HashMap<>(tagSize);
|
||||||
|
if (CollectionUtils.isNotEmpty(tsfUserTagList)) {
|
||||||
|
for (Tag tag : tsfUserTagList) {
|
||||||
|
if (Tag.ControlFlag.TRANSITIVE.equals(tag.getFlags())) {
|
||||||
|
tsfTransitiveMetadata.put(tag.getKey(), tag.getValue());
|
||||||
|
}
|
||||||
|
tsfDisposableMetadata.put(tag.getKey(), tag.getValue());
|
||||||
|
}
|
||||||
|
mergedTransitiveMetadata.putAll(tsfTransitiveMetadata);
|
||||||
|
mergedDisposableMetadata.putAll(tsfDisposableMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Tag> tsfSystemTagList = TsfTagUtils.deserializeTagList(encodedSystemTagList);
|
||||||
|
if (CollectionUtils.isNotEmpty(tsfSystemTagList)) {
|
||||||
|
for (Tag tag : tsfSystemTagList) {
|
||||||
|
if ("lane".equals(tag.getKey())) {
|
||||||
|
mergedTransitiveMetadata.put(LaneRouter.TRAFFIC_STAIN_LABEL, UrlUtils.encode("tsf/" + tag.getValue()));
|
||||||
|
addHeaders.put(MetadataConstant.POLARIS_TRANSITIVE_HEADER_PREFIX + LaneRouter.TRAFFIC_STAIN_LABEL,
|
||||||
|
UrlUtils.encode("tsf/" + tag.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata metadata = TsfTagUtils.deserializeMetadata(encodedMetadata);
|
||||||
|
if (metadata != null) {
|
||||||
|
if (StringUtils.isNotEmpty(metadata.getLocalIp())) {
|
||||||
|
callerIp.set(metadata.getLocalIp());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(metadata.getApplicationId())) {
|
||||||
|
mergedApplicationMetadata.put(TsfMetadataConstants.TSF_APPLICATION_ID, metadata.getApplicationId());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(metadata.getGroupId())) {
|
||||||
|
mergedApplicationMetadata.put(TsfMetadataConstants.TSF_GROUP_ID, metadata.getGroupId());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(metadata.getApplicationVersion())) {
|
||||||
|
mergedApplicationMetadata.put(TsfMetadataConstants.TSF_PROG_VERSION, metadata.getApplicationVersion());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(metadata.getNamespaceId())) {
|
||||||
|
mergedApplicationMetadata.put(TsfMetadataConstants.TSF_NAMESPACE_ID, metadata.getNamespaceId());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(metadata.getServiceName())) {
|
||||||
|
mergedApplicationMetadata.put(MetadataConstants.LOCAL_SERVICE, metadata.getServiceName());
|
||||||
|
mergedApplicationMetadata.put(TagConstant.SYSTEM_FIELD.SOURCE_SERVICE_NAME, metadata.getServiceName());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(metadata.getLocalIp())) {
|
||||||
|
mergedApplicationMetadata.put(MetadataConstants.LOCAL_IP, metadata.getLocalIp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug("mergedTransitiveMetadata:{}, mergedDisposableMetadata: {}, mergedApplicationMetadata: {},"
|
||||||
|
+ " addHeaders:{}, encodedUserTagList:{}, encodedSystemTagList:{}, encodedMetadata:{}, callerIp:{}",
|
||||||
|
mergedTransitiveMetadata, mergedDisposableMetadata, mergedApplicationMetadata,
|
||||||
|
addHeaders, encodedUserTagList, encodedSystemTagList, encodedMetadata, callerIp.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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.springframework.tsf.core.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
|
public class Metadata implements Serializable {
|
||||||
|
|
||||||
|
@JsonProperty("ai")
|
||||||
|
private String applicationId = "";
|
||||||
|
|
||||||
|
@JsonProperty("av")
|
||||||
|
private String applicationVersion = "";
|
||||||
|
|
||||||
|
@JsonProperty("sn")
|
||||||
|
private String serviceName = "";
|
||||||
|
|
||||||
|
@JsonProperty("ii")
|
||||||
|
private String instanceId = "";
|
||||||
|
|
||||||
|
@JsonProperty("gi")
|
||||||
|
private String groupId = "";
|
||||||
|
|
||||||
|
@JsonProperty("li")
|
||||||
|
private String localIp = "";
|
||||||
|
|
||||||
|
@JsonProperty("lis")
|
||||||
|
private String localIps = "";
|
||||||
|
|
||||||
|
@JsonProperty("ni")
|
||||||
|
private String namespaceId = "";
|
||||||
|
|
||||||
|
@JsonProperty("pi")
|
||||||
|
private boolean preferIpv6;
|
||||||
|
|
||||||
|
public Metadata() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApplicationId() {
|
||||||
|
return applicationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationId(String applicationId) {
|
||||||
|
this.applicationId = applicationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其实是程序包的版本,但是这里程序包概念没啥用,直接用应用来表示
|
||||||
|
public String getApplicationVersion() {
|
||||||
|
return applicationVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationVersion(String applicationVersion) {
|
||||||
|
this.applicationVersion = applicationVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServiceName() {
|
||||||
|
return serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceName(String serviceName) {
|
||||||
|
this.serviceName = serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstanceId() {
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInstanceId(String instanceId) {
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId(String groupId) {
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalIp() {
|
||||||
|
if (preferIpv6 && !StringUtils.isEmpty(localIps)) {
|
||||||
|
for (String ip : localIps.split(",")) {
|
||||||
|
if (ip.contains(":")) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return localIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalIp(String localIp) {
|
||||||
|
this.localIp = localIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalIps() {
|
||||||
|
return localIps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalIps(String localIps) {
|
||||||
|
this.localIps = localIps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespaceId() {
|
||||||
|
return namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNamespaceId(String namespaceId) {
|
||||||
|
this.namespaceId = namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreferIpv6() {
|
||||||
|
return preferIpv6;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreferIpv6(boolean preferIpv6) {
|
||||||
|
this.preferIpv6 = preferIpv6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Metadata{" +
|
||||||
|
"applicationId='" + applicationId + '\'' +
|
||||||
|
", applicationVersion='" + applicationVersion + '\'' +
|
||||||
|
", serviceName='" + serviceName + '\'' +
|
||||||
|
", instanceId='" + instanceId + '\'' +
|
||||||
|
", groupId='" + groupId + '\'' +
|
||||||
|
", localIp='" + localIp + '\'' +
|
||||||
|
", namespaceId='" + namespaceId + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.cloud.common.util;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.tsf.core.entity.Tag;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test for {@link TsfTagUtils}.
|
||||||
|
*/
|
||||||
|
public class TsfTagUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deserializeTagList() {
|
||||||
|
String data = "%5B%7B%22k%22%3A%22tsf-gateway-ratelimit-context%22%2C%22v%22%3A%22grp-vyiwvq5t%22%2C%22f%22%3A%5B%5D%7D%2C%7B%22k%22%3A%22feat%22%2C%22v%22%3A%22test%22%2C%22f%22%3A%5B%220%22%5D%7D%5D";
|
||||||
|
List<Tag> tagList = TsfTagUtils.deserializeTagList(data);
|
||||||
|
for (Tag tag : tagList) {
|
||||||
|
assertThat(tag.getKey()).isNotNull();
|
||||||
|
assertThat(tag.getValue()).isNotNull();
|
||||||
|
assertThat(tag.getFlags()).isNotNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>tsf-example</artifactId>
|
||||||
|
<groupId>com.tencent.cloud</groupId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>msgw-scg</artifactId>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.tencent.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-tencent-all</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.cloud.tsf.msgw.scg;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.tsf.annotation.EnableTsf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author seanlxliu
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableTsf
|
||||||
|
public class ScgApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ScgApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
error:
|
||||||
|
include-exception: true
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: msgw-scg
|
||||||
|
cloud:
|
||||||
|
gateway:
|
||||||
|
discovery:
|
||||||
|
locator:
|
||||||
|
enabled: true
|
||||||
|
lower-case-service-id: false
|
||||||
|
httpclient:
|
||||||
|
# The connect timeout in millis, the default is 45s.
|
||||||
|
connectTimeout: 200
|
||||||
|
responseTimeout: 10s
|
||||||
|
consul:
|
||||||
|
enabled: true
|
||||||
|
scheme: HTTP
|
||||||
|
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
root: INFO
|
||||||
|
file:
|
||||||
|
name: /tsf-demo-logs/${spring.application.name}/root.log
|
||||||
|
pattern:
|
||||||
|
level: "%-5level [${spring.application.name},%mdc{trace_id},%mdc{span_id},]"
|
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.cloud.plugin.gateway.context;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.AuthMode;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.CommonStatus;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.HeaderName;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.TsfAlgType;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayError;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayException;
|
||||||
|
import com.tencent.tsf.gateway.core.util.TsfSignUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
public final class AuthCheckUtil {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AuthCheckUtil.class);
|
||||||
|
|
||||||
|
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
private AuthCheckUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void signCheck(ServerWebExchange exchange, GroupContext groupContext) {
|
||||||
|
AuthMode authMode = Optional.ofNullable(groupContext.getAuth()).map(GroupContext.ContextAuth::getType)
|
||||||
|
.orElse(null);
|
||||||
|
if (!AuthMode.SECRET.equals(authMode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String secretId = exchange.getRequest().getHeaders().getFirst(HeaderName.APP_KEY);
|
||||||
|
if (StringUtils.isEmpty(secretId)) {
|
||||||
|
logger.error("[signCheck] secretId is empty. path: {}", exchange.getRequest().getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_BAD_REQUEST, "RequestHeader x-mg-secretid is required");
|
||||||
|
}
|
||||||
|
String nonce = exchange.getRequest().getHeaders().getFirst(HeaderName.NONCE);
|
||||||
|
if (StringUtils.isEmpty(nonce)) {
|
||||||
|
logger.error("[signCheck] nonce is empty. path: {}", exchange.getRequest().getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_BAD_REQUEST, "RequestHeader x-mg-nonce is required");
|
||||||
|
}
|
||||||
|
String alg = exchange.getRequest().getHeaders().getFirst(HeaderName.ALG);
|
||||||
|
if (StringUtils.isEmpty(alg)) {
|
||||||
|
logger.error("[signCheck] alg is empty. path: {}", exchange.getRequest().getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_BAD_REQUEST, "RequestHeader x-mg-alg is required");
|
||||||
|
}
|
||||||
|
String clientSign = exchange.getRequest().getHeaders().getFirst(HeaderName.SIGN);
|
||||||
|
if (StringUtils.isEmpty(clientSign)) {
|
||||||
|
logger.error("[signCheck] sign is empty. path: {}", exchange.getRequest().getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_FAILED, "RequestHeader x-mg-sign is wrong");
|
||||||
|
}
|
||||||
|
|
||||||
|
TsfAlgType algType = TsfAlgType.getSecurityCode(alg);
|
||||||
|
|
||||||
|
List<GroupContext.ContextSecret> secretList = groupContext.getAuth().getSecrets();
|
||||||
|
|
||||||
|
GroupContext.ContextSecret secret = null;
|
||||||
|
if (secretList != null) {
|
||||||
|
for (GroupContext.ContextSecret s : secretList) {
|
||||||
|
if (s.getId().equals(secretId)) {
|
||||||
|
secret = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secret == null) {
|
||||||
|
logger.error("[signCheck] secret is not found. secretId:{}, path: {}", secretId, exchange.getRequest()
|
||||||
|
.getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_FAILED, "GroupSecret Not Found");
|
||||||
|
}
|
||||||
|
if (CommonStatus.DISABLED.getStatus().equals(secret.getStatus())) {
|
||||||
|
logger.error("[signCheck] secret is invalid. secretId:{}, path: {}", secretId, exchange.getRequest()
|
||||||
|
.getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_BAD_REQUEST, "GroupSecret Invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
String expiredTime = secret.getExpiredTime();
|
||||||
|
LocalDateTime expiredDateTime = LocalDateTime.parse(expiredTime, FORMATTER);
|
||||||
|
LocalDateTime nowDateTime = LocalDateTime.now();
|
||||||
|
boolean expired = nowDateTime.isAfter(expiredDateTime);
|
||||||
|
|
||||||
|
if (expired) {
|
||||||
|
logger.error("[signCheck] secret is expired. secretId:{}, path: {}", secretId, exchange.getRequest()
|
||||||
|
.getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_FAILED, "GroupSecret Expired");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String serverSign = TsfSignUtil.generate(nonce, secretId, secret.getKey(), algType);
|
||||||
|
if (!StringUtils.equals(clientSign, serverSign)) {
|
||||||
|
logger.error("[signCheck] sign check failed. secretId:{}, nonce:{}, secretKey:{}, clientSign:{}, path: {}",
|
||||||
|
secretId, nonce, secret.getKey(), clientSign, exchange.getRequest().getURI().getPath());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_FAILED, "GroupSecret Check Failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,474 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.cloud.plugin.gateway.context;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import com.ecwid.consul.v1.ConsulClient;
|
||||||
|
import com.ecwid.consul.v1.ConsulRawClient;
|
||||||
|
import com.ecwid.consul.v1.QueryParams;
|
||||||
|
import com.ecwid.consul.v1.Response;
|
||||||
|
import com.ecwid.consul.v1.kv.model.GetValue;
|
||||||
|
import com.tencent.cloud.common.util.JacksonUtils;
|
||||||
|
import com.tencent.cloud.polaris.context.PolarisSDKContextManager;
|
||||||
|
import com.tencent.polaris.api.utils.CollectionUtils;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.polaris.client.util.NamedThreadFactory;
|
||||||
|
import com.tencent.polaris.factory.config.global.ServerConnectorConfigImpl;
|
||||||
|
import com.tencent.polaris.plugins.configuration.connector.consul.ConsulConfigConstants;
|
||||||
|
import com.tencent.polaris.plugins.configuration.connector.consul.ConsulConfigContext;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.AuthMode;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.GatewayConstant;
|
||||||
|
import com.tencent.tsf.gateway.core.model.GatewayAllResult;
|
||||||
|
import com.tencent.tsf.gateway.core.model.Group;
|
||||||
|
import com.tencent.tsf.gateway.core.model.GroupApi;
|
||||||
|
import com.tencent.tsf.gateway.core.model.GroupApiResult;
|
||||||
|
import com.tencent.tsf.gateway.core.model.GroupResult;
|
||||||
|
import com.tencent.tsf.gateway.core.model.GroupSecret;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PathRewriteResult;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PathWildcardResult;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PathWildcardRule;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PluginInstanceInfoResult;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
|
||||||
|
import org.springframework.cloud.gateway.filter.FilterDefinition;
|
||||||
|
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
|
||||||
|
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
|
||||||
|
import static com.tencent.polaris.api.config.plugin.DefaultPlugins.SERVER_CONNECTOR_CONSUL;
|
||||||
|
|
||||||
|
public class GatewayConsulRepo {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(GatewayConsulRepo.class);
|
||||||
|
|
||||||
|
private final ContextGatewayProperties contextGatewayProperties;
|
||||||
|
|
||||||
|
private final ContextGatewayPropertiesManager contextGatewayPropertiesManager;
|
||||||
|
|
||||||
|
private final ApplicationEventPublisher publisher;
|
||||||
|
private final AtomicLong gatewayGroupIndex = new AtomicLong(-1);
|
||||||
|
private final AtomicLong commonPluginIndex = new AtomicLong(-1);
|
||||||
|
private ConsulClient consulClient;
|
||||||
|
private ConsulConfigContext consulConfigContext;
|
||||||
|
private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2, new NamedThreadFactory("consul-gateway-watch", true));
|
||||||
|
|
||||||
|
public GatewayConsulRepo(ContextGatewayProperties contextGatewayProperties,
|
||||||
|
PolarisSDKContextManager polarisSDKContextManager,
|
||||||
|
ContextGatewayPropertiesManager contextGatewayPropertiesManager,
|
||||||
|
ApplicationEventPublisher publisher, String tsfGroupId) {
|
||||||
|
this.contextGatewayProperties = contextGatewayProperties;
|
||||||
|
this.contextGatewayPropertiesManager = contextGatewayPropertiesManager;
|
||||||
|
this.publisher = publisher;
|
||||||
|
|
||||||
|
List<ServerConnectorConfigImpl> serverConnectorConfigs = polarisSDKContextManager.getSDKContext().getConfig()
|
||||||
|
.getGlobal().getServerConnectors();
|
||||||
|
if (serverConnectorConfigs == null || serverConnectorConfigs.size() != 1 || !SERVER_CONNECTOR_CONSUL.equals(serverConnectorConfigs.get(0)
|
||||||
|
.getProtocol())) {
|
||||||
|
logger.warn("GatewayConsulRepo not enable, serverConnectorConfigs:{}", serverConnectorConfigs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init consul client
|
||||||
|
ServerConnectorConfigImpl connectorConfig = serverConnectorConfigs.get(0);
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(connectorConfig.getAddresses())) {
|
||||||
|
logger.warn("GatewayConsulRepo not enable, connectorConfig:{}", connectorConfig);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String address = connectorConfig.getAddresses().get(0);
|
||||||
|
int lastIndex = address.lastIndexOf(":");
|
||||||
|
String agentHost = address.substring(0, lastIndex);
|
||||||
|
int agentPort = Integer.parseInt(address.substring(lastIndex + 1));
|
||||||
|
logger.info("Connect to consul config server : [{}].", address);
|
||||||
|
|
||||||
|
consulClient = new ConsulClient(new ConsulRawClient(agentHost, agentPort));
|
||||||
|
initConsulConfigContext(connectorConfig);
|
||||||
|
|
||||||
|
Response<List<GetValue>> listResponse = consulClient.getKVValues("tsf_gateway/" + tsfGroupId, consulConfigContext.getAclToken());
|
||||||
|
|
||||||
|
gatewayGroupIndex.set(listResponse.getConsulIndex());
|
||||||
|
if (listResponse.getValue() != null) {
|
||||||
|
refreshGatewayGroupConfig(parseGroupResponse(listResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduledExecutorService.scheduleAtFixedRate(() -> {
|
||||||
|
try {
|
||||||
|
Response<List<GetValue>> watchResponse = consulClient.getKVValues("tsf_gateway/" + tsfGroupId,
|
||||||
|
consulConfigContext.getAclToken(), new QueryParams(consulConfigContext.getWaitTime(), gatewayGroupIndex.get()));
|
||||||
|
// 404
|
||||||
|
if (watchResponse.getValue() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 200
|
||||||
|
Long newIndex = watchResponse.getConsulIndex();
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[watch group] index: {}, newIndex: {}", gatewayGroupIndex.get(), newIndex);
|
||||||
|
}
|
||||||
|
if (newIndex != null && !Objects.equals(gatewayGroupIndex.get(), newIndex)) {
|
||||||
|
gatewayGroupIndex.set(newIndex);
|
||||||
|
refreshGatewayGroupConfig(parseGroupResponse(watchResponse));
|
||||||
|
this.publisher.publishEvent(new RefreshRoutesEvent(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.warn("Gateway config watch error.", e);
|
||||||
|
try {
|
||||||
|
Thread.sleep(consulConfigContext.getConsulErrorSleep());
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
logger.error("error in sleep, msg: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, consulConfigContext.getDelay(), consulConfigContext.getDelay(), TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
|
||||||
|
scheduledExecutorService.scheduleAtFixedRate(() -> {
|
||||||
|
try {
|
||||||
|
Response<List<GetValue>> watchResponse = consulClient.getKVValues("tsf_gateway/common/plugin",
|
||||||
|
consulConfigContext.getAclToken(), new QueryParams(consulConfigContext.getWaitTime(), commonPluginIndex.get()));
|
||||||
|
// 404
|
||||||
|
if (watchResponse.getValue() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 200
|
||||||
|
Long newIndex = watchResponse.getConsulIndex();
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[watch plugin] index: {}, newIndex: {}", commonPluginIndex.get(), newIndex);
|
||||||
|
}
|
||||||
|
if (newIndex != null && !Objects.equals(commonPluginIndex.get(), newIndex)) {
|
||||||
|
commonPluginIndex.set(listResponse.getConsulIndex());
|
||||||
|
parsePluginResponse(watchResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.error("Gateway plugin watch error.", e);
|
||||||
|
try {
|
||||||
|
Thread.sleep(consulConfigContext.getConsulErrorSleep());
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
logger.error("error in sleep, msg: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, consulConfigContext.getDelay(), consulConfigContext.getDelay(), TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initConsulConfigContext(ServerConnectorConfigImpl connectorConfig) {
|
||||||
|
// init consul config context.
|
||||||
|
consulConfigContext = new ConsulConfigContext();
|
||||||
|
// token
|
||||||
|
String tokenStr = connectorConfig.getToken();
|
||||||
|
if (StringUtils.isNotBlank(tokenStr)) {
|
||||||
|
consulConfigContext.setAclToken(tokenStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> metadata = connectorConfig.getMetadata();
|
||||||
|
if (CollectionUtils.isNotEmpty(metadata)) {
|
||||||
|
String waitTimeStr = metadata.get(ConsulConfigConstants.WAIT_TIME_KEY);
|
||||||
|
if (StringUtils.isNotBlank(waitTimeStr)) {
|
||||||
|
try {
|
||||||
|
int waitTime = Integer.parseInt(waitTimeStr);
|
||||||
|
consulConfigContext.setWaitTime(waitTime);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.warn("wait time string {} is not integer.", waitTimeStr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String delayStr = metadata.get(ConsulConfigConstants.DELAY_KEY);
|
||||||
|
if (StringUtils.isNotBlank(delayStr)) {
|
||||||
|
try {
|
||||||
|
int delay = Integer.parseInt(delayStr);
|
||||||
|
consulConfigContext.setDelay(delay);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.warn("delay string {} is not integer.", delayStr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String consulErrorSleepStr = metadata.get(ConsulConfigConstants.CONSUL_ERROR_SLEEP_KEY);
|
||||||
|
if (StringUtils.isNotBlank(consulErrorSleepStr)) {
|
||||||
|
try {
|
||||||
|
long consulErrorSleep = Long.parseLong(consulErrorSleepStr);
|
||||||
|
consulConfigContext.setConsulErrorSleep(consulErrorSleep);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.warn("delay string {} is not integer.", consulErrorSleepStr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parsePluginResponse(Response<List<GetValue>> listResponse) {
|
||||||
|
|
||||||
|
PluginInstanceInfoResult pluginInstanceInfoResult = new PluginInstanceInfoResult();
|
||||||
|
pluginInstanceInfoResult.setResult(new ArrayList<>());
|
||||||
|
|
||||||
|
for (GetValue getValue : listResponse.getValue()) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[parseResponse] Received plugin data: {}", getValue.getDecodedValue());
|
||||||
|
}
|
||||||
|
PluginInstanceInfoResult temp = JacksonUtils.deserialize(getValue.getDecodedValue(), PluginInstanceInfoResult.class);
|
||||||
|
pluginInstanceInfoResult.getResult().addAll(temp.getResult());
|
||||||
|
}
|
||||||
|
|
||||||
|
saveAsFile(JacksonUtils.serialize2Json(pluginInstanceInfoResult), GatewayConstant.PLUGIN_FILE_NAME);
|
||||||
|
|
||||||
|
contextGatewayProperties.setPlugins(pluginInstanceInfoResult.getResult());
|
||||||
|
contextGatewayPropertiesManager.refreshPlugins(contextGatewayProperties.getPlugins());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private GatewayAllResult parseGroupResponse(Response<List<GetValue>> listResponse) {
|
||||||
|
GroupResult groupResult = null;
|
||||||
|
GroupApiResult groupApiResult = new GroupApiResult();
|
||||||
|
groupApiResult.setResult(new ArrayList<>());
|
||||||
|
|
||||||
|
PathRewriteResult pathRewriteResult = new PathRewriteResult();
|
||||||
|
PathWildcardResult pathWildcardResult = null;
|
||||||
|
|
||||||
|
|
||||||
|
for (GetValue getValue : listResponse.getValue()) {
|
||||||
|
String key = getValue.getKey();
|
||||||
|
String[] keySplit = key.split("/");
|
||||||
|
// format example: tsf_gateway/group-xxx/group/data
|
||||||
|
if (keySplit.length < 4) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (keySplit[2]) {
|
||||||
|
case GatewayConstant.GROUP_FILE_NAME:
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[parseResponse] Received group data: {}", getValue.getDecodedValue());
|
||||||
|
}
|
||||||
|
groupResult = JacksonUtils.deserialize(getValue.getDecodedValue(), GroupResult.class);
|
||||||
|
break;
|
||||||
|
case GatewayConstant.API_FILE_NAME:
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[parseResponse] Received api data: {}", getValue.getDecodedValue());
|
||||||
|
}
|
||||||
|
GroupApiResult temp = JacksonUtils.deserialize(getValue.getDecodedValue(), GroupApiResult.class);
|
||||||
|
groupApiResult.getResult().addAll(temp.getResult());
|
||||||
|
break;
|
||||||
|
case GatewayConstant.PATH_REWRITE_FILE_NAME:
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[parseResponse] Received path rewrite data: {}", getValue.getDecodedValue());
|
||||||
|
}
|
||||||
|
pathRewriteResult = JacksonUtils.deserialize(getValue.getDecodedValue(), PathRewriteResult.class);
|
||||||
|
break;
|
||||||
|
case GatewayConstant.PATH_WILDCARD_FILE_NAME:
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("[parseResponse] Received path wildcard data: {}", getValue.getDecodedValue());
|
||||||
|
}
|
||||||
|
pathWildcardResult = JacksonUtils.deserialize(getValue.getDecodedValue(), PathWildcardResult.class);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
saveAsFile(JacksonUtils.serialize2Json(groupResult), GatewayConstant.GROUP_FILE_NAME);
|
||||||
|
saveAsFile(JacksonUtils.serialize2Json(groupApiResult), GatewayConstant.API_FILE_NAME);
|
||||||
|
saveAsFile(JacksonUtils.serialize2Json(pathRewriteResult), GatewayConstant.PATH_REWRITE_FILE_NAME);
|
||||||
|
saveAsFile(JacksonUtils.serialize2Json(pathWildcardResult), GatewayConstant.PATH_WILDCARD_FILE_NAME);
|
||||||
|
|
||||||
|
return new GatewayAllResult(groupResult, groupApiResult, pathRewriteResult, pathWildcardResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshGatewayGroupConfig(GatewayAllResult gatewayAllResult) {
|
||||||
|
GroupResult groupResult = gatewayAllResult.getGroupResult();
|
||||||
|
GroupApiResult groupApiResult = gatewayAllResult.getGroupApiResult();
|
||||||
|
PathRewriteResult pathRewriteResult = gatewayAllResult.getPathRewriteResult();
|
||||||
|
PathWildcardResult pathWildcardResult = gatewayAllResult.getPathWildcardResult();
|
||||||
|
|
||||||
|
Map<String, RouteDefinition> routes = new HashMap<>();
|
||||||
|
Map<String, GroupContext> groups = new HashMap<>();
|
||||||
|
|
||||||
|
if (groupResult != null && groupResult.getResult() != null) {
|
||||||
|
for (Group group : groupResult.getResult()) {
|
||||||
|
routes.put(group.getGroupId(), getRouteDefinition(group));
|
||||||
|
|
||||||
|
GroupContext.ContextPredicate contextPredicate = new GroupContext.ContextPredicate();
|
||||||
|
contextPredicate.setApiType(ApiType.valueOf(group.getGroupType().toUpperCase(Locale.ROOT)));
|
||||||
|
contextPredicate.setContext(group.getGroupContext());
|
||||||
|
contextPredicate.setNamespace(new GroupContext.ContextNamespace(
|
||||||
|
Position.valueOf(group.getNamespaceNameKeyPosition()
|
||||||
|
.toUpperCase(Locale.ROOT)), group.getNamespaceNameKey()));
|
||||||
|
contextPredicate.setService(new GroupContext.ContextService(
|
||||||
|
Position.valueOf(group.getServiceNameKeyPosition()
|
||||||
|
.toUpperCase(Locale.ROOT)), group.getServiceNameKey()));
|
||||||
|
|
||||||
|
List<GroupContext.ContextSecret> secrets = new ArrayList<>();
|
||||||
|
if (CollectionUtils.isNotEmpty(group.getSecretList())) {
|
||||||
|
for (GroupSecret groupSecret : group.getSecretList()) {
|
||||||
|
GroupContext.ContextSecret contextSecret = new GroupContext.ContextSecret();
|
||||||
|
contextSecret.setName(groupSecret.getSecretName());
|
||||||
|
contextSecret.setId(groupSecret.getSecretId());
|
||||||
|
contextSecret.setKey(groupSecret.getSecretKey());
|
||||||
|
contextSecret.setStatus(groupSecret.getStatus());
|
||||||
|
contextSecret.setExpiredTime(groupSecret.getExpiredTime());
|
||||||
|
|
||||||
|
secrets.add(contextSecret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupContext.ContextAuth auth = new GroupContext.ContextAuth();
|
||||||
|
auth.setType(AuthMode.getMode(group.getAuthMode()));
|
||||||
|
auth.setSecrets(secrets);
|
||||||
|
|
||||||
|
|
||||||
|
GroupContext groupContext = new GroupContext();
|
||||||
|
groupContext.setRoutes(new ArrayList<>());
|
||||||
|
groupContext.setPredicate(contextPredicate);
|
||||||
|
groupContext.setAuth(auth);
|
||||||
|
|
||||||
|
groups.put(group.getGroupId(), groupContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GroupApi groupApi : groupApiResult.getResult()) {
|
||||||
|
GroupContext groupContext = groups.get(groupApi.getGroupId());
|
||||||
|
if (groupContext == null) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("group api {} not found in group {}", groupApi.getApiId(), groupApi.getGroupId());
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupContext.ContextRoute contextRoute = new GroupContext.ContextRoute();
|
||||||
|
contextRoute.setApiId(groupApi.getApiId());
|
||||||
|
contextRoute.setHost(groupApi.getHost());
|
||||||
|
contextRoute.setPath(groupApi.getPath());
|
||||||
|
contextRoute.setPathMapping(groupApi.getPathMapping());
|
||||||
|
contextRoute.setMethod(groupApi.getMethod());
|
||||||
|
contextRoute.setService(groupApi.getServiceName());
|
||||||
|
contextRoute.setNamespaceId(groupApi.getNamespaceId());
|
||||||
|
contextRoute.setNamespace(groupApi.getNamespaceName());
|
||||||
|
if (groupApi.getTimeout() != null) {
|
||||||
|
Map<String, String> metadata = new HashMap<>();
|
||||||
|
metadata.put("response-timeout", String.valueOf(groupApi.getTimeout()));
|
||||||
|
contextRoute.setMetadata(metadata);
|
||||||
|
}
|
||||||
|
groupContext.getRoutes().add(contextRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathWildcardResult != null && pathWildcardResult.getResult() != null) {
|
||||||
|
for (PathWildcardRule wildcardRule : pathWildcardResult.getResult()) {
|
||||||
|
|
||||||
|
GroupContext.ContextRoute contextRoute = new GroupContext.ContextRoute();
|
||||||
|
contextRoute.setPath(wildcardRule.getWildCardPath());
|
||||||
|
contextRoute.setMethod(wildcardRule.getMethod());
|
||||||
|
contextRoute.setService(wildcardRule.getServiceName());
|
||||||
|
contextRoute.setNamespaceId(wildcardRule.getNamespaceId());
|
||||||
|
contextRoute.setNamespace(wildcardRule.getNamespaceName());
|
||||||
|
if (wildcardRule.getTimeout() != null) {
|
||||||
|
Map<String, String> metadata = new HashMap<>();
|
||||||
|
metadata.put("response-timeout", String.valueOf(wildcardRule.getTimeout()));
|
||||||
|
contextRoute.setMetadata(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupContext groupContext = groups.get(wildcardRule.getGroupId());
|
||||||
|
groupContext.getRoutes().add(contextRoute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contextGatewayProperties.setGroups(groups);
|
||||||
|
contextGatewayProperties.setRoutes(routes);
|
||||||
|
contextGatewayProperties.setPathRewrites(Optional.ofNullable(pathRewriteResult.getResult())
|
||||||
|
.orElse(new ArrayList<>()));
|
||||||
|
|
||||||
|
logger.debug("Gateway config loaded. :{}", JacksonUtils.serialize2Json(contextGatewayProperties));
|
||||||
|
|
||||||
|
contextGatewayPropertiesManager.setPathRewrites(contextGatewayProperties.getPathRewrites());
|
||||||
|
|
||||||
|
|
||||||
|
contextGatewayPropertiesManager.refreshGroupRoute(contextGatewayProperties.getGroups());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAsFile(String data, String type) {
|
||||||
|
try {
|
||||||
|
// 写入文件
|
||||||
|
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(getRepoStoreFile(type)));
|
||||||
|
writer.write(data);
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
logger.warn("[tsf-gateway] save as file occur exception.", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getRepoStoreFile(String type) {
|
||||||
|
String filePath = GatewayConstant.GATEWAY_REPO_PREFIX + type + GatewayConstant.FILE_SUFFIX;
|
||||||
|
File file = new File(filePath);
|
||||||
|
try {
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
file.createNewFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
|
||||||
|
logger.warn("[tsf-gateway] load group info from local file occur error. filePath: " + filePath, e);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RouteDefinition getRouteDefinition(Group group) {
|
||||||
|
RouteDefinition routeDefinition = new RouteDefinition();
|
||||||
|
routeDefinition.setUri(URI.create("lb://" + group.getGroupId()));
|
||||||
|
|
||||||
|
PredicateDefinition contextPredicateDefinition = new PredicateDefinition();
|
||||||
|
contextPredicateDefinition.setName("Context");
|
||||||
|
contextPredicateDefinition.setArgs(Collections.singletonMap("group", group.getGroupId()));
|
||||||
|
PredicateDefinition pathPredicateDefinition = new PredicateDefinition();
|
||||||
|
pathPredicateDefinition.setName("Path");
|
||||||
|
pathPredicateDefinition.setArgs(Collections.singletonMap("pattern", group.getGroupContext() + "/**"));
|
||||||
|
routeDefinition.setPredicates(Arrays.asList(contextPredicateDefinition, pathPredicateDefinition));
|
||||||
|
|
||||||
|
FilterDefinition contextFilterDefinition = new FilterDefinition();
|
||||||
|
contextFilterDefinition.setName("Context");
|
||||||
|
contextFilterDefinition.setArgs(Collections.singletonMap("group", group.getGroupId()));
|
||||||
|
routeDefinition.setFilters(Collections.singletonList(contextFilterDefinition));
|
||||||
|
|
||||||
|
routeDefinition.setOrder(-1);
|
||||||
|
|
||||||
|
return routeDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.cloud.plugin.gateway.context;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.GatewayConstant;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
|
||||||
|
public final class PathRewriteUtil {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PathRewriteUtil.class);
|
||||||
|
private static final String BLOCKED = "Y";
|
||||||
|
|
||||||
|
private PathRewriteUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getNewPath(List<PathRewrite> pathRewrites, String path, ServerWebExchange exchange) {
|
||||||
|
String newPath = path;
|
||||||
|
for (PathRewrite pathRewrite : pathRewrites) {
|
||||||
|
String regex = pathRewrite.getRegex();
|
||||||
|
String replacement = pathRewrite.getReplacement();
|
||||||
|
String blockedRegex = replacement.replaceAll("\\$(\\d+|\\{[^/]+?\\})", ".*");
|
||||||
|
|
||||||
|
if (!StringUtils.isBlank(blockedRegex) && BLOCKED.equalsIgnoreCase(pathRewrite.getBlocked())
|
||||||
|
&& path.matches(blockedRegex)) {
|
||||||
|
logger.warn("[TSF-MSGW] uri is blocked by rule. uri: [{}] rule: [{}] -> [{}]",
|
||||||
|
path, regex, replacement);
|
||||||
|
ResponseStatusException exception = new ResponseStatusException(HttpStatus.BAD_REQUEST, "uri is blocked by rule. uri: [" + path + "] rule: [" + regex + "] -> [" + replacement + "]");
|
||||||
|
exchange.getAttributes().put(GatewayConstant.PATH_REWRITE_EXCEPTION, exception);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.isBlank(regex) && !StringUtils.isBlank(replacement) && path.matches(regex)) {
|
||||||
|
newPath = path.replaceAll(regex, replacement);
|
||||||
|
logger.info("[TSF-MSGW] rewrite path [{}] to [{}], rule: [{}] -> [{}]", path, newPath, regex, replacement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Shedfree Wu
|
||||||
|
*/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Component
|
||||||
|
public @interface TsfGatewayFilter {
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/11 23:37
|
||||||
|
*/
|
||||||
|
public enum AuthMode {
|
||||||
|
/**
|
||||||
|
* NONE.
|
||||||
|
*/
|
||||||
|
NONE("none"),
|
||||||
|
/**
|
||||||
|
* SECRET.
|
||||||
|
*/
|
||||||
|
SECRET("secret");
|
||||||
|
|
||||||
|
private final String authMode;
|
||||||
|
|
||||||
|
AuthMode(String authMode) {
|
||||||
|
this.authMode = authMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AuthMode getMode(String authMode) {
|
||||||
|
for (AuthMode groupAuthType : AuthMode.values()) {
|
||||||
|
if (groupAuthType.authMode.equalsIgnoreCase(authMode)) {
|
||||||
|
return groupAuthType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/11 17:05
|
||||||
|
*/
|
||||||
|
public enum CommonStatus {
|
||||||
|
/**
|
||||||
|
* ENABLED.
|
||||||
|
*/
|
||||||
|
ENABLED("enabled"),
|
||||||
|
/**
|
||||||
|
* DISABLED.
|
||||||
|
*/
|
||||||
|
DISABLED("disabled");
|
||||||
|
|
||||||
|
private final String status;
|
||||||
|
|
||||||
|
CommonStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommonStatus getStatus(String status) {
|
||||||
|
for (CommonStatus commonStatus : CommonStatus.values()) {
|
||||||
|
if (commonStatus.status.equals(status)) {
|
||||||
|
return commonStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CommonStatus getStatus(String status, String errorMsg) {
|
||||||
|
for (CommonStatus commonStatus : CommonStatus.values()) {
|
||||||
|
if (commonStatus.status.equals(status)) {
|
||||||
|
return commonStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/10 15:34
|
||||||
|
*/
|
||||||
|
public final class GatewayConstant {
|
||||||
|
/**
|
||||||
|
* CONTEXT_ROUTE.
|
||||||
|
*/
|
||||||
|
public static final String CONTEXT_ROUTE = "contextRoute";
|
||||||
|
/**
|
||||||
|
* 网关能够访问的API分组的缓存文件名称.
|
||||||
|
*/
|
||||||
|
public static final String GROUP_FILE_NAME = "group";
|
||||||
|
/**
|
||||||
|
* 网关能够被访问的API的缓存文件名称.
|
||||||
|
*/
|
||||||
|
public static final String API_FILE_NAME = "api";
|
||||||
|
/**
|
||||||
|
* 网关分组绑定的插件缓存文件名称.
|
||||||
|
*/
|
||||||
|
public static final String PLUGIN_FILE_NAME = "plugin";
|
||||||
|
/**
|
||||||
|
* 网关分组绑定的插件缓存文件名称.
|
||||||
|
*/
|
||||||
|
public static final String PATH_REWRITE_FILE_NAME = "rewrite";
|
||||||
|
/**
|
||||||
|
* PATH_REWRITE_EXCEPTION.
|
||||||
|
*/
|
||||||
|
public static final String PATH_REWRITE_EXCEPTION = "PathRewriteException";
|
||||||
|
/**
|
||||||
|
* 网关路径通配规则缓存文件名称.
|
||||||
|
*/
|
||||||
|
public static final String PATH_WILDCARD_FILE_NAME = "wildcard";
|
||||||
|
/**
|
||||||
|
* 本地文件的文件扩展名称.
|
||||||
|
*/
|
||||||
|
public static final String FILE_SUFFIX = ".json";
|
||||||
|
/**
|
||||||
|
* 网关插件通用部署组名称.
|
||||||
|
*/
|
||||||
|
public static final String GATEWAY_COMMON_DEPLOY_GROUP_ID = "common";
|
||||||
|
/**
|
||||||
|
* 在Spring Cloud Gateway中用来全量匹配所有请求的.
|
||||||
|
*/
|
||||||
|
public static final String GATEWAY_WILDCARD_SERVICE_NAME = "wildcard_tsf_gateway";
|
||||||
|
/**
|
||||||
|
* Tsf Gateway 的限流标签.
|
||||||
|
*/
|
||||||
|
public static final String TSF_GATEWAY_RATELIMIT_CONTEXT_TAG = "tsf-gateway-ratelimit-context";
|
||||||
|
/**
|
||||||
|
* 本地文件的仓库跟目录.
|
||||||
|
*/
|
||||||
|
private static final String GATEWAY_REPO_ROOT = System.getProperty("user.home");
|
||||||
|
/**
|
||||||
|
* Gateway 本地仓库的文件目录.
|
||||||
|
*/
|
||||||
|
public static final String GATEWAY_REPO_PREFIX = GATEWAY_REPO_ROOT + "/tsf/gateway/";
|
||||||
|
|
||||||
|
private GatewayConstant() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
public final class HeaderName {
|
||||||
|
/**
|
||||||
|
* UNIT.
|
||||||
|
*/
|
||||||
|
public static final String UNIT = "TSF-Unit";
|
||||||
|
/**
|
||||||
|
* NAMESPACE_ID.
|
||||||
|
*/
|
||||||
|
public static final String NAMESPACE_ID = "TSF-NamespaceId";
|
||||||
|
/**
|
||||||
|
* APP_KEY.
|
||||||
|
*/
|
||||||
|
public static final String APP_KEY = "x-mg-secretid";
|
||||||
|
/**
|
||||||
|
* ALG.
|
||||||
|
*/
|
||||||
|
public static final String ALG = "x-mg-alg";
|
||||||
|
/**
|
||||||
|
* SIGN.
|
||||||
|
*/
|
||||||
|
public static final String SIGN = "x-mg-sign";
|
||||||
|
/**
|
||||||
|
* NONCE.
|
||||||
|
*/
|
||||||
|
public static final String NONCE = "x-mg-nonce";
|
||||||
|
/**
|
||||||
|
* NODE.
|
||||||
|
*/
|
||||||
|
public static final String NODE = "x-mg-node";
|
||||||
|
/**
|
||||||
|
* TRACE_ID.
|
||||||
|
*/
|
||||||
|
public static final String TRACE_ID = "x-mg-traceid";
|
||||||
|
|
||||||
|
|
||||||
|
private HeaderName() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/11 11:54
|
||||||
|
*/
|
||||||
|
public enum HttpMethod {
|
||||||
|
/**
|
||||||
|
* POST.
|
||||||
|
*/
|
||||||
|
POST("POST"),
|
||||||
|
/**
|
||||||
|
* GET.
|
||||||
|
*/
|
||||||
|
GET("GET"),
|
||||||
|
/**
|
||||||
|
* PUT.
|
||||||
|
*/
|
||||||
|
PUT("PUT"),
|
||||||
|
/**
|
||||||
|
* DELETE.
|
||||||
|
*/
|
||||||
|
DELETE("DELETE");
|
||||||
|
|
||||||
|
private final String httpMethod;
|
||||||
|
|
||||||
|
HttpMethod(String httpMethod) {
|
||||||
|
this.httpMethod = httpMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpMethod getHttpMethod(String method) {
|
||||||
|
for (HttpMethod httpMethod : HttpMethod.values()) {
|
||||||
|
if (httpMethod.httpMethod.equalsIgnoreCase(method)) {
|
||||||
|
return httpMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayError;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: vmershen
|
||||||
|
* @since: 1.1.0
|
||||||
|
**/
|
||||||
|
public final class PluginConstants {
|
||||||
|
/**
|
||||||
|
* 设置每个标签插件JSON串长度.
|
||||||
|
*/
|
||||||
|
public static final Integer TAG_PLUGIN_INFO_LIST_LIMIT = 3000;
|
||||||
|
|
||||||
|
private PluginConstants() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TAG插件traceIdEnabled类型.
|
||||||
|
*/
|
||||||
|
public enum TraceIdEnabledType {
|
||||||
|
/**
|
||||||
|
* Y: enable.
|
||||||
|
*/
|
||||||
|
Y,
|
||||||
|
/**
|
||||||
|
* N: disable.
|
||||||
|
*/
|
||||||
|
N;
|
||||||
|
|
||||||
|
public static TraceIdEnabledType getTraceIdEnabledType(String enabledType) {
|
||||||
|
for (TraceIdEnabledType taskFlowEdgeType : TraceIdEnabledType.values()) {
|
||||||
|
if (taskFlowEdgeType.name().equalsIgnoreCase(enabledType)) {
|
||||||
|
return taskFlowEdgeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void checkValidity(String enabledType) {
|
||||||
|
TraceIdEnabledType traceIdEnabledType = getTraceIdEnabledType(enabledType);
|
||||||
|
Optional.ofNullable(traceIdEnabledType).orElseThrow(()
|
||||||
|
-> new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_INVALID, "Tag插件TraceIdEnabled类型"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件范围类型.
|
||||||
|
* @author seanlxliu
|
||||||
|
* @since 2019/9/10
|
||||||
|
*/
|
||||||
|
public enum PluginScopeType {
|
||||||
|
/**
|
||||||
|
* 绑定组.
|
||||||
|
*/
|
||||||
|
GROUP("group"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绑定API.
|
||||||
|
*/
|
||||||
|
API("api");
|
||||||
|
|
||||||
|
private final String scopeType;
|
||||||
|
|
||||||
|
PluginScopeType(String scopeType) {
|
||||||
|
this.scopeType = scopeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PluginScopeType getScopeType(String scopeType) {
|
||||||
|
for (PluginScopeType pluginScopeType : PluginScopeType.values()) {
|
||||||
|
if (pluginScopeType.scopeType.equals(scopeType)) {
|
||||||
|
return pluginScopeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScopeType() {
|
||||||
|
return scopeType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.tencent.tsf.gateway.core.model.JwtPlugin;
|
||||||
|
import com.tencent.tsf.gateway.core.model.OAuthPlugin;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PluginInfo;
|
||||||
|
import com.tencent.tsf.gateway.core.model.RequestTransformerPlugin;
|
||||||
|
import com.tencent.tsf.gateway.core.model.TagPlugin;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public enum PluginType {
|
||||||
|
/**
|
||||||
|
* ReqTransformer 插件实现.
|
||||||
|
*/
|
||||||
|
REQ_TRANSFORMER("ReqTransformer", RequestTransformerPlugin.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth 插件实现.
|
||||||
|
*/
|
||||||
|
OAUTH("OAuth", OAuthPlugin.class),
|
||||||
|
/**
|
||||||
|
* Jwt 插件实现.
|
||||||
|
*/
|
||||||
|
JWT("Jwt", JwtPlugin.class),
|
||||||
|
/**
|
||||||
|
* Tag 转化插件实现.
|
||||||
|
*/
|
||||||
|
TAG("Tag", TagPlugin.class);
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
private static final Map<String, String> pluginMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
pluginMap.put(OAUTH.name(), OAUTH.type);
|
||||||
|
pluginMap.put(JWT.name(), JWT.type);
|
||||||
|
pluginMap.put(TAG.name(), TAG.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
private Class<? extends PluginInfo> pluginClazz;
|
||||||
|
|
||||||
|
PluginType(String type, Class<? extends PluginInfo> pluginClazz) {
|
||||||
|
this.type = type;
|
||||||
|
this.pluginClazz = pluginClazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PluginType getPluginType(String name) {
|
||||||
|
for (PluginType pluginType : PluginType.values()) {
|
||||||
|
if (pluginType.type.equalsIgnoreCase(name)) {
|
||||||
|
return pluginType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.warn("Unknown plugin type exception, please upgrade your gateway sdk");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> toMap() {
|
||||||
|
return pluginMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends PluginInfo> getPluginClazz() {
|
||||||
|
return pluginClazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPluginClazz(Class<? extends PluginInfo> pluginClazz) {
|
||||||
|
this.pluginClazz = pluginClazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/11 11:42
|
||||||
|
*/
|
||||||
|
public enum TsfAlgType {
|
||||||
|
/**
|
||||||
|
* 0:HMAC_MD5.
|
||||||
|
*/
|
||||||
|
HMAC_MD5("0"),
|
||||||
|
/**
|
||||||
|
* 1:HMAC_SHA_1.
|
||||||
|
*/
|
||||||
|
HMAC_SHA_1("1"),
|
||||||
|
/**
|
||||||
|
* 2:HMAC_SHA_256.
|
||||||
|
*/
|
||||||
|
HMAC_SHA_256("2"),
|
||||||
|
/**
|
||||||
|
* 3:HMAC_SHA_512.
|
||||||
|
*/
|
||||||
|
HMAC_SHA_512("3"),
|
||||||
|
/**
|
||||||
|
* 4:HMAC_SM3.
|
||||||
|
*/
|
||||||
|
HMAC_SM3("4");
|
||||||
|
|
||||||
|
|
||||||
|
private String alg;
|
||||||
|
|
||||||
|
TsfAlgType(String code) {
|
||||||
|
this.alg = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TsfAlgType getSecurityCode(String code) {
|
||||||
|
for (TsfAlgType algType : TsfAlgType.values()) {
|
||||||
|
if (algType.alg.equals(code)) {
|
||||||
|
return algType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlg() {
|
||||||
|
return alg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlg(String alg) {
|
||||||
|
this.alg = alg;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/9 13:30
|
||||||
|
*/
|
||||||
|
public enum TsfGatewayError {
|
||||||
|
/**
|
||||||
|
* GATEWAY_INTERNAL_ERROR.
|
||||||
|
*/
|
||||||
|
GATEWAY_INIT_ERROR(5000, "InitializeError: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_SYNC_ERROR.
|
||||||
|
*/
|
||||||
|
GATEWAY_SYNC_ERROR(5001, "SyncDataError: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_FILE_ERROR.
|
||||||
|
*/
|
||||||
|
GATEWAY_FILE_ERROR(5002, "LocalFile IO Error", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_SERIALIZE_ERROR.
|
||||||
|
*/
|
||||||
|
GATEWAY_SERIALIZE_ERROR(5003, "SerializeError: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_AUTH_ERROR.
|
||||||
|
*/
|
||||||
|
GATEWAY_AUTH_ERROR(5004, "AuthCheckException: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_INTERNAL_ERROR.
|
||||||
|
*/
|
||||||
|
GATEWAY_INTERNAL_ERROR(5005, "Gateway Internal Error: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_PARAMETER_REQUIRED.
|
||||||
|
*/
|
||||||
|
GATEWAY_PARAMETER_REQUIRED(5006, "ParameterRequired: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_PARAMETER_INVALID.
|
||||||
|
*/
|
||||||
|
GATEWAY_PARAMETER_INVALID(5007, "ParameterInvalid: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_BAD_REQUEST.
|
||||||
|
*/
|
||||||
|
GATEWAY_BAD_REQUEST(4000, "BadRequest: %s", 400),
|
||||||
|
/**
|
||||||
|
* GATEWAY_AUTH_FAILED.
|
||||||
|
*/
|
||||||
|
GATEWAY_AUTH_FAILED(4001, "AuthCheckFailed: %s", 401),
|
||||||
|
/**
|
||||||
|
* GATEWAY_REQUEST_FORBIDDEN.
|
||||||
|
*/
|
||||||
|
GATEWAY_REQUEST_FORBIDDEN(4003, "RequestForbidden: %s", 403),
|
||||||
|
/**
|
||||||
|
* GATEWAY_REQUEST_NOT_FOUND.
|
||||||
|
*/
|
||||||
|
GATEWAY_REQUEST_NOT_FOUND(4004, "RequestNotFound: %s", 404),
|
||||||
|
/**
|
||||||
|
* GATEWAY_REQUEST_METHOD_NOT_ALLOWED.
|
||||||
|
*/
|
||||||
|
GATEWAY_REMOTE_REQUEST_INVALID(4016, "RemoteRequestInvalid: %s", 416),
|
||||||
|
/**
|
||||||
|
* GATEWAY_REMOTE_SERVER_AUTH_FAILED.
|
||||||
|
*/
|
||||||
|
GATEWAY_REMOTE_SERVER_AUTH_FAILED(4017, "RemoteServerAuthFailed: %s", 401),
|
||||||
|
/**
|
||||||
|
* GATEWAY_PLUGIN_JWT.
|
||||||
|
*/
|
||||||
|
GATEWAY_PLUGIN_JWT(4020, "JwtError: %s", 500),
|
||||||
|
/**
|
||||||
|
* GATEWAY_REMOTE_SERVER_BUSY.
|
||||||
|
*/
|
||||||
|
GATEWAY_REMOTE_SERVER_BUSY(4021, "Server is busy: %s", 401),
|
||||||
|
/**
|
||||||
|
* GATEWAY_REMOTE_SERVER_CODE_INVALID.
|
||||||
|
*/
|
||||||
|
GATEWAY_REMOTE_SERVER_CODE_INVALID(4022, "Login Code is error: %s", 401),
|
||||||
|
/**
|
||||||
|
* GATEWAY_REMOTE_SERVER_LIMIT.
|
||||||
|
*/
|
||||||
|
GATEWAY_REMOTE_SERVER_LIMIT(4023, "Server Limit : %s", 401),
|
||||||
|
/**
|
||||||
|
* GATEWAY_AUTH_EXPIRED.
|
||||||
|
*/
|
||||||
|
GATEWAY_AUTH_EXPIRED(4024, "AuthCheckExpired : %s", 401),
|
||||||
|
/**
|
||||||
|
* GATEWAY_TOO_MANY_REQUEST.
|
||||||
|
*/
|
||||||
|
GATEWAY_TOO_MANY_REQUEST(4025, "AuthCheckExpired : %s", 429);
|
||||||
|
|
||||||
|
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
private String errMsg;
|
||||||
|
|
||||||
|
private Integer httpStatus;
|
||||||
|
|
||||||
|
TsfGatewayError(Integer code, String errMsg, Integer httpStatus) {
|
||||||
|
this.code = code;
|
||||||
|
this.errMsg = errMsg;
|
||||||
|
this.httpStatus = httpStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(Integer code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrMsg() {
|
||||||
|
return errMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrMsg(String errMsg) {
|
||||||
|
this.errMsg = errMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHttpStatus() {
|
||||||
|
return httpStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpStatus(Integer httpStatus) {
|
||||||
|
this.httpStatus = httpStatus;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.exception;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/9 12:29
|
||||||
|
*/
|
||||||
|
public class TsfGatewayException extends ResponseStatusException {
|
||||||
|
private static final long serialVersionUID = 9210499285923741857L;
|
||||||
|
|
||||||
|
private final TsfGatewayError gatewayError;
|
||||||
|
|
||||||
|
public TsfGatewayException(TsfGatewayError gatewayError, Object... args) {
|
||||||
|
this(gatewayError, null, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TsfGatewayException(TsfGatewayError gatewayError, Throwable throwable, Object... args) {
|
||||||
|
super(HttpStatus.resolve(gatewayError.getHttpStatus()), String.format("%s", String.format(gatewayError.getErrMsg(), args)), throwable);
|
||||||
|
this.gatewayError = gatewayError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TsfGatewayError getGatewayError() {
|
||||||
|
return gatewayError;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.http;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName Config
|
||||||
|
* @Description TODO
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/8 11:48
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public final class HttpConfigConstant {
|
||||||
|
/**
|
||||||
|
* HTTP_CONNECT_TIMEOUT.
|
||||||
|
*/
|
||||||
|
public static final int HTTP_CONNECT_TIMEOUT = 2000;
|
||||||
|
/**
|
||||||
|
* HTTP_SOCKET_TIMEOUT.
|
||||||
|
*/
|
||||||
|
public static final int HTTP_SOCKET_TIMEOUT = 10000;
|
||||||
|
/**
|
||||||
|
* HTTP_MAX_POOL_SIZE.
|
||||||
|
*/
|
||||||
|
public static final int HTTP_MAX_POOL_SIZE = 200;
|
||||||
|
/**
|
||||||
|
* HTTP_MONITOR_INTERVAL.
|
||||||
|
*/
|
||||||
|
public static final int HTTP_MONITOR_INTERVAL = 5000;
|
||||||
|
/**
|
||||||
|
* HTTP_IDLE_TIMEOUT.
|
||||||
|
*/
|
||||||
|
public static final int HTTP_IDLE_TIMEOUT = 30000;
|
||||||
|
|
||||||
|
private HttpConfigConstant() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,345 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InterruptedIOException;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.polaris.client.util.NamedThreadFactory;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.HttpEntityEnclosingRequest;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.HttpHost;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.HttpRequest;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.NoHttpResponseException;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.HttpRequestRetryHandler;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.config.RequestConfig;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.methods.HttpGet;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.methods.HttpPost;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.methods.HttpRequestBase;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.protocol.HttpClientContext;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.client.utils.URLEncodedUtils;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.config.Registry;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.config.RegistryBuilder;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.conn.ConnectTimeoutException;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.conn.routing.HttpRoute;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.conn.socket.LayeredConnectionSocketFactory;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.entity.StringEntity;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.impl.client.HttpClients;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.message.BasicNameValuePair;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.protocol.HttpContext;
|
||||||
|
import shade.polaris.org.apache.org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName HttpConnectionPoolUtil
|
||||||
|
* @Description httpclient连接池工具类
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/8 11:56
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public final class HttpConnectionPoolUtil {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
private static final int CONNECT_TIMEOUT = HttpConfigConstant.HTTP_CONNECT_TIMEOUT;
|
||||||
|
private static final int SOCKET_TIMEOUT = HttpConfigConstant.HTTP_SOCKET_TIMEOUT;
|
||||||
|
private static final int MAX_CONN = HttpConfigConstant.HTTP_MAX_POOL_SIZE;
|
||||||
|
private static final int MAX_PRE_ROUTE = HttpConfigConstant.HTTP_MAX_POOL_SIZE;
|
||||||
|
private static final int MAX_ROUTE = HttpConfigConstant.HTTP_MAX_POOL_SIZE;
|
||||||
|
private final static Object syncLock = new Object();
|
||||||
|
private volatile static CloseableHttpClient httpClient;
|
||||||
|
private static PoolingHttpClientConnectionManager manager;
|
||||||
|
private static ScheduledExecutorService monitorExecutor;
|
||||||
|
|
||||||
|
//程序退出时,释放资源
|
||||||
|
static {
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
closeConnectionPool();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpConnectionPoolUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setRequestConfig(HttpRequestBase httpRequestBase, Integer timeout) {
|
||||||
|
RequestConfig requestConfig = RequestConfig
|
||||||
|
.custom()
|
||||||
|
.setConnectionRequestTimeout(timeout == null ? CONNECT_TIMEOUT : timeout)
|
||||||
|
.setConnectTimeout(timeout == null ? CONNECT_TIMEOUT : timeout)
|
||||||
|
.setSocketTimeout(timeout == null ? SOCKET_TIMEOUT : timeout)
|
||||||
|
.build();
|
||||||
|
httpRequestBase.setConfig(requestConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CloseableHttpClient getHttpClient(String url) {
|
||||||
|
logger.info("url is : {}", url);
|
||||||
|
if (httpClient == null) {
|
||||||
|
//多线程下多个线程同时调用getHttpClient容易导致重复创建httpClient对象的问题,所以加上了同步锁
|
||||||
|
synchronized (syncLock) {
|
||||||
|
if (httpClient == null) {
|
||||||
|
httpClient = createHttpClient(url);
|
||||||
|
//开启监控线程,对异常和空闲线程进行关闭
|
||||||
|
monitorExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("gw-client", true));
|
||||||
|
monitorExecutor.scheduleAtFixedRate(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
//关闭异常连接
|
||||||
|
manager.closeExpiredConnections();
|
||||||
|
//关闭5s空闲的连接
|
||||||
|
manager.closeIdleConnections(HttpConfigConstant.HTTP_IDLE_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||||
|
logger.debug("close expired and idle for over {} ms connection", HttpConfigConstant.HTTP_IDLE_TIMEOUT);
|
||||||
|
}
|
||||||
|
}, HttpConfigConstant.HTTP_MONITOR_INTERVAL, HttpConfigConstant.HTTP_MONITOR_INTERVAL, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CloseableHttpClient createHttpClient(String url) {
|
||||||
|
ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
|
||||||
|
LayeredConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
|
||||||
|
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||||
|
.register("http", plainSocketFactory)
|
||||||
|
.register("https", sslSocketFactory).build();
|
||||||
|
manager = new PoolingHttpClientConnectionManager(registry);
|
||||||
|
//设置连接参数
|
||||||
|
manager.setMaxTotal(MAX_CONN); // 最大连接数
|
||||||
|
manager.setDefaultMaxPerRoute(MAX_PRE_ROUTE); // 路由最大连接数
|
||||||
|
//HttpHost httpHost = new HttpHost(host, port);
|
||||||
|
HttpHost httpHost = new HttpHost(url);
|
||||||
|
manager.setMaxPerRoute(new HttpRoute(httpHost), MAX_ROUTE);
|
||||||
|
//请求失败时,进行请求重试
|
||||||
|
HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {
|
||||||
|
@Override
|
||||||
|
public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
|
||||||
|
if (i > 3) {
|
||||||
|
//重试超过3次,放弃请求
|
||||||
|
logger.error("retry has more than 3 time, give up request");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e instanceof NoHttpResponseException) {
|
||||||
|
//服务器没有响应,可能是服务器断开了连接,应该重试
|
||||||
|
logger.error("receive no response from server, retry");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (e instanceof SSLHandshakeException) {
|
||||||
|
// SSL握手异常
|
||||||
|
logger.error("SSL hand shake exception");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e instanceof InterruptedIOException) {
|
||||||
|
//超时
|
||||||
|
logger.error("InterruptedIOException");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e instanceof UnknownHostException) {
|
||||||
|
// 服务器不可达
|
||||||
|
logger.error("server host unknown");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e instanceof ConnectTimeoutException) {
|
||||||
|
// 连接超时
|
||||||
|
logger.error("Connection Time out");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (e instanceof SSLException) {
|
||||||
|
logger.error("SSLException");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HttpClientContext context = HttpClientContext.adapt(httpContext);
|
||||||
|
HttpRequest request = context.getRequest();
|
||||||
|
//如果请求不是关闭连接的请求
|
||||||
|
return !(request instanceof HttpEntityEnclosingRequest);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CloseableHttpClient client = HttpClients.custom().setConnectionManager(manager).setRetryHandler(handler)
|
||||||
|
.build();
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get方式,请求参数以?形式拼接在url后面.
|
||||||
|
*
|
||||||
|
* @param url 请求url
|
||||||
|
* @param paramsMap 请求参数
|
||||||
|
* @param headerParamsMap 传入的header参数
|
||||||
|
* @param timeout 单位毫秒
|
||||||
|
* @return 返回结果
|
||||||
|
*/
|
||||||
|
public static String httpGet(String url, Map<String, String> paramsMap, Map<String, String> headerParamsMap, Integer timeout) {
|
||||||
|
// 数据必填项校验
|
||||||
|
if (StringUtils.isEmpty(url)) {
|
||||||
|
throw new IllegalArgumentException("url can not be empty");
|
||||||
|
}
|
||||||
|
CloseableHttpResponse res = null;
|
||||||
|
CloseableHttpClient httpClient = getHttpClient(url);
|
||||||
|
String result = null;
|
||||||
|
String baseUrl = buildUrl(url, paramsMap);
|
||||||
|
logger.info("get request: {}", baseUrl);
|
||||||
|
HttpGet httpGet = new HttpGet(baseUrl);
|
||||||
|
setRequestConfig(httpGet, timeout);
|
||||||
|
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
|
||||||
|
httpGet.setHeader("Accept", "application/json");
|
||||||
|
// 添加传入的header参数
|
||||||
|
buildHeaderParams(httpGet, headerParamsMap);
|
||||||
|
try {
|
||||||
|
res = httpClient.execute(httpGet, HttpClientContext.create());
|
||||||
|
result = EntityUtils.toString(res.getEntity());
|
||||||
|
logger.info("get response :{}", result);
|
||||||
|
if (res.getStatusLine().getStatusCode() != 200) {
|
||||||
|
logger.info("response error: {}", result);
|
||||||
|
throw new IllegalStateException(String.format("call url: %s failed, response: code[%s] body[%s]",
|
||||||
|
baseUrl, res.getStatusLine().getStatusCode(), result));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
logger.warn("Get request failed, url:" + baseUrl, e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
closeHttpResponse(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void closeHttpResponse(CloseableHttpResponse res) {
|
||||||
|
try {
|
||||||
|
if (res != null) {
|
||||||
|
res.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
logger.warn("Close httpClient failed!", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭连接池.
|
||||||
|
*/
|
||||||
|
public static void closeConnectionPool() {
|
||||||
|
try {
|
||||||
|
httpClient.close();
|
||||||
|
manager.close();
|
||||||
|
monitorExecutor.shutdown();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String httpPostWithJSON(String url, Map<String, String> paramsMap, String json, Map<String, String> headerParamsMap, Integer timeout)
|
||||||
|
throws Exception {
|
||||||
|
// 数据必填项校验
|
||||||
|
if (StringUtils.isBlank(url)) {
|
||||||
|
throw new Exception("url can't be empty");
|
||||||
|
}
|
||||||
|
// 数据必填项校验
|
||||||
|
if (StringUtils.isBlank(json)) {
|
||||||
|
json = "";
|
||||||
|
}
|
||||||
|
String baseUrl = buildUrl(url, paramsMap);
|
||||||
|
String result = null;
|
||||||
|
CloseableHttpResponse res = null;
|
||||||
|
CloseableHttpClient httpClient = getHttpClient(url);
|
||||||
|
HttpPost httpPost = new HttpPost(baseUrl);
|
||||||
|
setRequestConfig(httpPost, timeout);
|
||||||
|
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
|
||||||
|
httpPost.setHeader("Accept", "application/json");
|
||||||
|
// 添加传入的header参数
|
||||||
|
buildHeaderParams(httpPost, headerParamsMap);
|
||||||
|
|
||||||
|
httpPost.setEntity(new StringEntity(json, StandardCharsets.UTF_8));
|
||||||
|
logger.info("post url: {}", url);
|
||||||
|
try {
|
||||||
|
res = httpClient.execute(httpPost, HttpClientContext.create());
|
||||||
|
result = EntityUtils.toString(res.getEntity());
|
||||||
|
if (res.getStatusLine().getStatusCode() != 200 && res.getStatusLine().getStatusCode() != 201) {
|
||||||
|
logger.info("response error: {}", result);
|
||||||
|
throw new IllegalStateException(String.format("call url: %s failed, response: code[%s] body[%s]",
|
||||||
|
baseUrl, res.getStatusLine().getStatusCode(), result));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
logger.warn("Get request failed, url:" + baseUrl, e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
closeHttpResponse(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String buildUrl(String url, Map<String, String> paramsMap) {
|
||||||
|
String baseUrl = null;
|
||||||
|
if (paramsMap != null && !paramsMap.isEmpty()) {
|
||||||
|
List params = new ArrayList();
|
||||||
|
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue();
|
||||||
|
if (value != null) {
|
||||||
|
params.add(new BasicNameValuePair(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (url.contains("?")) {
|
||||||
|
baseUrl = url + "&" + URLEncodedUtils.format(params, "UTF-8");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
baseUrl = url + "?" + URLEncodedUtils.format(params, "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
baseUrl = url;
|
||||||
|
}
|
||||||
|
return baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildHeaderParams(HttpRequestBase httpRequestBase, Map<String, String> headerParamsMap) {
|
||||||
|
if (null != headerParamsMap) {
|
||||||
|
for (Map.Entry<String, String> entry : headerParamsMap.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue();
|
||||||
|
httpRequestBase.setHeader(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName ClaimMapping
|
||||||
|
* @Description TODO
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/12 16:12
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public class ClaimMapping implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8768365572845806890L;
|
||||||
|
//参数名称
|
||||||
|
private String parameterName;
|
||||||
|
//映射后参数名称
|
||||||
|
private String mappingParameterName;
|
||||||
|
//映射后参数名称
|
||||||
|
private String location;
|
||||||
|
|
||||||
|
public String getParameterName() {
|
||||||
|
return parameterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameterName(String parameterName) {
|
||||||
|
this.parameterName = parameterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMappingParameterName() {
|
||||||
|
return mappingParameterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMappingParameterName(String mappingParameterName) {
|
||||||
|
this.mappingParameterName = mappingParameterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
|
||||||
|
public class GatewayAllResult {
|
||||||
|
|
||||||
|
private GroupResult groupResult;
|
||||||
|
|
||||||
|
private GroupApiResult groupApiResult;
|
||||||
|
|
||||||
|
private PathRewriteResult pathRewriteResult;
|
||||||
|
|
||||||
|
private PathWildcardResult pathWildcardResult;
|
||||||
|
|
||||||
|
public GatewayAllResult(GroupResult groupResult, GroupApiResult groupApiResult,
|
||||||
|
PathRewriteResult pathRewriteResult, PathWildcardResult pathWildcardResult) {
|
||||||
|
this.groupResult = groupResult;
|
||||||
|
this.groupApiResult = groupApiResult;
|
||||||
|
this.pathRewriteResult = pathRewriteResult;
|
||||||
|
this.pathWildcardResult = pathWildcardResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupResult getGroupResult() {
|
||||||
|
return groupResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupResult(GroupResult groupResult) {
|
||||||
|
this.groupResult = groupResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupApiResult getGroupApiResult() {
|
||||||
|
return groupApiResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupApiResult(GroupApiResult groupApiResult) {
|
||||||
|
this.groupApiResult = groupApiResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathRewriteResult getPathRewriteResult() {
|
||||||
|
return pathRewriteResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathRewriteResult(PathRewriteResult pathRewriteResult) {
|
||||||
|
this.pathRewriteResult = pathRewriteResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathWildcardResult getPathWildcardResult() {
|
||||||
|
return pathWildcardResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathWildcardResult(PathWildcardResult pathWildcardResult) {
|
||||||
|
this.pathWildcardResult = pathWildcardResult;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/10 11:14
|
||||||
|
*/
|
||||||
|
public class GatewayResult<T> implements Serializable {
|
||||||
|
private static final long serialVersionUID = -8391900871963415134L;
|
||||||
|
|
||||||
|
private String gatewayId;
|
||||||
|
|
||||||
|
private String gatewayName;
|
||||||
|
|
||||||
|
private String gatewayGroupId;
|
||||||
|
|
||||||
|
private Integer reversion;
|
||||||
|
|
||||||
|
private String updatedTime;
|
||||||
|
|
||||||
|
private List<T> result;
|
||||||
|
|
||||||
|
public String getGatewayId() {
|
||||||
|
return gatewayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGatewayId(String gatewayId) {
|
||||||
|
this.gatewayId = gatewayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGatewayName() {
|
||||||
|
return gatewayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGatewayName(String gatewayName) {
|
||||||
|
this.gatewayName = gatewayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGatewayGroupId() {
|
||||||
|
return gatewayGroupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGatewayGroupId(String gatewayGroupId) {
|
||||||
|
this.gatewayGroupId = gatewayGroupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getReversion() {
|
||||||
|
return reversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReversion(Integer reversion) {
|
||||||
|
this.reversion = reversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdatedTime() {
|
||||||
|
return updatedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedTime(String updatedTime) {
|
||||||
|
this.updatedTime = updatedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(List<T> result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/10 10:18
|
||||||
|
*/
|
||||||
|
public class GroupApiResult extends GatewayResult<GroupApi> {
|
||||||
|
private static final long serialVersionUID = -408021255097231992L;
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/10 10:17
|
||||||
|
*/
|
||||||
|
public class GroupResult extends GatewayResult<Group> {
|
||||||
|
private static final long serialVersionUID = -7882585922852119178L;
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/4/10 10:18
|
||||||
|
*/
|
||||||
|
public class GroupSecret implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 4619764526878050813L;
|
||||||
|
|
||||||
|
|
||||||
|
private String secretId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秘钥值.
|
||||||
|
*/
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秘钥名称.
|
||||||
|
*/
|
||||||
|
private String secretName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API 分组ID.
|
||||||
|
*/
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用/禁用.
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
|
||||||
|
private String expiredTime;
|
||||||
|
|
||||||
|
|
||||||
|
public String getSecretId() {
|
||||||
|
return secretId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecretId(String secretId) {
|
||||||
|
this.secretId = secretId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecretKey() {
|
||||||
|
return secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecretKey(String secretKey) {
|
||||||
|
this.secretKey = secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecretName() {
|
||||||
|
return secretName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecretName(String secretName) {
|
||||||
|
this.secretName = secretName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId(String groupId) {
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExpiredTime() {
|
||||||
|
return expiredTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiredTime(String expiredTime) {
|
||||||
|
this.expiredTime = expiredTime;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayError;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName JwtPlugin
|
||||||
|
* @Description TODO
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/3 17:15
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public class JwtPlugin extends PluginInfo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 2238976166882026848L;
|
||||||
|
//公钥对kid
|
||||||
|
private String kid;
|
||||||
|
|
||||||
|
//公钥对
|
||||||
|
private String publicKeyJson;
|
||||||
|
|
||||||
|
//token携带位置
|
||||||
|
private String tokenBaggagePosition;
|
||||||
|
|
||||||
|
//token的key值,校验参数名称
|
||||||
|
private String tokenKeyName;
|
||||||
|
|
||||||
|
//重定向地址,非必填
|
||||||
|
private String redirectUrl;
|
||||||
|
|
||||||
|
//claim参数映射关系json
|
||||||
|
private String claimMappingJson;
|
||||||
|
|
||||||
|
public String getPublicKeyJson() {
|
||||||
|
return publicKeyJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicKeyJson(String publicKeyJson) {
|
||||||
|
this.publicKeyJson = publicKeyJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenBaggagePosition() {
|
||||||
|
return tokenBaggagePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokenBaggagePosition(String tokenBaggagePosition) {
|
||||||
|
this.tokenBaggagePosition = tokenBaggagePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenKeyName() {
|
||||||
|
return tokenKeyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokenKeyName(String tokenKeyName) {
|
||||||
|
this.tokenKeyName = tokenKeyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRedirectUrl() {
|
||||||
|
return redirectUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirectUrl(String redirectUrl) {
|
||||||
|
this.redirectUrl = redirectUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKid() {
|
||||||
|
return kid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKid(String kid) {
|
||||||
|
this.kid = kid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClaimMappingJson() {
|
||||||
|
return claimMappingJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClaimMappingJson(String claimMappingJson) {
|
||||||
|
this.claimMappingJson = claimMappingJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public void check() {
|
||||||
|
super.check();
|
||||||
|
if (StringUtils.isEmpty(publicKeyJson)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "publicKeyJson");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(tokenBaggagePosition) || !(tokenBaggagePosition.equalsIgnoreCase("query") ||
|
||||||
|
tokenBaggagePosition.equalsIgnoreCase("header"))) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "tokenBaggagePosition");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(tokenKeyName)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "tokenKeyName");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(kid)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "kid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName OAuthResult
|
||||||
|
* @Description TODO
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/8 15:51
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public class OAuthResult implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 863918261072626284L;
|
||||||
|
private Boolean result;
|
||||||
|
private String payload;
|
||||||
|
|
||||||
|
public Boolean getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(Boolean result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPayload() {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPayload(String payload) {
|
||||||
|
this.payload = payload;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.gateway.context.PathRewrite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author seanlxliu
|
||||||
|
* @date 2020/5/19
|
||||||
|
*/
|
||||||
|
public class PathRewriteResult extends GatewayResult<PathRewrite> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author clarezzhang
|
||||||
|
*/
|
||||||
|
public class PathWildcardResult extends GatewayResult<PathWildcardRule> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径通配规则.
|
||||||
|
* @author clarezzhang
|
||||||
|
*/
|
||||||
|
public class PathWildcardRule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径通配规则ID.
|
||||||
|
*/
|
||||||
|
private String wildCardId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关部署组ID.
|
||||||
|
*/
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通配路径.
|
||||||
|
*/
|
||||||
|
private String wildCardPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通配方法.
|
||||||
|
*/
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关微服务ID.
|
||||||
|
*/
|
||||||
|
private String serviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关微服务名称.
|
||||||
|
*/
|
||||||
|
private String serviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关命名空间ID.
|
||||||
|
*/
|
||||||
|
private String namespaceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关命名空间名称.
|
||||||
|
*/
|
||||||
|
private String namespaceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时时间.
|
||||||
|
*/
|
||||||
|
private Integer timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径通配规则IDs.
|
||||||
|
*/
|
||||||
|
@JsonIgnore
|
||||||
|
private List<String> wildCardIds;
|
||||||
|
|
||||||
|
public String getWildCardId() {
|
||||||
|
return wildCardId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWildCardId(String wildCardId) {
|
||||||
|
this.wildCardId = wildCardId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId(String groupId) {
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServiceId() {
|
||||||
|
return serviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceId(String serviceId) {
|
||||||
|
this.serviceId = serviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespaceId() {
|
||||||
|
return namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNamespaceId(String namespaceId) {
|
||||||
|
this.namespaceId = namespaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServiceName() {
|
||||||
|
return serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceName(String serviceName) {
|
||||||
|
this.serviceName = serviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNamespaceName() {
|
||||||
|
return namespaceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNamespaceName(String namespaceName) {
|
||||||
|
this.namespaceName = namespaceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWildCardPath() {
|
||||||
|
return wildCardPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWildCardPath(String wildCardPath) {
|
||||||
|
this.wildCardPath = wildCardPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getWildCardIds() {
|
||||||
|
return wildCardIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWildCardIds(List<String> wildCardIds) {
|
||||||
|
this.wildCardIds = wildCardIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethod(String method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTimeout() {
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeout(Integer timeout) {
|
||||||
|
this.timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PathWildcardRule{" +
|
||||||
|
"wildCardId='" + wildCardId + '\'' +
|
||||||
|
", groupId='" + groupId + '\'' +
|
||||||
|
", wildCardPath='" + wildCardPath + '\'' +
|
||||||
|
", method='" + method + '\'' +
|
||||||
|
", serviceId='" + serviceId + '\'' +
|
||||||
|
", serviceName='" + serviceName + '\'' +
|
||||||
|
", namespaceId='" + namespaceId + '\'' +
|
||||||
|
", namespaceName='" + namespaceName + '\'' +
|
||||||
|
", wildCardIds=" + wildCardIds +
|
||||||
|
", timeout=" + timeout +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class PluginArgInfo implements Serializable {
|
||||||
|
private static final long serialVersionUID = -4811191577457792816L;
|
||||||
|
|
||||||
|
//插件参数id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
//插件id
|
||||||
|
private String pluginId;
|
||||||
|
|
||||||
|
//插件属性名
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
//插件属性值
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPluginId() {
|
||||||
|
return pluginId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPluginId(String pluginId) {
|
||||||
|
this.pluginId = pluginId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Object value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName PluginDetail
|
||||||
|
* @Description TODO
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/2 11:53
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public class PluginDetail extends PluginInfo {
|
||||||
|
|
||||||
|
//插件参数
|
||||||
|
private List<PluginArgInfo> pluginArgInfos;
|
||||||
|
|
||||||
|
public List<PluginArgInfo> getPluginArgInfos() {
|
||||||
|
return pluginArgInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPluginArgInfos(List<PluginArgInfo> pluginArgInfos) {
|
||||||
|
this.pluginArgInfos = pluginArgInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof PluginDetail)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PluginDetail that = (PluginDetail) o;
|
||||||
|
return Objects.equals(getId(), that.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(getPluginArgInfos());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayError;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayException;
|
||||||
|
|
||||||
|
public class PluginInfo implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4823276300296184640L;
|
||||||
|
//网关插件id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
//插件名称
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
//插件类型
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
//插件执行顺序
|
||||||
|
private Integer order;
|
||||||
|
|
||||||
|
//插件描述
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private String createdTime;
|
||||||
|
|
||||||
|
private String updatedTime;
|
||||||
|
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreatedTime() {
|
||||||
|
return createdTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedTime(String createdTime) {
|
||||||
|
this.createdTime = createdTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdatedTime() {
|
||||||
|
return updatedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedTime(String updatedTime) {
|
||||||
|
this.updatedTime = updatedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(Integer order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public void check() {
|
||||||
|
if (StringUtils.isEmpty(name)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "插件名称参数错误");
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(type)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "插件类型参数错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PluginInfo{" +
|
||||||
|
"id='" + id + '\'' +
|
||||||
|
", name='" + name + '\'' +
|
||||||
|
", type='" + type + '\'' +
|
||||||
|
", order=" + order +
|
||||||
|
", description='" + description + '\'' +
|
||||||
|
", createdTime='" + createdTime + '\'' +
|
||||||
|
", updatedTime='" + updatedTime + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author vmershen
|
||||||
|
* @date 2019/7/5 10:41
|
||||||
|
*/
|
||||||
|
public class PluginInstanceInfo implements Serializable {
|
||||||
|
private static final long serialVersionUID = -8167195405736835024L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API或分组的ID.
|
||||||
|
*/
|
||||||
|
private String scopeValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件绑定到的对象类型:group/api.
|
||||||
|
*/
|
||||||
|
private String scopeType;
|
||||||
|
|
||||||
|
//分组绑定的插件列表
|
||||||
|
private List<PluginDetail> pluginDetails;
|
||||||
|
|
||||||
|
public static long getSerialVersionUID() {
|
||||||
|
return serialVersionUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScopeValue() {
|
||||||
|
return scopeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScopeValue(String scopeValue) {
|
||||||
|
this.scopeValue = scopeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PluginDetail> getPluginDetails() {
|
||||||
|
return pluginDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPluginDetails(List<PluginDetail> pluginDetails) {
|
||||||
|
this.pluginDetails = pluginDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScopeType() {
|
||||||
|
return scopeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScopeType(String scopeType) {
|
||||||
|
this.scopeType = scopeType;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author seanlxliu
|
||||||
|
* @since 2019/9/11
|
||||||
|
*/
|
||||||
|
public class PluginInstanceInfoResult extends GatewayResult<PluginInstanceInfo> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.tencent.cloud.common.util.JacksonUtils;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayError;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayException;
|
||||||
|
|
||||||
|
public class RequestTransformerPlugin extends PluginInfo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -2682243185036956532L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数配置的JSON串.
|
||||||
|
*/
|
||||||
|
private String pluginInfo;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private RequestTransformerPluginInfo requestTransformerPluginInfo;
|
||||||
|
|
||||||
|
public String getPluginInfo() {
|
||||||
|
return pluginInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPluginInfo(String pluginInfo) {
|
||||||
|
this.pluginInfo = pluginInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RequestTransformerPluginInfo getRequestTransformerPluginInfo() {
|
||||||
|
return requestTransformerPluginInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestTransformerPluginInfo(
|
||||||
|
RequestTransformerPluginInfo requestTransformerPluginInfo) {
|
||||||
|
this.requestTransformerPluginInfo = requestTransformerPluginInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public void check() {
|
||||||
|
super.check();
|
||||||
|
if (StringUtils.isEmpty(pluginInfo)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "验证插件参数");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
requestTransformerPluginInfo = JacksonUtils.deserialize(pluginInfo, new TypeReference<RequestTransformerPluginInfo>() { });
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "验证插件格式");
|
||||||
|
}
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
for (TransformerAction action : requestTransformerPluginInfo.getActions()) {
|
||||||
|
if (action.getWeight() == null || action.getWeight() < 0) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED,
|
||||||
|
"权重值不合法:" + action.getWeight());
|
||||||
|
}
|
||||||
|
sum += action.getWeight();
|
||||||
|
}
|
||||||
|
if (sum > 100) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED,
|
||||||
|
"验证插件权重失败,当前权重总和为" + sum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.tsf.gateway.core.constant.PluginConstants;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayError;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayException;
|
||||||
|
import com.tencent.tsf.gateway.core.util.PluginUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author seanlxliu
|
||||||
|
* @since 2019/9/12
|
||||||
|
*/
|
||||||
|
public class TagPlugin extends PluginInfo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -2682243185036956532L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数配置的JSON串.
|
||||||
|
*/
|
||||||
|
private String tagPluginInfoList;
|
||||||
|
|
||||||
|
public String getTagPluginInfoList() {
|
||||||
|
return tagPluginInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTagPluginInfoList(String tagPluginInfoList) {
|
||||||
|
this.tagPluginInfoList = tagPluginInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonIgnore
|
||||||
|
public void check() {
|
||||||
|
super.check();
|
||||||
|
if (StringUtils.isEmpty(tagPluginInfoList)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_REQUIRED, "验证Tag插件参数");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.length(tagPluginInfoList) > PluginConstants.TAG_PLUGIN_INFO_LIST_LIMIT ||
|
||||||
|
!PluginUtil.predicateJsonFormat(tagPluginInfoList)) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_PARAMETER_INVALID, "验证Tag插件参数");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.model;
|
||||||
|
|
||||||
|
import com.tencent.cloud.plugin.gateway.context.Position;
|
||||||
|
import com.tencent.polaris.plugins.connector.consul.service.common.TagCondition;
|
||||||
|
|
||||||
|
public class TransformerTag extends TagCondition {
|
||||||
|
|
||||||
|
private Position tagPosition;
|
||||||
|
|
||||||
|
public Position getTagPosition() {
|
||||||
|
return tagPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTagPosition(Position tagPosition) {
|
||||||
|
this.tagPosition = tagPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TransformerTag{" +
|
||||||
|
"tagPosition=" + tagPosition +
|
||||||
|
"} " + super.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.plugin;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName GatewayPluginContext
|
||||||
|
* @Description TODO
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/9 15:44
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public class GatewayPluginFactory {
|
||||||
|
|
||||||
|
//根据插件type找对应的插件执行类
|
||||||
|
private static final Map<String, IGatewayPlugin> gatewayPluginExecutorMap = new HashMap<>();
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
//获取插件业务执行器
|
||||||
|
public static IGatewayPlugin getGatewayPluginExecutor(String type) {
|
||||||
|
if (StringUtils.isEmpty(type)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return gatewayPluginExecutorMap.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putGatewayPlugin(String type, IGatewayPlugin gatewayPlugin) {
|
||||||
|
gatewayPluginExecutorMap.put(type, gatewayPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
logger.info("gatewayPluginExecutorMap start clear");
|
||||||
|
gatewayPluginExecutorMap.clear();
|
||||||
|
logger.info("gatewayPluginExecutorMap clear success");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.plugin;
|
||||||
|
|
||||||
|
import com.tencent.tsf.gateway.core.TsfGatewayRequest;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PluginInfo;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PluginPayload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author vmershen
|
||||||
|
* 2019/7/7 17:08
|
||||||
|
*/
|
||||||
|
public interface IGatewayPlugin<T extends PluginInfo> {
|
||||||
|
|
||||||
|
default PluginPayload invoke(PluginInfo info, TsfGatewayRequest tsfGatewayRequest) {
|
||||||
|
return startUp((T) info, tsfGatewayRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginPayload startUp(T pluginInfo, TsfGatewayRequest tsfGatewayRequest);
|
||||||
|
}
|
@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.plugin;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.tencent.cloud.common.util.JacksonUtils;
|
||||||
|
import com.tencent.cloud.plugin.gateway.context.Position;
|
||||||
|
import com.tencent.polaris.api.utils.StringUtils;
|
||||||
|
import com.tencent.tsf.gateway.core.TsfGatewayRequest;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayError;
|
||||||
|
import com.tencent.tsf.gateway.core.exception.TsfGatewayException;
|
||||||
|
import com.tencent.tsf.gateway.core.model.ClaimMapping;
|
||||||
|
import com.tencent.tsf.gateway.core.model.JwtPlugin;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PluginPayload;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import shade.polaris.org.jose4j.jwa.AlgorithmConstraints;
|
||||||
|
import shade.polaris.org.jose4j.jwk.PublicJsonWebKey;
|
||||||
|
import shade.polaris.org.jose4j.jwt.JwtClaims;
|
||||||
|
import shade.polaris.org.jose4j.jwt.MalformedClaimException;
|
||||||
|
import shade.polaris.org.jose4j.jwt.consumer.InvalidJwtException;
|
||||||
|
import shade.polaris.org.jose4j.jwt.consumer.JwtConsumer;
|
||||||
|
import shade.polaris.org.jose4j.jwt.consumer.JwtConsumerBuilder;
|
||||||
|
import shade.polaris.org.jose4j.lang.JoseException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName JwtGatewayPlugin
|
||||||
|
* @Description TODO
|
||||||
|
* @Author vmershen
|
||||||
|
* @Date 2019/7/8 16:45
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public class JwtGatewayPlugin implements IGatewayPlugin<JwtPlugin> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginPayload startUp(JwtPlugin pluginInfo, TsfGatewayRequest tsfGatewayRequest) {
|
||||||
|
Map<String, String[]> parameterMap = tsfGatewayRequest.getParameterMap();
|
||||||
|
String tokenBaggagePosition = pluginInfo.getTokenBaggagePosition();
|
||||||
|
if (Position.fromString(tokenBaggagePosition) == null) {
|
||||||
|
logger.error("tokenBaggagePosition is wrong, tokenBaggagePosition: {}, tsfGatewayRequest: {}", tokenBaggagePosition, tsfGatewayRequest);
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_FAILED, "tokenBaggagePosition is wrong");
|
||||||
|
}
|
||||||
|
String idToken;
|
||||||
|
if (Position.HEADER.equals(Position.fromString(tokenBaggagePosition))) {
|
||||||
|
idToken = tsfGatewayRequest.getRequestHeader(pluginInfo.getTokenKeyName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//queryParam中取
|
||||||
|
if (parameterMap.get(pluginInfo.getTokenKeyName()) == null || parameterMap.get(pluginInfo.getTokenKeyName()).length == 0) {
|
||||||
|
logger.error("idToken is empty, tsfGatewayRequest: {}", tsfGatewayRequest);
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_FAILED, "idToken is empty");
|
||||||
|
}
|
||||||
|
idToken = parameterMap.get(pluginInfo.getTokenKeyName())[0];
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(idToken)) {
|
||||||
|
logger.error("idToken is empty, tsfGatewayRequest: {}", tsfGatewayRequest);
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_FAILED, "idToken is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取公钥
|
||||||
|
String publicKeyJson = pluginInfo.getPublicKeyJson();
|
||||||
|
PublicJsonWebKey jwk;
|
||||||
|
//验签
|
||||||
|
try {
|
||||||
|
jwk = PublicJsonWebKey.Factory.newPublicJwk(publicKeyJson);
|
||||||
|
jwk.setKeyId(pluginInfo.getKid());
|
||||||
|
}
|
||||||
|
catch (JoseException e) {
|
||||||
|
logger.error("Generate PublicKey Error", e);
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_ERROR, "Generate PublicKey Error");
|
||||||
|
}
|
||||||
|
//解析idToken, 验签
|
||||||
|
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
|
||||||
|
.setRequireExpirationTime() // the JWT must have an expiration time
|
||||||
|
.setAllowedClockSkewInSeconds(30) // allow some leeway in validating time based claims to account for clock skew
|
||||||
|
.setRequireSubject() // the JWT must have a subject claim
|
||||||
|
.setVerificationKey(jwk.getPublicKey())
|
||||||
|
.setJwsAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST, jwk.getAlgorithm()))
|
||||||
|
// ignore audience
|
||||||
|
.setSkipDefaultAudienceValidation()
|
||||||
|
.build(); // create the JwtConsumer instance
|
||||||
|
|
||||||
|
JwtClaims jwtClaims;
|
||||||
|
try {
|
||||||
|
jwtClaims = jwtConsumer.processToClaims(idToken);
|
||||||
|
}
|
||||||
|
catch (InvalidJwtException e) {
|
||||||
|
// Whether or not the JWT has expired being one common reason for invalidity
|
||||||
|
if (e.hasExpired()) {
|
||||||
|
try {
|
||||||
|
long expirationTime = e.getJwtContext()
|
||||||
|
.getJwtClaims()
|
||||||
|
.getExpirationTime()
|
||||||
|
.getValueInMillis();
|
||||||
|
String msg = String
|
||||||
|
.format("JWT expired at (%d)", expirationTime);
|
||||||
|
logger.error(msg);
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_ERROR, msg);
|
||||||
|
}
|
||||||
|
catch (MalformedClaimException e1) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.warn("Invalid JWT! tsfGatewayRequest:{}, error:{}", tsfGatewayRequest, e.getMessage());
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_ERROR, "Invalid JWT");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jwtClaims == null) {
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_AUTH_ERROR, "Invalid JWT");
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginPayload pluginPayload = new PluginPayload();
|
||||||
|
//若成功,则封装claim字段映射到后台服务
|
||||||
|
if (StringUtils.isNotEmpty(pluginInfo.getClaimMappingJson())) {
|
||||||
|
logger.info("claim json is : " + pluginInfo.getClaimMappingJson());
|
||||||
|
List<ClaimMapping> claimMappings;
|
||||||
|
try {
|
||||||
|
claimMappings = JacksonUtils.deserializeCollection(pluginInfo.getClaimMappingJson(), ClaimMapping.class);
|
||||||
|
}
|
||||||
|
catch (Throwable t) {
|
||||||
|
logger.error("[tsf-gateway] claimMappingJson deserialize data to claimMappings occur exception.", t);
|
||||||
|
throw new TsfGatewayException(TsfGatewayError.GATEWAY_SERIALIZE_ERROR,
|
||||||
|
"claimMappingJson deserialize data to claimMappings occur exception");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String[]> paramsMap = new HashMap<>();
|
||||||
|
Map<String, String> headerParamsMap = new HashMap<>();
|
||||||
|
for (ClaimMapping claimMapping : claimMappings) {
|
||||||
|
try {
|
||||||
|
String claimValue = jwtClaims.getStringClaimValue(claimMapping.getParameterName());
|
||||||
|
if (!StringUtils.isEmpty(claimValue)) {
|
||||||
|
if (Position.HEADER.equals(Position.fromString(claimMapping.getLocation()))) {
|
||||||
|
headerParamsMap.put(claimMapping.getMappingParameterName(), claimValue);
|
||||||
|
}
|
||||||
|
else if (Position.QUERY.equals(Position.fromString(claimMapping.getLocation()))) {
|
||||||
|
paramsMap.put(claimMapping.getMappingParameterName(), new String[] {claimValue});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MalformedClaimException e) {
|
||||||
|
logger.warn("Claim mapping error, parameterName: " + claimMapping.getParameterName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pluginPayload.setRequestHeaders(headerParamsMap);
|
||||||
|
pluginPayload.setParameterMap(paramsMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pluginPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.plugin;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
|
||||||
|
import com.tencent.tsf.gateway.core.TsfGatewayRequest;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PluginPayload;
|
||||||
|
import com.tencent.tsf.gateway.core.model.RequestTransformerPlugin;
|
||||||
|
import com.tencent.tsf.gateway.core.util.PluginUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
public class ReqTransformerGatewayPlugin implements IGatewayPlugin<RequestTransformerPlugin> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginPayload startUp(RequestTransformerPlugin plugin, TsfGatewayRequest tsfGatewayRequest) {
|
||||||
|
PluginPayload payload = new PluginPayload();
|
||||||
|
return PluginUtil.doRequestTransformer(plugin.getRequestTransformerPluginInfo(), tsfGatewayRequest, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.plugin;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
|
||||||
|
import com.tencent.tsf.gateway.core.TsfGatewayRequest;
|
||||||
|
import com.tencent.tsf.gateway.core.model.PluginPayload;
|
||||||
|
import com.tencent.tsf.gateway.core.model.TagPlugin;
|
||||||
|
import com.tencent.tsf.gateway.core.util.PluginUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author seanlxliu
|
||||||
|
* @since 2019/9/12
|
||||||
|
*/
|
||||||
|
public class TagGatewayPlugin implements IGatewayPlugin<TagPlugin> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||||
|
|
||||||
|
public TagGatewayPlugin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginPayload startUp(TagPlugin tagPlugin, TsfGatewayRequest tsfGatewayRequest) {
|
||||||
|
PluginPayload payload = new PluginPayload();
|
||||||
|
return PluginUtil.transferToTag(tagPlugin.getTagPluginInfoList(), tsfGatewayRequest, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: vmershen
|
||||||
|
* @description:
|
||||||
|
* @create: 2020-05-23 17:41
|
||||||
|
**/
|
||||||
|
public final class CookieUtil {
|
||||||
|
|
||||||
|
private CookieUtil() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void buildCookie(StringBuilder cookieStringBuilder, Map<String, String> requestCookieMap) {
|
||||||
|
if (!CollectionUtils.isEmpty(requestCookieMap)) {
|
||||||
|
for (Map.Entry<String, String> cookieEntry : requestCookieMap.entrySet()) {
|
||||||
|
if (cookieStringBuilder.length() == 0) {
|
||||||
|
cookieStringBuilder.append(cookieEntry.getKey() + "=" + cookieEntry.getValue());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cookieStringBuilder.append("; ");
|
||||||
|
cookieStringBuilder.append(cookieEntry.getKey() + "=" + cookieEntry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.util;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import shade.polaris.org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/2/26 16:20
|
||||||
|
*/
|
||||||
|
public final class IdGenerator {
|
||||||
|
|
||||||
|
private IdGenerator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String uuid() {
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
return uuid.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generate() {
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
return compressedUUID(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateId(String prefix) {
|
||||||
|
return generateId(prefix, '#');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateId(String prefix, char splitor) {
|
||||||
|
String uuid = generate();
|
||||||
|
return prefix + splitor + uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String compressedUUID(UUID uuid) {
|
||||||
|
byte[] byUuid = new byte[16];
|
||||||
|
long least = uuid.getLeastSignificantBits();
|
||||||
|
long most = uuid.getMostSignificantBits();
|
||||||
|
long2bytes(most, byUuid, 0);
|
||||||
|
long2bytes(least, byUuid, 8);
|
||||||
|
return Base64.encodeBase64URLSafeString(byUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void long2bytes(long value, byte[] bytes, int offset) {
|
||||||
|
for (int i = 7; i > -1; --i) {
|
||||||
|
bytes[offset++] = (byte) ((int) (value >> 8 * i & 255L));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String compress(String uuidString) {
|
||||||
|
UUID uuid = UUID.fromString(uuidString);
|
||||||
|
return compressedUUID(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String uncompress(String compressedUuid) {
|
||||||
|
if (compressedUuid.length() != 22) {
|
||||||
|
throw new IllegalArgumentException("Invalid uuid!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte[] byUuid = Base64.decodeBase64(compressedUuid + "==");
|
||||||
|
long most = bytes2long(byUuid, 0);
|
||||||
|
long least = bytes2long(byUuid, 8);
|
||||||
|
UUID uuid = new UUID(most, least);
|
||||||
|
return uuid.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long bytes2long(byte[] bytes, int offset) {
|
||||||
|
long value = 0L;
|
||||||
|
|
||||||
|
for (int i = 7; i > -1; --i) {
|
||||||
|
value |= ((long) bytes[offset++] & 255L) << 8 * i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.core.util;
|
||||||
|
|
||||||
|
import com.tencent.tsf.gateway.core.constant.TsfAlgType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import shade.polaris.org.apache.commons.codec.binary.Base64;
|
||||||
|
import shade.polaris.org.apache.commons.codec.digest.HmacUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kysonli
|
||||||
|
* 2019/2/26 16:06
|
||||||
|
*/
|
||||||
|
public final class TsfSignUtil {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TsfSignUtil.class);
|
||||||
|
|
||||||
|
|
||||||
|
private TsfSignUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成签名.
|
||||||
|
*
|
||||||
|
* @param nonce 随机字符串
|
||||||
|
* @param secretId 秘钥ID
|
||||||
|
* @param secretKey 秘钥值
|
||||||
|
* @param algType 签名算法 {@link TsfAlgType}
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static String generate(String nonce, String secretId, String secretKey, TsfAlgType algType) {
|
||||||
|
String digestValue = nonce + secretId + secretKey;
|
||||||
|
byte[] serverSignBytes;
|
||||||
|
switch (algType) {
|
||||||
|
case HMAC_MD5:
|
||||||
|
serverSignBytes = HmacUtils.hmacMd5(secretKey, digestValue);
|
||||||
|
break;
|
||||||
|
case HMAC_SHA_1:
|
||||||
|
serverSignBytes = HmacUtils.hmacSha1(secretKey, digestValue);
|
||||||
|
break;
|
||||||
|
case HMAC_SHA_256:
|
||||||
|
serverSignBytes = HmacUtils.hmacSha256(secretKey, digestValue);
|
||||||
|
break;
|
||||||
|
case HMAC_SHA_512:
|
||||||
|
serverSignBytes = HmacUtils.hmacSha512(secretKey, digestValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("不支持的鉴权算法: " + algType);
|
||||||
|
}
|
||||||
|
String signValue = Base64.encodeBase64String(serverSignBytes);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("签名明文:{},签名密文:{}", digestValue, signValue);
|
||||||
|
}
|
||||||
|
return signValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tencent. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*
|
||||||
|
* 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 com.tencent.tsf.gateway.scg;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatible with old versions TSF SDK.
|
||||||
|
*
|
||||||
|
* @author Shedfree Wu
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTsfGlobalFilter implements GlobalFilter, Ordered {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
|
if (shouldFilter(exchange, chain)) {
|
||||||
|
return doFilter(exchange, chain);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return chain.filter(exchange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
abstract public int getOrder();
|
||||||
|
|
||||||
|
abstract public boolean shouldFilter(ServerWebExchange exchange, GatewayFilterChain chain);
|
||||||
|
|
||||||
|
abstract public Mono<Void> doFilter(ServerWebExchange exchange, GatewayFilterChain chain);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue