spring cloud gateway中如何读取请求参数

网友投稿 2067 2022-12-27

spring cloud gateway中如何读取请求参数

spring cloud gateway中如何读取请求参数

spring cloud gateway读取请求参数

1. 我的版本:

spring-cloud:Hoxton.RELEASE

spring-boot:2.2.2.RELEASE

spring-cloud-starter-gateway

2. 请求日志

import lombok.extern.slf4j.Slf4j;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.cloud.gateway.http://filter.GlobalFilter;

import org.springframework.core.io.buffer.DataBuffer;

import org.springframework.core.io.buffer.DataBufferUtils;

import org.springframework.http.HttpMethod;

import org.springframework.http.server.reactive.ServerHttpRequest;

import org.springframework.http.server.reactive.ServerHttpRequestDecorator;

import org.springframework.stereotype.Component;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Flux;

import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

import java.util.Map;

import java.util.stream.Collectors;

/**

* @author MinWeikai

* @date 2019-12-20 18:09:39

*/

@Slf4j

@Component

public class LoggerFilter implements GlobalFilter {

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

ServerHttpRequest request = exchange.getRequest();

String method = request.getMethodValue();

if (HttpMethod.POST.matches(method)) {

return DataBufferUtils.join(exchange.getRequest().getBody())

.flatMap(dataBuffer -> {

byte[] bytes = new byte[dataBuffer.readableByteCount()];

dataBuffer.read(bytes);

String bodyString = new String(bytes, StandardCharsets.UTF_8);

logtrace(exchange, bodyString);

exchange.getAttributes().put("POST_BODY", bodyString);

DataBufferUtils.release(dataBuffer);

Flux cachedFlux = Flux.defer(() -> {

DataBuffer buffer = exchange.getResponse().bufferFactory()

.wrap(bytes);

return Mono.just(buffer);

});

ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(

exchange.getRequest()) {

@Override

public Flux getBody() {

return cachedFlux;

}

};

return chain.filter(exchange.mutate().request(mutatedRequest)

.build());

});

} else if (HttpMethod.GET.matches(method)) {

Map m = request.getQueryParams();

logtrace(exchange, m.toString());

}

return chain.filter(exchange);

}

/**

* 日志信息

*

* @param exchange

* @param param 请求参数

*/

private void logtrace(ServerWebExchange exchange, String param) {

ServerHttpRequest serverHttpRequest = exchange.getRequest();

String path = serverHttpRequest.getURI().getPath();

String method = serverHttpRequest.getMethodValue();

String headers = serverHttpRequest.getHeaders().entrySet()

.stream()

.map(entry -> " " + entry.getKey() + ": [" + String.join(";", entry.getValue()) + "]")

.collect(Collectors.joining("\n"));

log.info("\n" + "---------------- ---------------- ---------------->>\n" +

"HttpMethod : {}\n" +

"Uri : {}\n" +

"Param : {}\n" +

"Headers : \n" +

"{}\n" +

"\"<<---------------- ---------------- ----------------"

, method, path, param, headers);

}

}

3. 测试输出,我这边测试没有问题,日志正常输出

gateway网关转发请求添加参数

在继承AbstractGatewayFilterFactory的过滤器中

GET请求添加参数

// 参考api文档中GatewapFilter中“添加请求参数-”:AddRequestParameterGatewayFilterFactory.java

//记录日志

//logger.info("全局参数处理: {} url:{} 参数:{}",method.toString(),sFozGTBZerverHttpRequest.getURI().getRawPath(),newRequestQueryParams.toString());

// 获http://取原参数

URI uri = serverHttpRequest.getURI();

StringBuilder query = new StringBuilder();

String originalQuery = uri.getRawQuery();

if (org.springframework.util.StringUtils.hasText(originalQuery)) {

query.APPend(originalQuery);

if (originalQuery.charAt(originalQuery.length() - 1) != '&') {

query.append('&');

}

}

// 添加查询参数

query.append(ServiceConstants.COMMON_PARAMETER_ENTERPRISEID+"="+authenticationVO.getEnterpriseId()

+"&"+ServiceConstants.COMMON_PARAMETER_USERID+"="+authenticationVO.getUserId());

// 替换查询参数

URI newUri = UriComponentsBuilder.fromUri(uri)

.replaceQuery(query.toString())

.build(true)

