[英]How to transform client request body with a zuul filter?
I want to use Zuul to authenticate, transform and forward request from a client to internal services.我想使用 Zuul 对来自客户端的请求进行身份验证、转换和转发到内部服务。 The goal is to hide from the client a legacy API.目标是向客户端隐藏遗留 API。
What I have in mind is: a client sends a POST request with the JSON representation of an object A to the API Gateway where Zuul is embedded.我的想法是:客户端将带有对象 A 的 JSON 表示的 POST 请求发送到嵌入 Zuul 的 API 网关。 The API Gateway transforms the body from A to LegacyA and send it to the internal service. API Gateway 将 body 从 A 转换为 LegacyA 并将其发送到内部服务。
For example, I search a way to transform the following JSON:例如,我搜索了一种转换以下 JSON 的方法:
["hello","world"]
in this JSON:在这个 JSON 中:
{hashCode("hello"):"hello", hashCode("world"):"world")}
I want to use a pre-filter.我想使用前置过滤器。 But I have problem to rewrite a valid request.但是我在重写有效请求时遇到问题。
Do you have any idea how can I do that?你知道我该怎么做吗?
I have written this filter:我写了这个过滤器:
public class RestZuulFilter extends ZuulFilter {
private final ObjectMapper objectMapper;
@Autowired
public RestZuulFilter(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 100;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequestWrapper wrapper = new MyWrapper(ctx.getRequest());
ctx.setRequest(wrapper);
return null;
}
class MyWrapper extends HttpServletRequestWrapper {
/**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
* @throws IllegalArgumentException if the request is null
*/
public MyWrapper(HttpServletRequest request) {
super(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
ServletInputStream inputStream = this.getRequest().getInputStream();
List<String> test = objectMapper.readValue(inputStream, new TypeReference<List<String>>() {
});
Map<Integer, String> result = test.stream()
.collect(Collectors.toMap(String::hashCode, str -> str));
byte[] json = objectMapper.writeValueAsBytes(result);
ServletInputStream response = new ServletInputStreamWrapper(json);
return response;
}
}
}
The problem that I have is with the Content-Length which is not updated accordinally.我遇到的问题是 Content-Length 没有相应更新。
Take a look at the following example of a request body being transformed.看看下面的请求正文被转换的例子。 I suppose this should work for you.我想这应该对你有用。
InputStream in = (InputStream) context.get("requestEntity");
if (in == null) {
in = context.getRequest().getInputStream();
}
String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
body = body.toUpperCase();
context.set("requestEntity", new ByteArrayInputStream(body.getBytes("UTF-8")));
For the complete class:对于完整的类:
https://github.com/spring-cloud-samples/sample-zuul-filters/blob/master/src/main/java/org/springframework/cloud/samplezuulfilters/UppercaseRequestEntityFilter.java https://github.com/spring-cloud-samples/sample-zuul-filters/blob/master/src/main/java/org/springframework/cloud/samplezuulfilters/UppercaseRequestEntityFilter.java
The quickest way is to use the HttpServletRequestWrapperclass inside your filter最快的方法是在过滤器中使用 HttpServletRequestWrapper 类
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import static com.netflix.zuul.context.RequestContext.getCurrentContext;
public class ModifyBodyFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = getCurrentContext();
String newBody = "{\"key\":\"value\"}";
byte[] bytes = newBody.getBytes();
ctx.setRequest(new HttpServletRequestWrapper(getCurrentContext().getRequest()) {
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(bytes);
}
@Override
public int getContentLength() {
return bytes.length;
}
@Override
public long getContentLengthLong() {
return bytes.length;
}
});
return null;
}
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.