現(xiàn)象
多個(gè)接口的請(qǐng)求參數(shù)中文偶爾部分亂碼,亂碼位置不固定
分析
- 根據(jù)日志分析,參數(shù)在達(dá)到應(yīng)用服務(wù)時(shí)亂碼,在應(yīng)用服務(wù)前還有Nginx和網(wǎng)關(guān),初步猜測(cè)網(wǎng)關(guān)出問(wèn)題的可能性較大
- 部分亂碼,估計(jì)是字節(jié)級(jí)別的處理問(wèn)題,在網(wǎng)關(guān)項(xiàng)目里全局搜索
stream和byte。經(jīng)過(guò)排查,在一處代碼出現(xiàn)byte轉(zhuǎn)字符串處理,代碼如下
@Override
public Flux<DataBuffer> getBody()
{
Flux<DataBuffer> body = super.getBody();
return body.map(dataBuffer -> {
byte[] content = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(content);
DataBufferUtils.release(dataBuffer);
String bodyStr = new String(content, StandardCharsets.UTF_8);
// 防xss攻擊過(guò)濾
bodyStr = EscapeUtil.clean(bodyStr);
// 轉(zhuǎn)成字節(jié)
byte[] bytes = bodyStr.getBytes();
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
buffer.write(bytes);
return buffer;
});
}
- 當(dāng)請(qǐng)求體過(guò)大時(shí),網(wǎng)關(guān)會(huì)對(duì)請(qǐng)求體進(jìn)行切割,切分為多個(gè)字節(jié)數(shù)組,一個(gè)中文字符占2~3個(gè)字節(jié),如果切割數(shù)組時(shí)恰巧將一個(gè)中文的多個(gè)字節(jié)切分到2個(gè)數(shù)組中(一部分前,一部分后),再將切分后的字節(jié)數(shù)組轉(zhuǎn)字符串時(shí),就會(huì)出現(xiàn)亂碼問(wèn)題。
解決
修改這部分代碼如下
@Override
public Flux<DataBuffer> getBody()
{
Flux<DataBuffer> body = super.getBody();
return body.buffer().map(dataBuffers -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffers);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
DataBufferUtils.release(join);
String bodyStr = new String(content, StandardCharsets.UTF_8);
// 防xss攻擊過(guò)濾
bodyStr = EscapeUtil.clean(bodyStr);
// 轉(zhuǎn)成字節(jié)
byte[] bytes = bodyStr.getBytes();
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
buffer.write(bytes);
return buffer;
});
}
如何復(fù)現(xiàn)
知道問(wèn)題問(wèn)題為什么出現(xiàn),就容易復(fù)現(xiàn)了,只需要將請(qǐng)求體多塞點(diǎn)中文,中文越多,請(qǐng)求體越大,越容易復(fù)現(xiàn)。
后記
項(xiàng)目作者也修復(fù)了這個(gè)問(wèn)題:修復(fù)響應(yīng)體過(guò)大出現(xiàn)的亂碼問(wèn)題