使用protobuf定义的接口api发起http请求报错,日志如下:

[-- ::] DEBUG AbstractPool: - server updated, node=10.211.95.79:, server={ node: 10.211.95.79:, hostname: 10.211.95.79, port: , status: , weight: , capacity: , breaker: { state :CLOSED, working: , delay: , failureThreshold: [/, 0.8], successThreshold: [/, 0.75]}, version:  }
[-- ::] DEBUG EnvironmentInterceptor: - EnvironmentInterceptor.preHandle requesturl:http://127.0.0.1:8080/ms-search-war/ms.search.searchService/getSearchRank
[-- ::] DEBUG EnvironmentInterceptor: - RequestHeads,User-Agent=Apache-HttpClient/4.1. (java 1.5),X-Identity-ID=,X-Auth-Token=,X-Login-Type=
[-- ::] ERROR ServletRequestParser: - IOException: request=/ms-search-war/ms.search.searchService/getSearchRank, ex=java.nio.charset.MalformedInputException: Input length =
[-- ::] DEBUG EnvironmentInterceptor: - EnvironmentInterceptor completed, requesturl= http://127.0.0.1:8080/ms-search-war/ms.search.searchService/getSearchRank and server delayTime = 141

  我们来看ServletRequestParser的报错代码行:

import java.io.IOException;
import java.math.BigDecimal;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import com.google.protobuf.ByteString;
import com.google.protobuf.Descriptors;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
public class ServletRequestParser {
private static final Logger logger = LoggerFactory.getLogger(ServletRequestParser.class); public static Message parse(HttpServletRequest request, Message prototype) {
String requestMethod = request.getMethod();
Descriptors.Descriptor inputType = prototype.getDescriptorForType();
Message.Builder builder = prototype.newBuilderForType();
if (HttpMethod.POST.matches(requestMethod)) {
MediaType contentType = ContentType.BINARY;
try {
contentType = MediaType.valueOf(request.getContentType());
} catch (Exception ex) {
}
try {
if (ContentType.isProtobuf(contentType) || ContentType.isBinary(contentType)) {
return builder.mergeFrom(request.getInputStream()).build();
} else if (ContentType.isJson(contentType)) {
request.setCharacterEncoding("utf-8");
JsonFormat.parser().merge(request.getReader(), builder);
return builder.build();
} else {
logger.error("invalid content-type: {}", contentType);
}
} catch (InvalidProtocolBufferException ex) {
logger.error("InvalidProtocolBuffer: request={}, ex={}", request.getRequestURI(), ex);
} catch (IOException ex) {
logger.error("IOException: request={}, ex={}", request.getRequestURI(), ex);
}
} else if (HttpMethod.GET.matches(requestMethod)) {
for (Descriptors.FieldDescriptor field : inputType.getFields()) {
String[] values = request.getParameterValues(field.getName());
if (null != values && values.length > 0) {
if (!field.isRepeated()) {
Object o = parseFieldValue(field, values[0], builder);
if (null != o) builder.setField(field, o);
} else {
for (String value : values) {
Object o = parseFieldValue(field, value, builder);
if (null != o) builder.addRepeatedField(field, o);
}
}
}
}
return builder.build();
}
return null;
}

  这里调用了com.google.protobuf.util.JsonFormat的内部类Parser的merge方法进行转换时报错,因为异常只在这里抛出,所以只能怀疑获取Reader对象的这个request.getReader()方法,跟进代码:

/**
* Wrapper object for the Coyote request.
*
* @author Remy Maucherat
* @author Craig R. McClanahan
*/
public class Request implements org.apache.catalina.servlet4preview.http.HttpServletRequest {
/**
* Read the Reader wrapping the input stream for this Request. The
* default implementation wraps a <code>BufferedReader</code> around the
* servlet input stream returned by <code>createInputStream()</code>.
*
* @return a buffered reader for the request
* @exception IllegalStateException if <code>getInputStream()</code>
* has already been called for this request
* @exception IOException if an input/output error occurs
*/
@Override
public BufferedReader getReader() throws IOException { if (usingInputStream) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getReader.ise"));
} usingReader = true;
inputBuffer.checkConverter();
if (reader == null) {
reader = new CoyoteReader(inputBuffer);
}
return reader; }

  这里调用的是catalina的Requst对象的getReader方法,返回的是一个BufferedReader对象,这里最终实例化出了一个CoyoteReader对象。

    /**
     * Reader.
     */
    protected CoyoteReader reader = new CoyoteReader(inputBuffer);

  我们来看下CoyoteReader对象:  

/**
* Coyote implementation of the buffered reader.
*
* @author Remy Maucherat
*/
public class CoyoteReader
extends BufferedReader { // -------------------------------------------------------------- Constants private static final char[] LINE_SEP = { '\r', '\n' };
private static final int MAX_LINE_LENGTH = 4096; // ----------------------------------------------------- Instance Variables protected InputBuffer ib; protected char[] lineBuffer = null; // ----------------------------------------------------------- Constructors public CoyoteReader(InputBuffer ib) {
super(ib, 1);
this.ib = ib;
} }

  再看下它里面的InputBuffer对象:

/**
* The buffer used by Tomcat request. This is a derivative of the Tomcat 3.3
* OutputBuffer, adapted to handle input instead of output. This allows
* complete recycling of the facade objects (the ServletInputStream and the
* BufferedReader).
*
* @author Remy Maucherat
*/
public class InputBuffer extends Reader
implements ByteChunk.ByteInputChannel, ApplicationBufferHandler { /**
* The string manager for this package.
*/
protected static final StringManager sm = StringManager.getManager(InputBuffer.class); private static final Log log = LogFactory.getLog(InputBuffer.class); public static final int DEFAULT_BUFFER_SIZE = 8 * 1024; // The buffer can be used for byte[] and char[] reading
// ( this is needed to support ServletInputStream and BufferedReader )
public final int INITIAL_STATE = 0;
public final int CHAR_STATE = 1;
public final int BYTE_STATE = 2; /**
* Encoder cache.
*/
private static final ConcurrentMap<Charset, SynchronizedStack<B2CConverter>> encoders = new ConcurrentHashMap<>(); // ----------------------------------------------------- Instance Variables /**
* The byte buffer.
*/
private ByteBuffer bb; /**
* The char buffer.
*/
private CharBuffer cb; /**
* State of the output buffer.
*/
private int state = 0; /**
* Flag which indicates if the input buffer is closed.
*/
private boolean closed = false; /**
* Encoding to use.
*/
private String enc; /**
* Current byte to char converter.
*/
protected B2CConverter conv; /**
* Associated Coyote request.
*/
private Request coyoteRequest; /**
* Buffer position.
*/
private int markPos = -1; /**
* Char buffer limit.
*/
private int readLimit; /**
* Buffer size.
*/
private final int size; // ----------------------------------------------------------- Constructors /**
* Default constructor. Allocate the buffer with the default buffer size.
*/
public InputBuffer() { this(DEFAULT_BUFFER_SIZE); } /**
* Alternate constructor which allows specifying the initial buffer size.
*
* @param size Buffer size to use
*/
public InputBuffer(int size) { this.size = size;
bb = ByteBuffer.allocate(size);
clear(bb);
cb = CharBuffer.allocate(size);
clear(cb);
readLimit = size; } }

  通过调试发现,当我的请求里没有中文时,CoyoteReader对象的InputBuffer属性的ByteBuffer的hb属性是能取到请求消息体的,而包含了中文则无法获取,protobuf直接转换报错了。

protobuf接口调用报错:java.nio.charset.MalformedInputException: Input length = 1的更多相关文章

  1. scala文件读取报错“java.nio.charset.MalformedInputException: Input length = 1”

    今天写spark程序的时候遇到了一个问题就是,读取文件的时候报了一个错:“Exception in thread "main" java.nio.charset.Malformed ...

  2. windows中文编码报错 com.google.gson.JsonIOException: java.nio.charset.MalformedInputException: Input length = 1

    昨天碰到一个问题:同一个请求页面,页面经过匹配后调用http的post协议接口,部署在linux环境的没问题,本地Eclipse启动的tomcat也没问题,直接启动本地tomcat却报错了: 18:4 ...

  3. org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1

    项目启动报错2018-12-21 14:06:24.917 INFO 23472 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refr ...

  4. 我的Java开发学习之旅------>Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常

    今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常, ...

  5. Caused by: java.nio.charset.MalformedInputException: Input length = 1

    java.lang.IllegalStateException: Failed to load property source from location 'classpath:/applicatio ...

  6. [bug] org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 2

    原因 SpringBoot启动加载yml配置文件出现编码格式错误 参考 https://www.pianshen.com/article/2431144034/

  7. 转载:回编译APK出错:java.nio.char set.MalformedInputException: Input length = 1

    使用APKtool回编译APK,出现错误如下:    Exception in thread "main" org.yaml.snakeyaml.error.YAMLExcepti ...

  8. dubbo 使用zookeeper 出现 Dubbo客户端调用报错NullPointerException

    现在将网上的方法总结一下 方法一:.https://blog.csdn.net/u011294519/article/details/81810631 dubbo-provider.xml:提供者先扫 ...

  9. springcloud采坑--Zuul上传文件报java.nio.charset.IllegalCharsetNameException: UTF-8;boundary=sqgzzmMxl1UPdIp0IAYnQgUIAr9yNewVAzKIX

    报错日志: 2018-12-17 10:01:19,688 ERROR [io.undertow.request] (default task-3) UT005023: Exception handl ...

随机推荐

  1. HDU 4665 Mutiples on a circle (圆环DP)

    题意 N个数的圆环上有多少种方案可以使得选出来的一段数是K的倍数(N<=50000, K<=200, a[i]<=1000). 思路 多校第七场1004.圆上的DP--大脑太简单处理 ...

  2. python类常用装饰器

    class Myclass(object): def __init__(self): pass #必须实例化才能调用 def sayhi(self): print 'hello' #静态方法,跟类没什 ...

  3. FlashFXP 4.3.1 注册码

    FlashFXP 4.3.1 注册码 --------start--------- FLASHFXPwQAOlhkgwQAAAAC6W5MNJwTnsl73nIraAU149tnCQS0hmZU3GG ...

  4. linux---tar命令,vim编辑器,磁盘分区,挂载,链接

    1) 将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) [root@bogon ~]# cp /etc/passwd ./ [root@bogon ~]# cp /etc/ ...

  5. 安装magento主题模板

    magento 的强大功能自不必说, 另外还有一点更重要的是拥有很多顶级的精致模板开发者和爱好者的支持开发出种类繁多, 用途各异的模板, 深受用户的喜爱, 但是安装模板对于初次使用者或者很久没有使用者 ...

  6. 基于centos的docker安装

    1. 安装需求 内核版本3.10以上 Centos 7以上 64位版本 2. 使用root登录或者具有sudo权限 3. 确保系统是最新的 yum update 4. 添加yum源 tee /etc/ ...

  7. 块级元素display:inline-block 在IE6 IE7无效

    ie6,ie7中,对块级元素设置display:inline-block,无效. 所以要先设置为inline,再触发haslayout .div1{ /*重点代码开始*/ display: inlin ...

  8. DRF中两大视图基类APIView/GenericAPIView的介绍

    (1)APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类,继承自Django的View父类. APIView与V ...

  9. Oracle 对比两张表不一样 的数据

    闲来无事,更一片博客,前几天有一个项目中有一个需求,用户通过excel导入数据,由于是通用的导入,所以导入的列的类型都为varchar,所以需要建一张中间表,使其列都为varchar类型,然后通过存储 ...

  10. linux中的网络基础

    ifconfig -a 查看所有网口ifconfig eth 查看具体网口 ifup ethoifdown etho 网卡配置文件/etc/sysconfig/networkk-scripts/ifc ...