byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

cant advice the javax.servlet.http.HttpServlet and acquired the request`s header

Open xiewenci opened this issue 3 years ago • 4 comments

I want to advice the HttpServletRequest and to acquired the header when I advice on Class javax.servlet.http.HttpServlet, method service(HttpServletRequest req, HttpServletResponse resp) ,cant advice the method. for example: new AgentBuilder.Default(byteBuddy) .ignore(nameStartsWith("net.bytebuddy.") .or(nameStartsWith("org.slf4j.")) .or(nameStartsWith("org.apache.logging.")) .or(nameStartsWith("org.groovy.")) .or(nameContains("javassist")) .or(nameContains(".asm.")) .or(nameStartsWith("sun.reflect")) .or(ElementMatchers.isSynthetic())) // 拦截 .type(ElementMatchers.named(RPC_INVOKER_TRANSFORMER) .or(ElementMatchers.named(RPC_PRODUCER_OPER_TRANSFORMER)) .or(ElementMatchers.named(HTTP_NIO_CLIENT_TRANSFORMER)) .or(ElementMatchers.named(HTTP_CLIENT_TRANSFORMER)) .or(ElementMatchers.named("javax.servlet.http.HttpServlet")) .or(ElementMatchers.nameStartsWith(IOT_SERVICE_PREFIX_TRANSFORMER))) // 设置Transform .transform(new Transformer()) .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) .installOn(inst);

And my transForm is blow: ` public class Transformer implements AgentBuilder.Transformer {

@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {

    //RPC客户端调用拦截
    try {
         if (typeDescription.getTypeName().startsWith("com.huawei.")
                && !HttpAgentUtil.checkRpcRestSchemaAnn(typeDescription) || "javax.servlet.http.HttpServlet".equals(typeDescription.getTypeName())) {
            //Http服务端调用拦截,需要去除通过CSE @RestSchema注解定义的RPC接口(和Http定义类似)

            System.out.println("Transformer " + typeDescription);
            //只对有RequestMapping/PostMapping/GetMapping/DeleteMapping/PutMapping注解的函数进行拦截
            DynamicType.Builder<?> builder1 = builder.visit(Advice.to(HttpServerInvInterceptor.class).on(
                    ElementMatchers.named("service").and(ElementMatchers.takesArgument(0,ElementMatchers.named("javax.servlet.http.HttpServletRequest")))
            ));
            return builder1;

        }
    } catch (Throwable e) {

        System.err.println("error " + e.getMessage());
    }
    return builder;
}

} ` and my HttpServerInvInterceptor is below :

@Advice.OnMethodEnter public static void enter(@Advice.Origin("#t.#m") String signature, @Advice.AllArguments Object[] args, @Advice.Origin("#t") String className, @Advice.Origin("#m") String methodName) { try { if (args[0] instanceof HttpServletRequest) { HttpServletRequest request = (HttpServletRequest) args[0]; String sp = request.getHeader("sp"); System.out.println("sp: " + sp); } AgentUtils.logInfo("===start Enter " + signature + "==="); System.out.println("Im coming"); setHttpServerMethodLogStartTime(System.currentTimeMillis()); AgentUtils.logInfo("get the method start time"); AgentUtils.logInfo("===end Enter " + signature + "==="); } catch (Throwable e) { AgentUtils.logWarn("execute " + signature + " Enter Exception:" + ExceptionUtil.getBriefExceptionStackTrace(e)); destroyHttpServerMethodLogStartTime(); } } and then , i cant acquired the HttpServletRequest.

Excuse me, where is this configuration processing wrong?

xiewenci avatar Mar 24 '22 12:03 xiewenci

Did you try registering a listener? It would show you any types being transformed or that fail. I recommend to also set disableClassFormatChanges.

raphw avatar Mar 24 '22 14:03 raphw

when the project start, i can see the log : FlowListener: javax.servlet.http.HttpServlet FlowListener: javax.servlet.http.HttpServlet

but when i send the http request ,my Listener cant serch the log, so, i guess my TransForm only advice once time, and after my project started, my transform cant advice the HttpServlet.

listener as below: ` public class FlowListener implements AgentBuilder.Listener {

@Override
public void onDiscovery(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) {
    System.out.println("FlowListener: " + s);
}

@Override
public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, boolean b, DynamicType dynamicType) {
    System.out.println("FlowListener: " + typeDescription.getTypeName());

}

@Override
public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, boolean b) {
    System.out.println("FlowListener: " + typeDescription.getTypeName());

}

@Override
public void onError(String s, ClassLoader classLoader, JavaModule javaModule, boolean b, Throwable throwable) {
    System.out.println("FlowListener: " + s);

}

@Override
public void onComplete(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) {
    System.out.println("FlowListener: " + s);

}

} `

any other suggestions? thanks

xiewenci avatar Mar 25 '22 02:03 xiewenci

Could you use Byte Buddy's print writing listener or change yours to showcase if this was a successful or a failed transformation? Maybe it was even ignored. I recommend using Byte Buddy's builtin listener, it is quite detailed and even has a factory for writing to the output stream.

raphw avatar Mar 25 '22 20:03 raphw

Try this way while instantiating the Agent: .type(isSubTypeOf(new TypeDescription.Latent("javax.servlet.GenericServlet", Modifier.PUBLIC | Modifier.ABSTRACT, TypeDescription.Generic.OBJECT))) .transform( new AgentBuilder.Transformer.ForAdvice() .include(ExecuteAgent.class.getClassLoader()) .advice( named("service") .and(takesArgument(0, named("javax.servlet.ServletRequest"))) .and(takesArgument(1, named("javax.servlet.ServletResponse"))) , "com.your.advice.yourAdvice" ) ) and have appropriate code in your advice: @Advice.OnMethodEnter public static void enter(//@Advice.This Object obj, @Advice.Argument(value = 0) ServletRequest request, @Advice.Argument(value = 1) ServletResponse response, //@Advice.AllArguments Object[] allArguments, //@Advice.Origin("#t") String className, @Advice.Origin("#m") String methodName) {

Hopefully this helps you.

chaudharydeepak avatar May 18 '22 20:05 chaudharydeepak