.toUri();

ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build();

return chain.filter(exchange.mutate().request(request).build());

POST请求添加参数

//从请求里获取Post请求体

String bodyStr = resolveBodyFromRequest(serverHttpRequest);

String userId = "123";

// 这种处理方式,必须保证post请求时,原始post表单必须有数据过来,不然会报错

if (StringUtils.isEmpty(bodyStr)) {

logger.error("请求异常:{} POST请求必须传递参数", serverHttpRequest.getURI().getRawPath());

ServerHttpResponse response = exchange.getResponse();

response.setStatusCode(HttpStatus.BAD_REQUEST);

return response.setComplete();

}

//application/x-www-form-urlencoded和application/json才添加参数

//其他上传文件之类的,不做参数处理,因为文件流添加参数,文件原格式就会出问题了

/* if (MediaType.APPLICATION_FORM_URLENCODED_VALUE.equalsIgnoreCase(contentType)) {

// 普通键值对,增加参数

bodyStr = String.format(bodyStr+"&%s=%s&%s=%s",ServiceConstants.COMMON_PARAMETER_ENTERPRISEID,authenticationVO.getEnterpriseId()

,ServiceConstants.COMMON_PARAMETER_USERID,authenticationVO.getUserId());

}*/

// 新增body参数

if (MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(contentType)) {

JSONObject jsonObject = new JSONObject(bodyStr);

jsonObject.put("userId", userId);

bodyStr = jsonObject.toString();

}

//记录日志

logger.info("全局参数处理: {} url:{} 参数:{}", method.toString(), serverHttpRequest.getURI().getRawPath(), bodyStr);

//下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值

URI uri = serverHttpRequest.getURI();

URI newUri = UriComponentsBuilder.fromUri(uri).build(true).toUri();

ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build();

DataBuffer bodyDataBuffer = stringBuffer(bodyStr);

Flux bodyFlux = Flux.just(bodyDataBuffer);

// 定义新的消息头

HttpHeaders headers = new HttpHeaders();

headers.putAll(exchange.getRequest().getHeaders());

// 添加消息头

// headers.set(ServiceConstants.SHIRO_SESSION_PRINCIPALS,GsonUtils.toJson(authenticationVO));

// 由于修改了传递参数,需要重新设置CONTENT_LENGTH,长度是字节长度,不是字符串长度

int length = bodyStr.getBytes().length;

headers.remove(HttpHeaders.CONTENT_LENGTH);

headers.setContentLength(length);

// 设置CONTENT_TYPE

if (StringUtils.isEmpty(contentType)) {

headers.set(HttpHeaders.CONTENT_TYPE, contentType);

}

// 由于post的body只能订阅一次,由于上面代码中已经订阅过一次body。所以要再次封装请求到request才行,不然会报错请求已经订阅过

request = new ServerHttpRequestDecorator(request) {

@Override

public HttpHeaders getHeaders() {

long contentLength = headers.getContentLength();

HttpHeaders httpHeaders = new HttpHeaders();

httpHeaders.putAll(super.getHeaders());

if (contentLength > 0) {

httpHeaders.setContentLength(contentLength);

} else {

// TODO: this causes a 'HTTP/1.1 411 Length Required' on httpbin.org

httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");

}

return httpHeaders;

}

@Override

public Flux getBody() {

return bodyFlux;

}

};

//封装request,传给下一级

request.mutate().header(HttpHeaders.CONTENT_LENGTH, Integer.toString(bodyStr.length()));

return chain.filter(exchange.mutate().request(request).build());

/**

* 从Flux中获取字符串的方法

* @return 请求体

*/

private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {

//获取请求体

Flux body = serverHttpRequest.getBody();

AtomicReference bodyRef = new AtomicReference<>();

FozGTBZ body.subscribe(buffer -> {

CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());

DataBufferUtils.release(buffer);

bodyRef.set(charBuffer.toString());

});

//获取request body

return bodyRef.get();

}

/**

* 字符串转DataBuffer

* @param value

* @return

*/

private DataBuffer stringBuffer(String value) {

byte[] bytes = value.getBytes(StandardCharsets.UTF_8);

NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);

DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);

buffer.write(bytes);

return buffer;

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:解决Jenkins集成SonarQube遇到的报错问题
下一篇:做好一网通办宣传活动(做好一网通办宣传活动总结)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~