zuul's method of modifying request parameter information in springcloud

  • 2021-01-22 05:11:37
  • OfStack

Zuul is a load balancer based on JVM routing and server.

Zuul function:

certification Pressure test The canary test Dynamic routing Load reduction security Static response processing Active/active exchange management

Zuul's rules engine allows rules and filters to be written in any JVM language, supporting builds based on Java and Groovy.

Configuration properties zuul. max. host. connections has been replaced by two new configuration properties, zuul. host. maxTotalConnections (total number of connections) and zuul host. maxPerRouteConnections, routing number of connections (each) the default value is 200 and 20 respectively.

1. Why use this

In the micro-service system based on springcloud, the gateway zuul is usually used to carry out some filtering operations such as user authentication. For example, the user stores token in header or url parameters. The gateway layer needs to use this token to find the user's userId and store it in request, so that the subsequent micro-service can be directly used and avoid using token query.

2. The basics

The biggest use in zuul, besides routing, is the filter. Custom filters need to implement the interface ZuulFilter, which is available in the run() method


RequestContext ctx = RequestContext.getCurrentContext(); 
HttpServletRequest request = ctx.getRequest(); 

setAttribute() can be used in reqeust. However, due to the difference in scope, the attribute set here will not be available in the subsequent microservice. Therefore, another method must be considered.

3. Specific approaches

Finally, the feasible method was determined to use


ctx.setRequest(new HttpServletRequestWrapper(request) {}) 

The way to reconstruct the context of request is as follows:


import javax.servlet.http.HttpServletRequestWrapper; 
 //  in json Parameter to add  userId 
try { 
 InputStream in = ctx.getRequest().getInputStream(); 
 String body = StreamUtils.copyToString(in, Charset.forName("UTF-8")); 
 System.out.println("body:" + body); 
 JSONObject json = JSONObject.fromObject(body); 
 json.put("userId", userId); 
 String newBody = json.toString(); 
 System.out.println("newBody:" + newBody); 
 final byte[] reqBodyBytes = newBody.getBytes(); 
 ctx.setRequest(new HttpServletRequestWrapper(request){  
 @Override 
 public ServletInputStream getInputStream() throws IOException { 
  return new ServletInputStreamWrapper(reqBodyBytes); 
 } 
 @Override 
 public int getContentLength() { 
  return reqBodyBytes.length; 
 } 
 @Override 
 public long getContentLengthLong() { 
  return reqBodyBytes.length; 
 } 
 }); 
} catch (IOException e) { 
 e.printStackTrace(); 
} 

The idea is to take the input stream of the request and override it, overriding the json parameter.

In the controller of the subsequent microservice, you can use the likeness


@RequestBody Map<String,Object> body 
======= 
body.get("userId"); 

In this way, to get userId passed in zuulFilter

4.1 some try

I tried to rewrite it when I rewrote HttpServletRequestWrapper getParameterNames() and getParameterMap() Method, expecting to override the url parameter, but it did not take effect.

conclusion


Related articles: