@@ -40,6 +40,8 @@ public void addTrace(MethodEvent event, PolicyNode policyNode) {
4040 traceId = addTraceToApacheHttpClientLegacy (event );
4141 } else if (HttpClient .matchOkhttp (this .matchedSignature )) {
4242 traceId = addTraceToOkhttp (event );
43+ } else if (HttpClient .matchApacheHttpComponents (this .matchedSignature )) {
44+ traceId = addTraceToApacheHttpComponents (event );
4345 }
4446
4547 if (traceId != null && !traceId .isEmpty ()) {
@@ -273,13 +275,66 @@ private void addHeaderToOkhttp(MethodEvent event, Map<String, String> headers) {
273275 }
274276 }
275277
278+ /**
279+ * 添加traceId到Apache HttpComponents的请求上
280+ *
281+ * @param event
282+ * @return
283+ */
284+ private String addTraceToApacheHttpComponents (MethodEvent event ) {
285+ Object obj = event .objectInstance ;
286+ if (obj == null ) {
287+ return null ;
288+ }
289+ try {
290+ String className = obj .getClass ().getName ();
291+ if (!HttpClient .matchApacheHttpComponents (className )) {
292+ return null ;
293+ }
294+
295+ // 关于库的版本兼容性:
296+ // 在GA org.apache.httpcomponents:fluent-hc的[4.4, 4.5.14]这个区间的版本里的request字段是这个org.apache.http.client.fluent.InternalHttpRequest类型
297+ // private final InternalHttpRequest request;
298+ // 然后org.apache.http.client.fluent.InternalHttpRequest这个类继承的org.apache.http.message.AbstractHttpMessage上有个setHeader方法:
299+ // @Override // org.apache.http.HttpMessage
300+ // public void setHeader(String name, String value) {
301+ // Args.notNull(name, "Header name");
302+ // this.headergroup.updateHeader(new BasicHeader(name, value));
303+ // }
304+ // 另外一提,org.apache.http.message.AbstractHttpMessage是在httpcomponents-httpcore:httpcore下的,它自从4.0-alpha5版本被添加了之后就没有变更过
305+ //
306+ // 在GA org.apache.httpcomponents:fluent-hc的[4.2, 4.4) 版本区间的request字段是org.apache.http.client.methods.HttpRequestBase类型,这个类属于依赖中的org.apache.httpcomponents:httpclient
307+ // private final HttpRequestBase request;
308+ // 在org.apache.httpcomponents:httpclient的[4.0.1, 4.2.6]版本区间,org.apache.http.client.methods.HttpRequestBase这个类是继承的org.apache.http.message.AbstractHttpMessage,此条分支可以与上面的合并
309+ // org.apache.httpcomponents:httpclient的[4.3, 4.5.14]区间内是继承的org.apache.http.client.methods.AbstractExecutionAwareRequest
310+ // org.apache.http.client.methods.AbstractExecutionAwareRequest自从4.3.4版本被添加依赖,一直继承的org.apache.http.message.AbstractHttpMessage,此条分支又可以与上面合并
311+ // 所有版本的实现最终都会直接继承或者间接继承到org.apache.http.message.AbstractHttpMessage,所以下面的操作才可以统一
312+
313+ Field reqField = obj .getClass ().getDeclaredField ("request" );
314+ reqField .setAccessible (true );
315+ Object internalHttpRequest = reqField .get (obj );
316+ Method setHeaderMethod = internalHttpRequest .getClass ().getMethod ("setHeader" , String .class , String .class );
317+
318+ // 然后把追踪的头加上
319+ final String traceId = ContextManager .nextTraceId ();
320+ setHeaderMethod .invoke (internalHttpRequest , ContextManager .getHeaderKey (), traceId );
321+ setHeaderMethod .invoke (internalHttpRequest , ContextManager .getParentKey (), String .valueOf (EngineManager .getAgentId ()));
322+ return traceId ;
323+ } catch (Throwable e ) {
324+ DongTaiLog .debug ("add traceId header to apache http components failed: {}, {}" , e .getMessage (), e .getCause () != null ? e .getCause ().getMessage () : "" );
325+ }
326+ return null ;
327+ }
328+
276329 public static boolean validate (MethodEvent event ) {
277330 if (HttpClient .matchJavaNetUrl (event .signature )) {
278331 return validateURLConnection (event );
279332 } else if (HttpClient .matchApacheHttp4 (event .signature ) || HttpClient .matchApacheHttp5 (event .signature )) {
280333 return validateApacheHttpClient (event );
281334 } else if (HttpClient .matchOkhttp (event .signature )) {
282335 return validateOkhttp (event );
336+ } else if (HttpClient .matchApacheHttpComponents (event .signature )) {
337+ return validateApacheHttpComponents (event );
283338 }
284339 return true ;
285340 }
@@ -377,4 +432,37 @@ public static boolean validateOkhttp(MethodEvent event) {
377432 }
378433 return false ;
379434 }
435+
436+ /**
437+ * 验证是否是合法的
438+ *
439+ * @param event
440+ * @return
441+ */
442+ public static boolean validateApacheHttpComponents (MethodEvent event ) {
443+ Object obj = event .objectInstance ;
444+ if (obj == null ) {
445+ return false ;
446+ }
447+ try {
448+ String className = obj .getClass ().getName ();
449+ if (!HttpClient .matchApacheHttpComponents (className )) {
450+ return false ;
451+ }
452+
453+ // 关于类的版本兼容性,详见 #addTraceToApacheHttpComponents方法
454+ Field reqField = obj .getClass ().getDeclaredField ("request" );
455+ reqField .setAccessible (true );
456+ Object internalHttpRequest = reqField .get (obj );
457+ Object header = internalHttpRequest .getClass ().getMethod ("getFirstHeader" , String .class ).invoke (internalHttpRequest , ContextManager .getHeaderKey ());
458+ // traceId header not exists
459+ if (header == null ) {
460+ return true ;
461+ }
462+ } catch (Throwable e ) {
463+ DongTaiLog .debug ("validate apache http components failed: {}, {}" , e .getMessage (), e .getCause () != null ? e .getCause ().getMessage () : "" );
464+ }
465+ return false ;
466+ }
467+
380468}
0 commit comments