一次使用自定义 Http Header 引发的血案

HttpClient Http Header 自定义 nginx 不转发 

起因

最近在整理我们产品的 OpenAPI Demo (Python、C#、Java),为使各语言 Demo 表现一致,使用同样的测试数据和同样的请求封装方式。

在 Python、C# 都特别顺利写完后,Java 遇到问题了:其中有一个接口返回 HTTP 400 错误,而其他接口都正常

环境

  1. JDK 1.8
  2. JAVA 调用接口使用 Apache HttpClient 4.2.1

排查

疑因1

由于 HTTP 400 Bad Request 很明显的是客户请求不满足服务端的要求,是客户端的问题,所以最先怀疑是客户端参数没传。

经过再三确认后,确认参数传递没有问题。

疑因2

排除疑因1后,有点陷入死局,不知如何下手。最后,有可能是请求通过 nginx 转发时,nginx 破坏了请求,导致应用服务器报 400.

于是,登录服务器,查看 Nginx 日志,发现请求没有被转发,如下图:

与正常的的请求相比,如下图:

未被转发的请求缺少了 Http Header : Host,也就是说错误的请求的 Host Header 被客户端丢弃,通过 Wireshark 抓包也确认是客户端的请求中没有 Host Header

疑因3

通过排除疑因2的过程,明确了问题出在请求调用方,而请求方式都是统一的封装接口,那么最有可能的原因就是请求的参数不一致导致。

于是,逐个去掉该请求的参数,发现其中一个 key 为 “productName”, value 为“测试修改产品名称” 的参数导致。将 value 改为其它值进行测试,发现没有问题,于是逐个去掉 value 的汉字,发现只要去掉“名”字就可测试通过。

这就奇了怪了,为什么有“名”字就测试不通过呢,又为什么其它语言能测试通过?!!!

思考。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

然后,对比有“名”字和无“名”字两次 wireshark 的抓包。

哇哇哇,为什么有“名”字的 Header 有换行

然后,将“名”字转换成 Unicode ,其值为 \u540d

ASCII 转换

然后对照 ASCCI 码表发现,发现 0D 表示“回车键”

ASCCI 码表

至此就清楚了,请求封装的代码将请求数据也放到了 Header ,而恰巧“名”字导致了 Header 头不合规范,从而导致 Host Header 丢失。而对比其它语言的请求封装类,并没有将请求数据放到 Header 中,这也解释了其它语言为什么可以测试通过。

经查 OpenAPI 的协议文档,并没有要求将请求数据放到 Header,而当时为什么这么做了,也无从考查。。。。。。

总结

虽然这次问题解决了,但却花费了半天的时间,在排查问题的时候,还是要再细心一些,多抓包并仔细分析,多对比正常情况与异常情况的不同,可能会事半功倍。

谨记!!!

一次使用自定义 Http Header 引发的血案的更多相关文章

  1. 自定义 Preference Header 布局

    1. Preference Header 概述: 对于什么是 Preference Header,以及何时使用 Preference Header,请参考我的另一篇博文: 何时使用 Preferenc ...

  2. iOS-AFNetworking封装Get(自定义HTTP Header)和Post请求及文件下载

    前面提到AFNetworking是一个很强大的网络三方库,首先你需要引入AFNetworking三方库:如封装的有误还请指出,谢谢! 1.Get请求 /**Get请求 url 服务器请求地址 succ ...

  3. Vuejs中slot实现自定义组件header、footer等

    Vuejs中slot实现自定义组件header.footer等 vue中的slot主要负责内容分发,之前有介绍过slot的内容,具体链接:http://www.cnblogs.com/vipzhou/ ...

  4. Nginx获取自定义头部header的值

    http://blog.csdn.net/xbynet/article/details/51899286?_t=t http://shift-alt-ctrl.iteye.com/blog/23314 ...

  5. [WCF]缺少一行代码引发的血案

    这是今天作项目支持的发现的一个关于WCF的问题,虽然最终我只是添加了一行代码就解决了这个问题,但是整个纠错过程是痛苦的,甚至最终发现这个问题都具有偶然性.具体来说,这是一个关于如何自动为服务接口(契约 ...

  6. 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器

    1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...

  7. dubbox微服务实例及引发的“血案”

    Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成. 主要核心部件: Remoting: 网络通信框架 ...

  8. Integer.parseInt 引发的血案

    Integer.parseInt 处理一个空字符串, 结果出错了, 程序没有注意到,搞了很久, 引发了血案啊!! 最后,终于 观察到了, 最后的部分: Caused by: java.lang.NoC ...

  9. Replication的犄角旮旯(六)-- 一个DDL引发的血案(上)(如何近似估算DDL操作进度)

    <Replication的犄角旮旯>系列导读 Replication的犄角旮旯(一)--变更订阅端表名的应用场景 Replication的犄角旮旯(二)--寻找订阅端丢失的记录 Repli ...

随机推荐

  1. 配置nginx直接使用webpack生成的gz压缩文件,而不用nginx自己压缩

    参考链接:https://blog.csdn.net/ywl570717586/article/details/100011721

  2. [转帖]AARRR已是过去式,而RARRA才是更好的增长黑客模型

    AARRR已是过去式,而RARRA才是更好的增长黑客模型 管理.该方法论已成为了企业家创业的增长利器.但现在看来,AARRR已是过去式. http://www.woshipm.com/operate/ ...

  3. C++常用数据类型和Windows常见数据类型

    一.C++基本的内置类型 C++ 为程序员提供了种类丰富的内置数据类型和用户自定义的数据类型.下表列出了七种基本的 C++ 数据类型: 类型 关键字 布尔型 bool 字符型 char 整型 int ...

  4. [转载]Python 魔法方法详解

    据说,Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围,他们是面向对象的 Python 的一切. 他们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个, ...

  5. 流程控制之 while 循环

    目录 流程控制之while while 条件循环语句 while contine while else while 循环的嵌套 流程控制之while while 条件循环语句 循环就是一个重复的过程 ...

  6. phpexcel 生成大于26列数据

    function excelExport2($fileName = '', $headArr = [], $data = [], $widths=[]) { ob_clean(); // $fileN ...

  7. Java Web ClassLoader工作机制

    一.ClassLoader的作用: 1.类加载机制:父优先的等级加载机制 2.类加载过程 3.将Class字节码重新解析成JVM统一要求的对象格式 二.ClassLoader常用方法 1.define ...

  8. 【原创】大数据基础之Kudu(6)kudu tserver内存占用统计分析

    kudu tserver占用内存过高后会拒绝部分写请求,日志如下: 19/06/01 13:34:12 INFO AsyncKuduClient: Invalidating location 34b1 ...

  9. std::list保存大量数据时,类型即是无析构函数,该list析构时会占用大量CPU

    std::list保存大量数据时,类型即是无析构函数,该list析构时会占用大量CPU

  10. otter+canal

    https://blog.csdn.net/u011142688/article/details/52046928 https://blog.csdn.net/chenzeyuczy/article/ ...