diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml index ec6fee4..2830651 100644 --- a/fizz-bootstrap/pom.xml +++ b/fizz-bootstrap/pom.xml @@ -12,13 +12,13 @@ com.fizzgate fizz-bootstrap - 2.3.1 + 2.3.2-beta1 1.8 5.2.13.RELEASE Dragonfruit-SR3 - Dysprosium-SR22 + Dysprosium-SR23 5.3.7.RELEASE 4.1.68.Final 4.4.14 diff --git a/fizz-common/pom.xml b/fizz-common/pom.xml index 0ac28cc..b40e131 100644 --- a/fizz-common/pom.xml +++ b/fizz-common/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.1 + 2.3.2-beta1 ../pom.xml 4.0.0 diff --git a/fizz-common/src/main/java/we/spring/web/server/ext/FizzServerWebExchangeDecorator.java b/fizz-common/src/main/java/we/spring/web/server/ext/FizzServerWebExchangeDecorator.java new file mode 100644 index 0000000..831cc55 --- /dev/null +++ b/fizz-common/src/main/java/we/spring/web/server/ext/FizzServerWebExchangeDecorator.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package we.spring.web.server.ext; + +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.lang.Nullable; +import org.springframework.util.CollectionUtils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; +import reactor.core.publisher.Mono; +import we.util.NettyDataBufferUtils; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * @author hongqiaowei + */ + +public class FizzServerWebExchangeDecorator extends ServerWebExchangeDecorator { + + private static final MultiValueMap EMPTY_FORM_DATA = CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap(0)); + + private static final Mono> EMPTY_FORM_DATA_MONO = Mono.just(EMPTY_FORM_DATA).cache(); + + public FizzServerWebExchangeDecorator(ServerWebExchange delegate) { + super(delegate); + } + + private Charset getMediaTypeCharset(@Nullable MediaType mediaType) { + if (mediaType != null && mediaType.getCharset() != null) { + return mediaType.getCharset(); + } else { + return StandardCharsets.UTF_8; + } + } + + private MultiValueMap parseFormData(Charset charset, String source) { + String[] pairs = StringUtils.tokenizeToStringArray(source, "&"); + MultiValueMap result = new LinkedMultiValueMap<>(pairs.length); + try { + for (String pair : pairs) { + int idx = pair.indexOf('='); + if (idx == -1) { + result.add(URLDecoder.decode(pair, charset.name()), null); + } else { + String name = URLDecoder.decode(pair.substring(0, idx), charset.name()); + String value = URLDecoder.decode(pair.substring(idx + 1), charset.name()); + result.add(name, value); + } + } + } catch (UnsupportedEncodingException ex) { + throw new IllegalStateException(ex); + } + return result; + } + + @Override + public Mono> getFormData() { + ServerHttpRequest req = getDelegate().getRequest(); + MediaType ct = req.getHeaders().getContentType(); + if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(ct)) { + Charset charset = getMediaTypeCharset(ct); + return + req.getBody().defaultIfEmpty(NettyDataBufferUtils.EMPTY_DATA_BUFFER) + .single() + .map( + body -> { + if (body == NettyDataBufferUtils.EMPTY_DATA_BUFFER) { + return EMPTY_FORM_DATA; + } else { + CharBuffer charBuffer = charset.decode(body.asByteBuffer()); + return parseFormData(charset, charBuffer.toString()); + } + } + ); + } else { + return EMPTY_FORM_DATA_MONO; + } + } +} diff --git a/fizz-core/pom.xml b/fizz-core/pom.xml index f0795c0..499c331 100644 --- a/fizz-core/pom.xml +++ b/fizz-core/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.1 + 2.3.2-beta1 ../pom.xml 4.0.0 diff --git a/fizz-core/src/main/java/we/plugin/requestbody/RequestBodyPlugin.java b/fizz-core/src/main/java/we/plugin/requestbody/RequestBodyPlugin.java index 6f81e25..0823be5 100644 --- a/fizz-core/src/main/java/we/plugin/requestbody/RequestBodyPlugin.java +++ b/fizz-core/src/main/java/we/plugin/requestbody/RequestBodyPlugin.java @@ -20,6 +20,7 @@ package we.plugin.requestbody; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; @@ -28,6 +29,7 @@ import we.flume.clients.log4j2appender.LogService; import we.plugin.FizzPluginFilter; import we.plugin.FizzPluginFilterChain; import we.spring.http.server.reactive.ext.FizzServerHttpRequestDecorator; +import we.spring.web.server.ext.FizzServerWebExchangeDecorator; import we.util.NettyDataBufferUtils; import java.util.Map; @@ -51,19 +53,23 @@ public class RequestBodyPlugin implements FizzPluginFilter { NettyDataBufferUtils.join(req.getBody()).defaultIfEmpty(NettyDataBufferUtils.EMPTY_DATA_BUFFER) .flatMap( body -> { - ServerWebExchange newExchange = exchange; + FizzServerHttpRequestDecorator requestDecorator = new FizzServerHttpRequestDecorator(req); if (body != NettyDataBufferUtils.EMPTY_DATA_BUFFER) { - FizzServerHttpRequestDecorator requestDecorator = new FizzServerHttpRequestDecorator(req); try { requestDecorator.setBody(body); } finally { NettyDataBufferUtils.release(body); } requestDecorator.getHeaders().remove(HttpHeaders.CONTENT_LENGTH); - newExchange = exchange.mutate().request(requestDecorator).build(); - if (log.isDebugEnabled()) { - log.debug("retain body", LogService.BIZ_ID, req.getId()); - } + } + ServerWebExchange mutatedExchange = exchange.mutate().request(requestDecorator).build(); + ServerWebExchange newExchange = mutatedExchange; + MediaType contentType = req.getHeaders().getContentType(); + if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) { + newExchange = new FizzServerWebExchangeDecorator(mutatedExchange); + } + if (log.isDebugEnabled()) { + log.debug(req.getId() + " request is decorated", LogService.BIZ_ID, req.getId()); } return FizzPluginFilterChain.next(newExchange); } diff --git a/fizz-plugin/pom.xml b/fizz-plugin/pom.xml index 80d90ac..981ed7d 100644 --- a/fizz-plugin/pom.xml +++ b/fizz-plugin/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.1 + 2.3.2-beta1 ../pom.xml 4.0.0 diff --git a/fizz-spring-boot-starter/pom.xml b/fizz-spring-boot-starter/pom.xml index 79ee058..b35ec46 100644 --- a/fizz-spring-boot-starter/pom.xml +++ b/fizz-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.3.1 + 2.3.2-beta1 ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 1a57896..fac4814 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 2.2.13.RELEASE 5.2.13.RELEASE - Dysprosium-SR22 + Dysprosium-SR23 5.3.7.RELEASE 2.2.5.RELEASE 4.1.68.Final @@ -34,7 +34,7 @@ fizz-gateway-community ${project.artifactId} fizz gateway community - 2.3.1 + 2.3.2-beta1 pom fizz-common