-
-
Save WeirdBob/b25569d461f0f54444d2c0eab51f3c48 to your computer and use it in GitHub Desktop.
| spring: | |
| cloud: | |
| gateway: | |
| routes: | |
| - id: test | |
| uri: https://httpbin.org:443 | |
| predicates: | |
| - Path=/uuid | |
| - Method=GET | |
| server: | |
| port: 8080 |
| package examples; | |
| import org.springframework.boot.SpringApplication; | |
| import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | |
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |
| @SpringBootApplication | |
| @EnableAutoConfiguration | |
| public class GatewayApplication { | |
| public static void main(String[] args) { | |
| SpringApplication.run(GatewayApplication.class, args); | |
| } | |
| } |
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
| <modelVersion>4.0.0</modelVersion> | |
| <groupId>examples</groupId> | |
| <artifactId>gateway</artifactId> | |
| <version>0.0.1-SNAPSHOT</version> | |
| <parent> | |
| <groupId>org.springframework.boot</groupId> | |
| <artifactId>spring-boot-starter-parent</artifactId> | |
| <version>2.0.0.M5</version> | |
| <relativePath /> <!-- lookup parent from repository --> | |
| </parent> | |
| <properties> | |
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
| <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |
| <java.version>1.8</java.version> | |
| </properties> | |
| <dependencies> | |
| <dependency> | |
| <groupId>org.springframework.cloud</groupId> | |
| <artifactId>spring-cloud-starter-gateway</artifactId> | |
| <version>2.0.0.M3</version> | |
| </dependency> | |
| </dependencies> | |
| <profiles> | |
| <profile> | |
| <id>spring</id> | |
| <activation> | |
| <activeByDefault>true</activeByDefault> | |
| </activation> | |
| <repositories> | |
| <repository> | |
| <id>spring-milestones</id> | |
| <name>Spring Milestones</name> | |
| <url>https://repo.spring.io/libs-milestone-local</url> | |
| <snapshots> | |
| <enabled>false</enabled> | |
| </snapshots> | |
| </repository> | |
| </repositories> | |
| </profile> | |
| </profiles> | |
| </project> |
| package examples; | |
| import java.nio.charset.Charset; | |
| import org.reactivestreams.Publisher; | |
| import org.springframework.cloud.gateway.filter.GatewayFilterChain; | |
| import org.springframework.cloud.gateway.filter.GlobalFilter; | |
| import org.springframework.core.Ordered; | |
| import org.springframework.core.io.buffer.DataBuffer; | |
| import org.springframework.core.io.buffer.DataBufferFactory; | |
| import org.springframework.http.server.reactive.ServerHttpResponse; | |
| import org.springframework.http.server.reactive.ServerHttpResponseDecorator; | |
| import org.springframework.stereotype.Component; | |
| import org.springframework.web.server.ServerWebExchange; | |
| import reactor.core.publisher.Flux; | |
| import reactor.core.publisher.Mono; | |
| @Component | |
| public class ToUppercaseGlobalFilter implements GlobalFilter, Ordered { | |
| @Override | |
| public int getOrder() { | |
| return -2; // -1 is response write filter, must be called before that | |
| } | |
| @Override | |
| public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { | |
| ServerHttpResponse originalResponse = exchange.getResponse(); | |
| DataBufferFactory bufferFactory = originalResponse.bufferFactory(); | |
| ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) { | |
| @Override | |
| public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) { | |
| if (body instanceof Flux) { | |
| Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body; | |
| return super.writeWith(fluxBody.map(dataBuffer -> { | |
| // probably should reuse buffers | |
| byte[] content = new byte[dataBuffer.readableByteCount()]; | |
| dataBuffer.read(content); | |
| byte[] uppedContent = new String(content, Charset.forName("UTF-8")).toUpperCase().getBytes(); | |
| return bufferFactory.wrap(uppedContent); | |
| })); | |
| } | |
| return super.writeWith(body); // if body is not a flux. never got there. | |
| } | |
| }; | |
| return chain.filter(exchange.mutate().response(decoratedResponse).build()); // replace response with decorator | |
| } | |
| } |
when i use this to modify a large content,it usually read a part of my json string ,server has no response,do you have meet this question?how can i solve this
you can remove the Content-Length from headers to handle this problem;
thanks for this gist. it steered me towards what i need to modify the response of a body via Spring Cloud Gateway. A lot can be learned from the source code of ModifyResponseBodyGatewayFilterFactory.java to maybe improve on this but for my purpose the gist works as it is.
edit: oof. that didn't last long 😝. the above approach will work to some degree but it is limited...like, for example, if you intend to modify a JSON response body prior to returning to the client, the above gist will not work (i know because i tried). also note that the gist doesn't take the decoders into account from upstream like here.
I found an article that tackled this and the solution seems to be a modification of ModifyResponseBodyGatewayFilterFactory.
edit 2: after tinkering around, i was able to write a quick and dirty custom filter that modifies response body based on what ModifyResponseBodyGatewayFilterFactorydoes today ...i wrote up a gist here.
https://gist.github.com/MdShohanurRahman/0d27148e7a1c9e05f6542f11c2ad98a0
here is the complete request and response log. You can follow.
@arpitkh12 have you found solution yet?