zuul 验证,重写返回报文,解析gzip压缩response,使用案例

news/2024/11/14 7:46:37/文章来源:https://www.cnblogs.com/isyysblog/p/18542388

业务是调用另一个平台API,用他们的接口能力实现一些功能。

真正请求前的filter,我把一些请求前的验证和日志入库放在了这里。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.iMagine.iMagine_common.exception.MyException;
import com.iMagine.iMagine_common.result.CommonResult;
import com.iMagine.iMagine_common.utils.UUIDUtil;
import com.iMagine.iMagine_mapper.entity.User;
import com.iMagine.iMagine_pro.constant.ErrorEnum;
import com.iMagine.iMagine_pro.constant.SysConstant;
import com.iMagine.iMagine_pro.feign.body.AiServerResponseBody;
import com.iMagine.iMagine_pro.service.MjToAiService;
import com.iMagine.iMagine_pro.utils.TokenUtil;
import com.iMagine.iMagine_pro.utils.ZuulParameterUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.util.HTTPRequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StreamUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;/*** Zuul过滤器,必须继承ZuulFilter父类。* 当前类型的对象必须交由Spring容器管理。使用@Component注解描述。* 继承父类后,必须实现父类中定义的4个抽象方法。* shouldFilter、 run、 filterType、 filterOrder*/
@Component
@Slf4j
public class LoggerPostFilter extends ZuulFilter {@Autowiredprivate MjToAiService mjToAiService;/*** 返回boolean类型。代表当前filter是否生效。* 默认值为false。* 返回true代表开启filter。*/@Overridepublic boolean shouldFilter() {return true;}/*** run方法就是过滤器的具体逻辑。* return 可以返回任意的对象,当前实现忽略。(spring-cloud-zuul官方解释)* 直接返回null即可。*/@Overridepublic Object run() {log.info("LoggerPostFilter任务处理开始...");// 获取zuul提供的上下文对象RequestContext context = RequestContext.getCurrentContext();HttpServletRequest request = context.getRequest();String requestUrl = request.getRequestURI();log.info("requestUrl:{}",requestUrl);//创建统一UUIDString uuid = UUIDUtil.getUUID();ConcurrentHashMap<String,Object> params = new ConcurrentHashMap<>(4);HttpServletResponse response = context.getResponse();params.put("uuid",uuid);params.put("date",new Date());try {InputStream responseDataStream = context.getResponseDataStream();String contentEncoding = context.getZuulRequestHeaders().get("accept-encoding");if (responseDataStream != null && "gzip".equals(contentEncoding) && context.getResponseGZipped()) {responseDataStream  = new GZIPInputStream(context.getResponseDataStream());}else{responseDataStream = context.getResponseDataStream();}String body = StreamUtils.copyToString(responseDataStream, Charset.forName("UTF-8"));//根据code值替换提示内容JSONObject requestJson = JSON.parseObject(body);log.info("requestJson:{}",requestJson);// 处理一些返回的数据到paramsparams.put("code",response.getStatus());params.put("returnMj",body);if(!ObjectUtils.isEmpty(response) && response.getStatus() == 200){//设置接口记录为执行中状态params.put("operationResult",SysConstant.STATUS_TWO);//收集一些埋点需要的参数handlerSomething(body,params);}else{//设置接口记录为失败状态params.put("operationResult",SysConstant.STATUS_ONE);//根据code替换返回前端的提示信息log.error("返回异常报文{}",JSON.toJSONString(requestJson));String code = "";if(ObjectUtils.isEmpty(requestJson)){code = String.valueOf(response.getStatus());requestJson = new JSONObject();requestJson.put("code",code);}else{code = requestJson.get("code").toString();}String reason = ErrorEnum.ErrorEnumType.getModelUploadType(code);if(StringUtils.isBlank(reason)) reason = ErrorEnum.ErrorEnumType.getModelUploadType("1000");requestJson.put("reason",reason);}//对请求的入参进行筛选记录log.info("开始调用handlerRequest...,{}",params);handlerRequest(context,params);response.setCharacterEncoding("UTF-8");response.setContentType("application/json");// 将修改后的内容重新压缩为 GZIP 格式if (responseDataStream != null && "gzip".equals(contentEncoding) && context.getResponseGZipped()) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);gzipOutputStream.write(JSON.toJSONString(CommonResult.success(requestJson)).getBytes("UTF-8"));gzipOutputStream.close();// 设置新的压缩后的响应数据流context.setResponseDataStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));}else{// 设置新的压缩后的响应数据流context.setResponseBody(JSON.toJSONString(CommonResult.success(requestJson)));}} catch (Exception e) {log.error("请求异常!{}",e);// 异常数据记录User user = TokenUtil.getUserByToken();mjToAiService.handlerException(uuid,e,DateUtils.parseDate(params.get("date")+""),user,context.getRequest());throw new MyException("请求异常!");}log.info("LoggerPostFilter任务处理结束!");return null;}/*** 收集一些埋点需要的参数* @param body 接口返回的报文* @param params 需要存储的集合*/private void handlerSomething( String body,ConcurrentHashMap<String,Object> params){String paramString = body.replaceAll(" ", "").replaceAll(System.getProperty("line.separator"), "");JSONObject responseBody = JSON.parseObject(paramString);if (!ObjectUtils.isEmpty(responseBody)){log.info("【返回参数】{}" , responseBody);//不确定接口返回的是jobid  还是  id//如果是正常返回,则覆盖uuid,届时用来对回调接口做关联if (ObjectUtils.isEmpty(responseBody.get("id"))){params.put("uuid",responseBody.get("jobid"));}else{params.put("uuid",responseBody.get("id"));}}}/*** 对请求的入参进行筛选记录* 统一记录生图埋点数据* @param context*/private void handlerRequest(RequestContext context,ConcurrentHashMap<String,Object> params){//对MJ相关生图接口做埋点log.info("对MJ相关生图接口做埋点...");HttpServletRequest request = context.getRequest();String requestUrl = request.getRequestURI();Date dateHandler = DateUtils.parseDate(String.valueOf(params.get("date")));JSONObject requestMap = JSON.parseObject(JSON.toJSONString(ZuulParameterUtil.getRequestParams(context)));User user = TokenUtil.getUserByToken();try {log.info("接口url:{},参数列表:{}", requestUrl,requestMap);String clientIp = TokenUtil.getRequest().getRemoteHost();//1.请求悠船文生图接口//2.封装AiServerResponseBodyAiServerResponseBody result = mjToAiService.handlerSpecial(Integer.valueOf(params.get("code")+""),params.get("returnMj") + "",params.get("uuid")+"",dateHandler,user);log.info("AiServerResponseBody 存入数据{}",result);//3.异步插入调用记录img_ai_record,日活记录img_dau_record,异步处理mjToAiService.addRecord(params.get("returnMj") + "",Integer.valueOf(params.get("code")+""),JSON.toJSONString(requestMap),params.get("uuid")+"",dateHandler,request.getRequestURI(),params.get("operationResult")+"",user,clientIp,1);log.info("diffusion uuid:{}, result:{}", params.get("uuid")+"", result);} catch (Exception e) {//5.处理异常log.error("handlerRequest异常:{}",e);mjToAiService.handlerException(params.get("uuid")+"",e,dateHandler,user,request);}}/*** 过滤器的类型。可选值有:* pre - 前置过滤* route - 路由后过滤* error - 异常过滤* post - 远程服务调用后过滤*/@Overridepublic String filterType() {return "post";}/*** 同种类的过滤器的执行顺序。* 按照返回值的自然升序执行。*/@Overridepublic int filterOrder() {return 2;}
}

请求回来拦截的filter,解析返回的报文,分析数据和业务处理,最终gzip重构返回报文。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.iMagine.iMagine_common.exception.MyException;
import com.iMagine.iMagine_common.result.CommonResult;
import com.iMagine.iMagine_common.utils.UUIDUtil;
import com.iMagine.iMagine_mapper.entity.User;
import com.iMagine.iMagine_pro.constant.ErrorEnum;
import com.iMagine.iMagine_pro.constant.SysConstant;
import com.iMagine.iMagine_pro.feign.body.AiServerResponseBody;
import com.iMagine.iMagine_pro.service.MjToAiService;
import com.iMagine.iMagine_pro.utils.TokenUtil;
import com.iMagine.iMagine_pro.utils.ZuulParameterUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.util.HTTPRequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
* Zuul过滤器,必须继承ZuulFilter父类。
* 当前类型的对象必须交由Spring容器管理。使用@Component注解描述。
* 继承父类后,必须实现父类中定义的4个抽象方法。
* shouldFilter、 run、 filterType、 filterOrder
*/
@Component
@Slf4j
public class LoggerPostFilter extends ZuulFilter {

@Autowired
private MjToAiService mjToAiService;

/**
* 返回boolean类型。代表当前filter是否生效。
* 默认值为false。
* 返回true代表开启filter。
*/
@Override
public boolean shouldFilter() {
return true;
}

/**
* run方法就是过滤器的具体逻辑。
* return 可以返回任意的对象,当前实现忽略。(spring-cloud-zuul官方解释)
* 直接返回null即可。
*/
@Override
public Object run() {
log.info("LoggerPostFilter任务处理开始...");
// 获取zuul提供的上下文对象
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String requestUrl = request.getRequestURI();
log.info("requestUrl:{}",requestUrl);
//创建统一UUID
String uuid = UUIDUtil.getUUID();
ConcurrentHashMap<String,Object> params = new ConcurrentHashMap<>(4);
HttpServletResponse response = context.getResponse();
params.put("uuid",uuid);
params.put("date",new Date());
try {
InputStream responseDataStream = context.getResponseDataStream();
//这里的accept-encoding 看源码会自动转为小写
String contentEncoding = context.getZuulRequestHeaders().get("accept-encoding");
if (responseDataStream != null && "gzip".equals(contentEncoding) && context.getResponseGZipped()) {
responseDataStream = new GZIPInputStream(context.getResponseDataStream());
}else{
responseDataStream = context.getResponseDataStream();
}
String body = StreamUtils.copyToString(responseDataStream, Charset.forName("UTF-8"));
//根据code值替换提示内容
JSONObject requestJson = JSON.parseObject(body);
log.info("requestJson:{}",requestJson);
// 处理一些返回的数据到params
params.put("code",response.getStatus());
params.put("returnMj",body);
if(!ObjectUtils.isEmpty(response) && response.getStatus() == 200){
//设置接口记录为执行中状态
params.put("operationResult",SysConstant.STATUS_TWO);
//收集一些埋点需要的参数
handlerSomething(body,params);
}else{
//设置接口记录为失败状态
params.put("operationResult",SysConstant.STATUS_ONE);
//根据code替换返回前端的提示信息
log.error("返回异常报文{}",JSON.toJSONString(requestJson));
String code = "";
if(ObjectUtils.isEmpty(requestJson)){
code = String.valueOf(response.getStatus());
requestJson = new JSONObject();
requestJson.put("code",code);
}else{
code = requestJson.get("code").toString();
}
String reason = ErrorEnum.ErrorEnumType.getModelUploadType(code);
if(StringUtils.isBlank(reason)) reason = ErrorEnum.ErrorEnumType.getModelUploadType("1000");
requestJson.put("reason",reason);
}
//对请求的入参进行筛选记录
log.info("开始调用handlerRequest...,{}",params);
handlerRequest(context,params);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
// 将修改后的内容重新压缩为 GZIP 格式
if (responseDataStream != null && "gzip".equals(contentEncoding) && context.getResponseGZipped()) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
gzipOutputStream.write(JSON.toJSONString(CommonResult.success(requestJson)).getBytes("UTF-8"));
gzipOutputStream.close();
// 设置新的压缩后的响应数据流
context.setResponseDataStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
}else{
// 设置新的压缩后的响应数据流
context.setResponseBody(JSON.toJSONString(CommonResult.success(requestJson)));
}
} catch (Exception e) {
log.error("请求异常!{}",e);
// 异常数据记录
User user = TokenUtil.getUserByToken();
mjToAiService.handlerException(uuid,e,DateUtils.parseDate(params.get("date")+""),user,context.getRequest());
throw new MyException("请求异常!");
}
log.info("LoggerPostFilter任务处理结束!");
return null;
}

/**
* 收集一些埋点需要的参数
* @param body 接口返回的报文
* @param params 需要存储的集合
*/
private void handlerSomething( String body,ConcurrentHashMap<String,Object> params){
String paramString = body.replaceAll(" ", "").replaceAll(System.getProperty("line.separator"), "");
JSONObject responseBody = JSON.parseObject(paramString);
if (!ObjectUtils.isEmpty(responseBody)){
log.info("【返回参数】{}" , responseBody);
//不确定接口返回的是jobid 还是 id
//如果是正常返回,则覆盖uuid,届时用来对回调接口做关联
if (ObjectUtils.isEmpty(responseBody.get("id"))){
params.put("uuid",responseBody.get("jobid"));
}else{
params.put("uuid",responseBody.get("id"));
}
}
}

/**
* 对请求的入参进行筛选记录
* 统一记录生图埋点数据
* @param context
*/
private void handlerRequest(RequestContext context,ConcurrentHashMap<String,Object> params){
//对MJ相关生图接口做埋点
log.info("对MJ相关生图接口做埋点...");
HttpServletRequest request = context.getRequest();
String requestUrl = request.getRequestURI();
Date dateHandler = DateUtils.parseDate(String.valueOf(params.get("date")));
JSONObject requestMap = JSON.parseObject(JSON.toJSONString(ZuulParameterUtil.getRequestParams(context)));
User user = TokenUtil.getUserByToken();
try {
log.info("接口url:{},参数列表:{}", requestUrl,requestMap);
String clientIp = TokenUtil.getRequest().getRemoteHost();
//1.请求悠船文生图接口
//2.封装AiServerResponseBody
AiServerResponseBody result = mjToAiService.handlerSpecial(
Integer.valueOf(params.get("code")+""),
params.get("returnMj") + "",
params.get("uuid")+"",
dateHandler,user);
log.info("AiServerResponseBody 存入数据{}",result);
//3.异步插入调用记录img_ai_record,日活记录img_dau_record,异步处理
mjToAiService.addRecord(params.get("returnMj") + "",Integer.valueOf(params.get("code")+""),
JSON.toJSONString(requestMap),params.get("uuid")+"",dateHandler,request.getRequestURI(),
params.get("operationResult")+"",user,clientIp,1);
log.info("diffusion uuid:{}, result:{}", params.get("uuid")+"", result);
} catch (Exception e) {
//5.处理异常
log.error("handlerRequest异常:{}",e);
mjToAiService.handlerException(params.get("uuid")+"",e,dateHandler,user,request);
}
}

/**
* 过滤器的类型。可选值有:
* pre - 前置过滤
* route - 路由后过滤
* error - 异常过滤
* post - 远程服务调用后过滤
*/
@Override
public String filterType() {
return "post";
}

/**
* 同种类的过滤器的执行顺序。
* 按照返回值的自然升序执行。
*/
@Override
public int filterOrder() {

return 2;
}
}

  

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/832389.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Blender 常用材质节点

