
com.taotao.cloud.openfeign.feign.FeignRequestInterceptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of taotao-cloud-starter-openfeign Show documentation
Show all versions of taotao-cloud-starter-openfeign Show documentation
taotao-cloud-starter-openfeign
/*
* Copyright (c) 2020-2030, Shuigedeng ([email protected] & https://blog.taotaocloud.top/).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.taotao.cloud.openfeign.feign;
import static com.taotao.cloud.common.constant.CommonConstant.BLANK;
import static com.taotao.cloud.common.utils.lang.StringUtils.NEW_LINE;
import com.taotao.cloud.common.constant.CommonConstant;
import com.taotao.cloud.common.constant.ContextConstant;
import com.taotao.cloud.common.holder.TenantContextHolder;
import com.taotao.cloud.common.holder.TraceContextHolder;
import com.taotao.cloud.common.holder.VersionContextHolder;
import com.taotao.cloud.common.utils.common.IdGeneratorUtils;
import com.taotao.cloud.common.utils.servlet.TraceUtils;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* 假装请求拦截器
*
* @author shuigedeng
* @version 2023.07
* @since 2023-07-06 09:26:57
*/
public class FeignRequestInterceptor implements RequestInterceptor {
protected List requestHeaders = new ArrayList<>();
public static final List HEADER_NAME_LIST = Arrays.asList(
ContextConstant.JWT_KEY_TENANT,
ContextConstant.JWT_KEY_SUB_TENANT,
ContextConstant.JWT_KEY_USER_ID,
ContextConstant.JWT_KEY_ACCOUNT,
ContextConstant.JWT_KEY_NAME,
ContextConstant.GRAY_VERSION,
ContextConstant.TRACE_ID_HEADER,
"X-Real-IP",
"x-forwarded-for");
@PostConstruct
public void initialize() {
requestHeaders.add(CommonConstant.TTC_USER_ID_HEADER);
requestHeaders.add(CommonConstant.TTC_USER_NAME_HEADER);
requestHeaders.add(CommonConstant.TTC_USER_ROLE_HEADER);
requestHeaders.add(CommonConstant.TTC_VERSION_HEADER);
}
@Override
public void apply(RequestTemplate template) {
Map> headers = template.headers();
Set feignHeaderNames = headers.keySet();
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// job 类型的任务,可能没有Request
if (requestAttributes != null) {
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
// RequestContextHolder.setRequestAttributes(attributes, true);
HttpServletRequest request = attributes.getRequest();
Enumeration headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
if (feignHeaderNames.contains(headerName)) {
continue;
}
String values = request.getHeader(headerName);
// 跳过content-length值的复制。因为服务之间调用需要携带一些用户信息之类的
// 所以实现了Feign的RequestInterceptor拦截器复制请求头,复制的时候是所有头都复制的,可能导致Content-length长度跟body不一致
// @see https://blog.csdn.net/qq_39986681/article/details/107138740
if (StringUtils.equalsIgnoreCase(headerName, HttpHeaders.CONTENT_LENGTH)) {
continue;
}
// 解决 UserAgent 信息被修改后,AppleWebKit/537.36 (KHTML,like Gecko)部分存在非法字符的问题
if (StringUtils.equalsIgnoreCase(headerName, HttpHeaders.USER_AGENT)) {
values = StringUtils.replace(values, NEW_LINE, String.valueOf(BLANK));
}
template.header(headerName, values);
}
}
String token = extractHeaderToken(request);
if (StrUtil.isEmpty(token)) {
token = request.getParameter(CommonConstant.ACCESS_TOKEN);
}
if (StrUtil.isNotEmpty(token)) {
addHeader(template, CommonConstant.TTC_TOKEN_HEADER, CommonConstant.BEARER_TYPE + " " + token);
}
}
// 传递client 传递access_token,无网络隔离时需要传递
String tenant = TenantContextHolder.getTenant();
if (StrUtil.isBlank(tenant)) {
tenant = TraceUtils.getTenantId();
}
addHeader(template, CommonConstant.TTC_TENANT_ID, StrUtil.isNotBlank(tenant) ? tenant : "1");
// 传递日志traceId
String traceId = TraceContextHolder.getTraceId();
if (StrUtil.isBlank(traceId)) {
traceId = TraceUtils.getTraceId();
}
addHeader(
template,
CommonConstant.TTC_TRACE_ID,
StrUtil.isNotBlank(traceId) ? traceId : IdGeneratorUtils.getIdStr());
// 传递version
String version = VersionContextHolder.getVersion();
if (StrUtil.isBlank(version)) {
version = TraceUtils.getVersion();
}
addHeader(template, CommonConstant.TTC_REQUEST_VERSION, StrUtil.isNotBlank(version) ? version : "");
// 服务内部inner
addHeader(template, CommonConstant.TTC_FROM_INNER, "true");
}
/**
* 解析head中的token
*
* @param request request
*/
private String extractHeaderToken(HttpServletRequest request) {
Enumeration headers = request.getHeaders(CommonConstant.TTC_TOKEN_HEADER);
while (headers.hasMoreElements()) {
String value = headers.nextElement();
if (value.startsWith(CommonConstant.BEARER_TYPE)) {
String authHeaderValue =
value.substring(CommonConstant.BEARER_TYPE.length()).trim();
int commaIndex = authHeaderValue.indexOf(',');
if (commaIndex > 0) {
authHeaderValue = authHeaderValue.substring(0, commaIndex);
}
return authHeaderValue;
}
}
return null;
}
private void addHeader(RequestTemplate template, String headerName, String headerValue) {
Map> headers = template.headers();
if (StrUtil.isBlank(headerName) || StrUtil.isBlank(headerValue)) {
return;
}
if (headers.containsKey(headerName)) {
Collection headerValues = headers.get(headerName);
if (CollUtil.isEmpty(headerValues)) {
template.header(headerName, headerValue);
}
if (!headerValues.contains(headerValue)) {
template.header(headerName, headerValue);
}
} else {
template.header(headerName, headerValue);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy