spring-cloud-netflix: Zuul returning 400 bad request when changing body with HttpServletRequestWrapper
Personal, the zuul receives a request with the encrypted body, decrypts the body and passes the request to the internal services with the payload open.
It does the right job, however I have identified a bug, the first call works, the second gives 400 error, the third one works, the fourth gives 400, and so on, that is, one request works, the other does not.
public class SimpleFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(SimpleFilter.class);
private UrlPathHelper urlPathHelper = new UrlPathHelper();
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
final String requestURI = this.urlPathHelper.getPathWithinApplication(ctx.getRequest());
if (RequestMethod.valueOf(request.getMethod()) == RequestMethod.POST)
ctx.setRequest(DecryptionFilter.getInstance().parse(request));
return null;
}
}
public class DecryptionFilter {
private static DecryptionFilter instance;
private JsonObject json;
private String body;
public HttpServletRequest parse(HttpServletRequest request) {
try {
InputStream is = request.getInputStream();
this.body = IOUtils.toString(is);
} catch (IOException e) {
e.printStackTrace();
}
this.json = new JsonParser().parse(body).getAsJsonObject();
try {
this.body = Cryptography.decrypt(new Param(
json.get("param").getAsString(),
json.get("param1").getAsString()), "src/main/resources/private.pem");
} catch (Exception e) {
throw new RuntimeException();
}
return modifyRequest(request, body);
}
private static HttpServletRequestWrapper modifyRequest(HttpServletRequest request, String body) {
System.out.println("body: " + body);
return new HttpServletRequestWrapper(request) {
@Override
public ServletInputStream getInputStream() {
return new ServletInputStreamWrapper(body.getBytes());
}
};
}
public static DecryptionFilter getInstance() {
if (instance == null)
instance = new DecryptionFilter();
return instance;
}
}
buildscript {
ext {
springBootVersion = '1.5.6.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath "se.transmode.gradle:gradle-docker:1.2"
classpath('io.spring.gradle:dependency-management-plugin:0.5.4.RELEASE')
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'docker'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
jar {
baseName = 'app'
version = '0.0.1-SNAPSHOT'
archiveName = 'app.jar'
}
ext {
springCloudVersion = 'Dalston.SR2'
}
dependencies {
compile('org.springframework.cloud:spring-cloud-starter-zuul')
compile('org.springframework.boot:spring-boot-starter-web')
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
compile('org.springframework.cloud:spring-cloud-starter-config')
compile('org.springframework.cloud:spring-cloud-starter-bus-amqp')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 31 (6 by maintainers)
@ryanjbaxter This is a good example but another right way using the HtttpServletRequestWrapper as @eutiagocosta used on your sample as follows.
@eutiagocosta the issue with HttpServletRequestWrapper occurs when you change request content length. In other words, when you change the request content you need rewrite the other descriptors as content length and other reader methods from your request.