com.logicbus.backend.message.YamlMessage Maven / Gradle / Ivy
package com.logicbus.backend.message;
import com.alogic.idnote.IdNote;
import com.alogic.idnote.IdNoteFactory;
import com.alogic.idnote.IdNoteGroup;
import com.anysoft.util.IOTools;
import com.anysoft.util.JsonTools;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.Settings;
import com.anysoft.util.compress.Compressor;
import com.anysoft.util.compress.compressor.GZIP;
import com.jayway.jsonpath.JsonPath;
import com.logicbus.backend.Context;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
/**
* 基于YAML的Message
*
* @since 1.6.12.27 [20190403 duanyy]
*
* @version 1.6.13.21 [20201021 duanyy]
* - 支持gzip压缩
*/
public class YamlMessage implements Message {
protected static final Logger logger = LoggerFactory.getLogger(JsonMessage.class);
protected static String formContentType = "application/x-www-form-urlencoded";
protected static IdNoteGroup idnote = null;
protected static boolean hostMask = true;
protected static ThreadLocal yamlLocal = new ThreadLocal(){
protected Yaml initialValue() {
return new Yaml();
};
};
private static Compressor gzipCompressor = new GZIP();
private static boolean gzipSupport = false;
/**
* gzip开启的报文长度
*/
private static int gzipEnableLength = 1024;
static {
gzipSupport = PropertiesConstants.getBoolean(Settings.get(),"http.yaml.gzip",gzipSupport);
gzipEnableLength = PropertiesConstants.getInt(Settings.get(),"http.gzip.length",gzipEnableLength);
formContentType = Settings.get().GetValue("http.formContentType",
"application/x-www-form-urlencoded");
hostMask = PropertiesConstants.getBoolean(Settings.get(),"servant.hostmask",hostMask);
idnote = IdNoteFactory.get(PropertiesConstants.getString(Settings.get(), "servant.code.group", "servant.code"));
}
private String contentType = "text/plain;charset=utf-8";
/**
* Json结构的根节点
*/
protected Map root = null;
private long contentLength = 0;
private String outputPath = "";
private boolean isGzipEnable(Context ctx,String header){
if (!gzipSupport) return false;
String gzip = ctx.getRequestHeader(header);
return StringUtils.isNotEmpty(gzip)?gzip.equalsIgnoreCase("gzip"):false;
}
public void setOutputPath(String path){
this.outputPath = path;
}
protected static String getHost(String host){
return hostMask ? host.replaceFirst("\\d{1,}\\.\\d{1,}\\.\\d{1,}\\.","*.*.*."):host;
}
@Override
@SuppressWarnings("unchecked")
public void init(Context ctx) {
boolean gzipEnable = isGzipEnable(ctx,"Content-Encoding");
String data = null;
{
byte [] inputData = ctx.getRequestRaw();
if (inputData != null){
try {
if (gzipEnable && inputData.length > 0){
inputData = gzipCompressor.decompress(inputData);
}
data = new String(inputData,ctx.getEncoding());
}catch (Exception ex){
}
}
}
if (data == null){
//当客户端通过form来post的时候,Message不去读取输入流。
String _contentType = ctx.getRequestContentType();
if (_contentType == null || !_contentType.startsWith(formContentType)){
InputStream in = null;
try {
in = ctx.getInputStream();
if (gzipEnable && in.available() > 0){
in = gzipCompressor.getInputStream(in);
}
data = Context.readFromInputStream(in, ctx.getEncoding());
}catch (Exception ex){
logger.error("Error when reading data from inputstream",ex);
}finally{
IOTools.close(in);
}
}
}
if (data != null && data.length() > 0){
contentLength += data.getBytes().length;
try {
Object rootObj = yamlLocal.get().load(data);
if (rootObj instanceof Map){
root = (Map)rootObj;
}
}catch (Exception ex){
logger.error("Failed to parse yaml document:" + data);
}
}
if (root == null){
root = new HashMap();
}
contentType = "text/plain;charset=" + ctx.getEncoding();
}
@Override
public void finish(Context ctx,boolean closeStream) {
boolean gzipEnable = isGzipEnable(ctx,"Accept-Encoding");
Map _root = getRoot();
JsonTools.setString(_root, "code", ctx.getReturnCode());
if (idnote != null){
IdNote note = idnote.getNote(ctx.getReturnCode());
if (note != null){
JsonTools.setString(_root, "reason", note.getNote());
JsonTools.setString(_root, "advise", ctx.getReason());
}else{
JsonTools.setString(_root, "reason", ctx.getReason());
}
}else{
JsonTools.setString(_root, "reason", ctx.getReason());
}
JsonTools.setString(_root, "duration", String.valueOf(ctx.getDuration()));
JsonTools.setString(_root, "host", getHost(ctx.getHost()));
JsonTools.setString(_root, "serial", ctx.getGlobalSerial());
OutputStream out = null;
try {
Object outputObject = _root;
if (StringUtils.isNotEmpty(outputPath)){
try {
outputObject = JsonPath.read(outputObject, outputPath);
}catch (Exception ex){
logger.error("Can not location jsonpath " + outputPath);
}
}
outputObject = outputObject == null ? _root : outputObject;
Yaml yaml = yamlLocal.get();
String data = yaml.dump(outputObject);
out = ctx.getOutputStream();
ctx.setResponseContentType(contentType);
byte [] bytes = data.getBytes(ctx.getEncoding());
if (gzipEnable && bytes.length > gzipEnableLength){
bytes = gzipCompressor.compress(bytes);
ctx.setResponseHeader("Content-Encoding","gzip");
}
contentLength += bytes.length;
ctx.setResponseContentLength(bytes.length);
Context.writeToOutpuStream(out, bytes);
out.flush();
}catch (Exception ex){
logger.error("Error when writing data to outputstream",ex);
}finally{
if (closeStream)
IOTools.close(out);
}
}
/**
* 获取JSON结构的根节点
*
* @return JSON结构的根节点
*/
public Map getRoot(){
return root;
}
@Override
public String toString(){
return yamlLocal.get().dump(root);
}
@Override
public String getContentType() {
return contentType;
}
@Override
public long getContentLength() {
return contentLength;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy