大家好,我是烤鸭:
     记一次 由 HttpsURLConnection 引起的返回值400的错误。
1. 场景复现
      今天线上调用第三方接口的时候突然报错了。
      严格来说也不是报错,就是发的请求不通了,http报400的错误。
      问了下对接方,也没有改代码,我们这边也没什么大的改动。
      奇了怪了。。。
      这是请求原来的代码
HttpsURLConnection conn = (HttpsURLConnection) reqURL.openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Accept", "*/*");
conn.setRequestProperty("User-Agent", "stargate");
conn.setRequestProperty("Content-Type", "application/json");
OutputStreamWriter osw = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
osw.write(reqStr);
osw.flush();
osw.close();这是改动的地方,加了句log。
OutputStreamWriter osw = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
log.info("【返回值】"+conn.getResponseCode());
osw.write(reqStr);
osw.flush();
osw.close();2. 寻找问题
     把改动的地方逐步还原,最后发现是log的问题。
     log是没有问题,问题在于 conn.getResponseCode()。
     conn.getOutputStream() 获取连接的输出流,准备向对方发送(写入)数据的时候,
     调用conn.getResponseCode() 报错。为什么呢。一步步看。

getInputStream方法中调用的是getInputStream0()。
public synchronized InputStream getInputStream() throws IOException {this.connecting = true;SocketPermission var1 = this.URLtoSocketPermission(this.url);if (var1 != null) {try {return (InputStream)AccessController.doPrivilegedWithCombiner(new PrivilegedExceptionAction<InputStream>() {public InputStream run() throws IOException {return HttpURLConnection.this.getInputStream0();}}, (AccessControlContext)null, var1);} catch (PrivilegedActionException var3) {throw (IOException)var3.getException();}} else {return this.getInputStream0();}}getInputStream0方法中
    
     if setDoInput(true)
     if else 抛出rememberedException异常
     if else 输入流不为空
     else 输出的方式是否是流的形式
     往对应的服务器写一段文字,主要调用的是这个方法
    writeRequests,看是否正常响应,响应后关闭流。
     看到这大概就明白了。
3. 总结
     调用 conn.getOutputStream() 获取连接的输出流,等待内容写入。(连接是阻塞的,BIO)
     此时调用 conn.getResponseCode() 会向服务器写入其他的东西(一个8192byte的字符串),
     写入完成后,flush 再close。这时对接方的服务器发现获取到的东西并不是指定格式传输的内容,
     就报400了。
关于400的说明—— HTTP 400 错误 - 请求无效 (Bad request);出现这个请求无效报错说明请求没有进入到后台服务里
    https://www.cnblogs.com/beppezhang/p/5824986.html
     不能忽略每一次小的改动。一句小小的log都可能导致问题,还有就是要多测试。