package com.philemonworks.critter.condition; import com.philemonworks.critter.proto.Definitions; import com.philemonworks.critter.proto.Inspector; import com.philemonworks.critter.rule.RuleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Base64; /** * Created by emicklei on 25/02/16. */ public class ProtobufPath implements Condition { private static final Logger LOG = LoggerFactory.getLogger(ProtobufPath.class); // name of the message String messageName = "** missing messageName **"; // dotted path String expression = ""; // regular expression to match the string representation of the value. String matches = ""; @Override public boolean test(RuleContext ctx) { String contentType = ctx.httpContext.getRequest().getHeaderValue("Content-Type"); if (!"application/octet-stream".equals(contentType)) { if (ctx.rule.tracing) { LOG.info("rule={} contentType={} expected={}", ctx.rule.id, contentType, "application/octet-stream"); return false; } } byte[] data = ctx.getRequestEntityContent(); // see if we need to decode it String contentEncoding = ctx.httpContext.getRequest().getHeaderValue("Content-Encoding"); if (contentEncoding != null && contentEncoding.length() > 0) { if (!"base64".equals(contentEncoding)) { if (ctx.rule.tracing) { LOG.info("rule={} acceptEncoding={} expected={}", ctx.rule.id, contentEncoding, "base64"); } return false; } data = Base64.getDecoder().decode(data); } if (ctx.rule.tracing) { LOG.info("rule={} data-base64={} data-size={}", ctx.rule.id, new String(Base64.getEncoder().encode(data)), data.length); } Definitions defs = ctx.protoDefinitions.getDefinitions(ctx.rule.id); if (defs.isEmpty()) { if (ctx.rule.tracing) { LOG.info("rule={} missing definitions", ctx.rule.id); } return false; } Inspector inspector = defs.newInspector(this.messageName); if (!inspector.read(data)) { if (ctx.rule.tracing) { LOG.info("rule={} error=unable to read protobuf message data (definitions uploaded?)", ctx.rule.id); } return false; } String value = inspector.path(this.expression); if (ctx.rule.tracing) { LOG.debug("rule={} messageName={} expression={} value={}", ctx.rule.id, this.messageName, this.expression, value); } return value.matches(this.matches); } @Override public String explain() { return "the protobuf path [" + expression + "] matches [" + matches + "] from a [" + this.messageName + "]"; } }