渲染模型 PBR全称:Physically Based Rendering (基于物理的渲染)BRDF全称:Bidirectional Reflectance Distribution Function (双向散射分布函数)BSDF包含BRDF(反射)和BTDF(透射)功能区介绍 伪用户 如果材质没有任何模型引用,关掉blender时,该材质会被自动删除,要想不…

Linux搭建FTP服务器配置

一、概念 1.1介绍 FTP:File transfer protocol 文件传输协议 端口 TCP21:命令 TCP20:数据 1.2原理 默认采用被动模式 被动模式FTP 为了解决服务器发起到客户的连接的问题,人们开发了一种不同的FTP连接方式。这就是所谓的被动方式,或者叫做PASV,当客户端通知服务器它处于被动…

基于RBAC做数据权限

在RBAC模型下,系统只会验证用户A是否属于角色RoleX,而不会判断用户A是否能访问只属于用户B的数据DataB。这种问题我们称之为“水平权限管理问题”。 数据权限 数据规则 比如我们系统的商机数据,需要从下面几个维度来控制数据访问权限。 销售人员只能看自己的数据; 各大区的…

Free5GC源码研究(9) - PCF研究(下)

前文再续书接上一回,继续研究Free5GC中所实现的PCF的另外两组服务:SMPolicy和PolicyAuthorizationSMPolicy PCF中与SMF的交互,对session的控制有着很重的的分量,甚至连TS23.503中对与Policy Control的定义都是指PCF指示SMF去控制QoS流的过程。Policy control: The process …

