Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How does FeignClient share Header and trampling process

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains "how to share Header and step on the pit by FeignClient". Interested friends may wish to have a look at it. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "how FeignClient shares Header and the process of stepping on a pit".

FeignClient sharing Header and trampling problem

When we call feign, we often need to use the header held by the client, such as auth-token, and we need to pass on these header

Train of thought

Use the interceptor to intercept the feign request on the client side and pass on the required header

Code:

Define interceptor @ Configurationpublic class FeignInterceptor implements RequestInterceptor {@ Override public void apply (RequestTemplate requestTemplate) {Map headers = getHeaders (getHttpServletRequest ()); for (String headerName: headers.keySet ()) {requestTemplate.header (headerName, getHeaders (getHttpServletRequest ()) .get (headerName));} private HttpServletRequest getHttpServletRequest () {try {return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes ()) .getRequest () } catch (Exception e) {e.printStackTrace (); return null;}} private Map getHeaders (HttpServletRequest request) {Map map = new LinkedHashMap (); Enumeration enumeration = request.getHeaderNames (); while (enumeration.hasMoreElements ()) {String key = enumeration.nextElement () If (needThisHeader (key)) {String value = request.getHeader (key); map.put (key, value);} return map;} private boolean needThisHeader (String headerName) {/ / todo: write your logic here, which header needs to be passed, never pass all header to return true }} inject the interceptor into the Spring@Configurationpublic class FeignSupportConfig {/ * feign request interceptor * * @ return * / @ Bean public RequestInterceptor requestInterceptor () {return new FeignInterceptor ();}} tell me about the pit

You must not upload all the header, which is likely to lead to confusion in the type of request when calling feign, and wear what header you should wear.

Feign sets the Header header

Today, you try to use feign to call a HTTP interface provided by another department, which requires that a username header be set in the request for identity authentication.

FeignClient (name = "kafka-client", url = "http://kafka.xxx.com")public interface KafkaClient {@ GetMapping (value =" / api/clusterManager/listTopics ") @ Headers ({" cache-control: no-cache "," username: wangyong@xxx.com "}) TopicsResponse listTopics (@ RequestParam (" clusterName ") String clusterName, @ RequestParam (" clusterArea ") String clusterArea);}

Write the code well and try to access it

Throw the following error message {"timestamp": 1551768926170, "status": 500,500, "error": "Internal Server Error", "exception": "com.netflix.zuul.exception.ZuulException", "message": "pre:AuthAccessFilter"}

The exception stack information is as follows:

At feign.FeignException.errorStatus (FeignException.java:62)

At feign.codec.ErrorDecoder$Default.decode (ErrorDecoder.java:91)

At feign.SynchronousMethodHandler.executeAndDecode (SynchronousMethodHandler.java:134)

At feign.SynchronousMethodHandler.invoke (SynchronousMethodHandler.java:76)

At feign.ReflectiveFeign$FeignInvocationHandler.invoke (ReflectiveFeign.java:103)

At com.sun.proxy.$Proxy147.listTopics (Unknown Source)

At com.yidian.data.exptmgr.controller.KafkaController.getKafkaTopics (KafkaController.java:35)

/ / omit more exception stack information

So I tried to find the root cause of the problem through debug. Through debug, I found that feign will first build the request parameters into a Request object. The request information is as follows:

Request

You can see from the figure that the headers attribute of the Request instance is empty, and the Request is generated from the RequestTemplate template object. The RequestTemplate instance information is as follows:

RequestTemplate

As you can see here, the problem lies in the build composition of RequestTemplate, so I traced the code built by RequestTemplate and found that RequestTemplate is built on MethodMetadata, and MethodMetadata is an abstraction of method configuration.

RequestTemplate template = resolve (argv, mutable, varBuilder); if (metadata.queryMapIndex ()! = null) {/ / add query map parameters after initial resolve so that they take / / precedence over any predefined values template = addQueryMapQueryParameters (argv, template);} if (metadata.headerMapIndex ()! = null) {template = addHeaderMapHeaders (argv, template);}

As you can see from the above code, the setting of header is determined by the headerMapIndex property of metadata, so the location of setting headerMapIndex must be related to the parsing of Header, so check the method reference

I found the following code private void parseHeaders (MethodMetadata md, Method method, RequestMapping annotation) {/ / TODO: only supports one header value per key if (annotation.headers ()! = null & & annotation.headers (). Length > 0) {for (String header: annotation.headers ()) {int index = header.indexOf ('=') If (! header.contains ("! =") & & index > = 0) {md.template () .header (resolve (header.substring (0, index)), resolve (header.substring (index + 1). Trim ());}}

We can clearly see from the code that the Header is parsed from @ RequestMapping or the header attribute of its derived annotation, and the key and value of Header need to be separated by "=".

So I changed it to the following form

The problem has been solved @ GetMapping (value = "/ api/clusterManager/listTopics", headers = {"cache-control=no-cache", "username=wangyong@xxx.com"}) TopicsResponse listTopics (@ RequestParam ("clusterName") String clusterName, @ RequestParam ("clusterArea") String clusterArea). At this point, I believe you have a better understanding of "how FeignClient shares Header and stepping on the pit". You might as well do it in practice! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report