遥感大数据智能分析与应用

在数字化和信息化时代,遥感技术已经成为获取地球表面信息的重要手段。随着遥感数据量的激增,如何高效、智能地分析和应用这些数据,成为了一个亟待解决的问题。本文将探讨遥感大数据智能分析的现状与未来趋势。遥感大数据的挑战与机遇遥感数据正以前所未有的速度增长,这些数…

GMES101 作业一

一共就是求两个矩阵一个旋转矩阵一个投射矩阵 旋转矩阵 旋转矩阵还能第一时间反应过来去找公式 投射矩阵 投射矩阵就完全不记得了,又去看了一遍视频,终于完全理解了投射矩阵究竟是个啥意思 原来还要自己算\[ M_{persp\to ortho}= \begin{matrix} n&0&0&0 \\ 0&am…

waypoint常常被翻译成航路点

参考资料:2023-端到端自动驾驶系统研究综述-陈妍妍 2024-EMMA: End-to-End Multimodal Model for Autonomous Driving

作业四

作业一 要求: ▪ 熟练掌握 Selenium 查找 HTML 元素、爬取 Ajax 网页数据、等待 HTML 元素等内 容。 ▪ 使用 Selenium 框架+ MySQL 数据库存储技术路线爬取“沪深 A 股”、“上证 A 股”、 “深证 A 股”3 个板块的股票数据信息。 o 候选网站:东方财富网: http://quote.eas…

ATE测试 - STDF文件分析 - Excel报表格式探讨

1、转换对象:STDF文件 2、适用人员:TE 或 解决方案人员 或 需要对测试项TestItem原始测试值进行分析的 2、Excel格式:如下示意图4、局限性:Excel一个sheet中,列数最大不能超过16384列,行数最大不能超过1048576行,因此这种格式对于超过16384颗Die的文件就无法生成Excel文…

实验一:百度机器翻译SDK实验(2024.11.15日完成)

实验一:百度机器翻译SDK实验(2024.11.15日完成)任务一:下载配置百度翻译Java相关库及环境(占10%)。任务二:了解百度翻译相关功能并进行总结,包括文本翻译-通用版和文本翻译-词典版(占20%)。任务三:完成百度翻译相关功能代码并测试调用,要求可以实现中文翻译成英文,…

2024.11.12 NOIP模拟 - 模拟赛记录

Preface 一套烂题。 T1 一眼搬的 CF(赛后十秒就找到原题了),只搬 idea 就算了,根本不设置部分分,大样例给的更是一坨(数据范围给的 \(10^{15}\),1 2 10 72 121 算什么大样例?),甚至最后的题解都是直接复制的洛谷。 T2 稍好,除了实数运算稍微恶心一点,其它都没什么。…

数据采集与融合技术作业四

目录作业①实验要求及结果心得体会作业②实验要求及结果心得体会作业③实验要求及结果心得体会码云连接作业① 实验要求及结果要求 熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容。 使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证…