使用工具(Postman)能调通但使用代码调不通的问题分析及解决方法

本文分析了一种常见问题:使用Feign调用第三方接口时返回500错误,通过调整日志级别至debug,发现报文大小写转换问题,最终通过手动填充字段解决了问题。

问题描述

在和第三方对接开发接口的时候,出现了一个问题,即使用Postman发送报文过去给对方,对方能够返回结果过来,但是使用代码发送报文过去,却返回500错误。首先排除不是调用地址的问题,然后再排除不是调用方式的问题(即post请求变为了get请求)。然后再看看是不是报文内容有所不同,但是在代码里面报文发送之前就已经有日志打印了,发现报文内容和Postman里面是一模一样,那问题到底出现在哪里呢?

问题分析

找对方的人沟通,我代码发送请求给对方时,让他们看看他们收到的报文内容。结果傻眼了,用Postman发送报文的时候,他们的日志能正常显示接收到的报文,但是用代码发送报文的时候,对方日志显示的是“接收到的报文内容为null”。这就说明了用代码调他们是能够调通的,但是我代码调用过程中发送给他们的报文有问题,结果他们收到了null的报文(姑且这么认为)。通过询问公司的大佬们,了解到可以使用查看Feign的debug级别的日志查看具体发送了什么内容。

解决问题

设置Feign的日志级别为debug

这个过程分为三部

1.创建一个配置类

@Configuration
public class FeignConfiguration {

    @Bean
    Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }

}

2.feign客户端的设置

@FeignClient(name = "${query.name}", configuration = FeignConfiguration.class)
public interface QueryClient {

    @PostMapping(value = "/Service/call")
    String getQueryData(@RequestBody JSONObject jsonObject);

}

这一步其实就是把配置类的属性加入到客户端的设置中,即configuration = FeignConfiguration.class这段代码

3.yml文件中加入

logging:
  level:
    com.foreign.feign.QueryClient: debug

4.最后在全局日志设置里面把控制台的日志级别设置为debug,不然就算fegin日志级别设置为debug了也是看不到debug日志的

查看日志

于是重启工程,再次发送报文给对方,然后在debug日志中发现了这么一块日志(日志有所删除,只保留核心部分)

DEBUG o.s.c.o.support.SpringEncoder - Writing [{"SERVICE":{"SERVICE_HEADER":{"SUB_TERMINAL_TYPE":"Android","VERSION_ID":"01","CHANNEL_ID":"BANK","ORG":"15601","SERVICESN":"APP2020052116583861818","OP_ID":"001","SERVICE_ID":"LoanQueryByCust","ACQ_ID":"10000000","REQUEST_TIME":"20200521165838","MAC":""},"SERVICE_BODY":{"REQUEST":{"CUST_NAME":"王大大3","ID_NO":"340602198512141876","PRODUCT_CODE":"6001","PRODUCT_GROUP":"KX001","QUERY_RANGE_IND":"01"}}}}] using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@2e3c5ecc]
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] ---> POST http://29.23.35.3:31006/nmsRpcNonfinService/call HTTP/1.1
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] Content-Length: 409
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] Content-Type: application/json;charset=UTF-8
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] X-CMSP-ApiRsskey: OGY5MDQwZmZjNzdhNDQ1N2FhYWZkNWEzNjcyYjZlZjUxNTcwNTg1NzgzMzc3
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] X-CMSP-ApplicantCode: T134505761.NMS001.S00001
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] X-CMSP-ClientServiceCode: aas-foreign-1
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] X-CMSP-ClientServiceVersion: v1.0
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] 
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] {"SERVICE":{"SERVICE_HEADER":{"SUB_TERMINAL_TYPE":"Android","VERSION_ID":"01","CHANNEL_ID":"BANK","ORG":"15601","SERVICESN":"APP2020052116583861818","OP_ID":"001","SERVICE_ID":"LoanQueryByCust","ACQ_ID":"10000000","REQUEST_TIME":"20200521165838","MAC":""},"SERVICE_BODY":{"REQUEST":{"query_RANGE_IND":"01","product_CODE":"6001","cust_NAME":"王大大3","product_GROUP":"KX001","id_NO":"340602198512141876"}}}}
DEBUG c.s.foreign.feign.QueryClient - [QueryClient#getQueryData] ---> END HTTP (409-byte body)

可以看到,我用代码发送的报文内容并不是对方日志所收到的null,在这里推测一下,对方日志打印的并不是接收到的原始报文而是经过各种判断处理后的报文内容。可能我发送的报文格式不对导致对面处理报文时判断出报文内容不正确,于是对面就草草的打印了一个接收到的报文内容为null的日志。同时对面不会处理异常,按理说即使我的报文内容有误,也不应该返回一个500错误过来而是返回一个类似于“报文内容不正确”的信息给我。哎,对面的代码编写不规范啊。

言归正传,经过仔细查看这个段日志,我发现了这段日志的第一行和倒数第二行的报文内容不一样了,有部分的大写变成小写了

{"CUST_NAME":"王大大3","ID_NO":"340602198512141876","PRODUCT_CODE":"6001","PRODUCT_GROUP":"KX001","QUERY_RANGE_IND":"01"}

{"query_RANGE_IND":"01","product_CODE":"6001","cust_NAME":"王大大3","product_GROUP":"KX001","id_NO":"340602198512141876"}

那么为什么会这样呢,我分析是因为这部分内容导致的

using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@2e3c5ecc]

即我的报文又经过了MappingJackson2HttpMessageConverter它的重新编码,导致了部分大写变成小写了

报文出错原因分析

那么为什么就只有这一部分的报文内容大写变成了小写而且是下划线的前段部分?是不是因为这部分的报文内容是通过查询数据库把数据放经javabean,然后再把javabean转换为JsonObject之后导致的?

于是便不用javabean转换为JsonObject的方式,而是把字段值一个一个put进去的方式,结果把这部分代码改了之后,发现,有结果返回了!

总结

1.首先报文的内容最好不要用大写字母,对方要求报文内容全部是大写,这就很离谱

2.作为服务方,首先需要把接收到的原始报文打印出来

3.异常处理要规范,像这种报文内容不正确的情况,不应该直接抛出异常而是需要返回一个错误结果给调用方

4.要是报文内容有大写的,最好是手动put字段值

5.可以开启debug级别的日志查看我们自己到底发送了什么报文过去

 

<think>嗯,用户问的是Postman,但用Python写requests的时候报错。这个问题其实挺常见的,我得一步一步帮他们理清楚可能的原因。首先,得确认用户是否正确地复制了请求的各个部分。Postman有时候会自动加一些头信息,比如Content-Type或者User-Agent,如果Python代码没加,可能会出问题。 然后,可能需要检查URL是否正确。有时候Postman用了环境变量或者全局变量,而Python代码直接写死了,导致URL对。另外,路径参数或者查询参数有没有正确传递,比如Postman可能用了动态生成的参数,而Python代码没有处理这些动态部分。 接下来,请求方法是否正确。虽然用户可能知道用POST或GET,但有时候小心写错了方法,比如该用POST却用了GET,或者反过来。另外,请求体的格式是否正确,比如JSON、表单数据或者文件上传。Postman会自动设置Content-Type,但Python中需要手动指定,然服务器可能无法解析。 还有可能需要处理Cookie或者Session。如果Postman保存了Cookie,而Python代码没处理,会导致认证失败。这时候可能需要用Session对象来保持会话,或者在headers手动添加Cookie。 SSL证书验证也是一个常见的问题。有些服务器证书可能有问题Postman默认验证,但Python的requests库会验证。这时候可以加上verify=False参数过得提醒用户注意安全。 重定向处理也可能导致问题Postman可能自动处理重定向,而Python代码可能需要手动设置allow_redirects=True。另外,服务器返回的响应结构可能和预期同,比如错误处理没做好,需要打印出来看看状态码和内容。 最后,建议用户对比请求的具体细节,用工具抓包或者打印请求信息,确保Python代码Postman的请求完全一致。同时,分步骤测试,先发简单的请求,再逐步加上参数、头信息等,方便定位问题所在。</think>我帮你分析Postman但Python代码报错的常见原因解决方案,请按以下步骤排查: --- ### 一、基础信息核对 1. **请求头(Headers)差异** - Postman自动携带`Content-Type`/`User-Agent`等头信息 - Python需手动添加: ```python headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer your_token' } ``` 2. **URL准确性验证** - 检查是否包含环境变量(如`{{base_url}}`) - 确认路径参数是否替换: ```python # Postman中的动态路径 /users/:id url = "https://api.com/users/123" # 必须替换实际值 ``` --- ### 二、请求体对比排查 1. **数据格式匹配** - JSON格式需明确指定: ```python import json data = {'key': 'value'} requests.post(url, data=json.dumps(data), headers=headers) # 错误方式 requests.post(url, json=data, headers=headers) # 正确方式(自动处理JSON) ``` 2. **表单数据特殊处理** - 使用`data`参数并设置`Content-Type`: ```python headers['Content-Type'] = 'application/x-www-form-urlencoded' data = {'username': 'admin', 'password': '123'} requests.post(url, data=data, headers=headers) ``` --- ### 三、证书与会话问题 1. **SSL证书验证** - 临时关闭验证(生产环境慎用): ```python requests.get(url, verify=False) ``` 2. **Cookie处理** - 使用Session保持状态: ```python with requests.Session() as s: s.get(login_url) s.post(api_url, data=payload) ``` --- ### 四、高级试技巧 1. **请求对比工具** - 在Postman点击**Code**按钮生成Python代码 - 对比与自己代码的差异 2. **网络抓包分析** - 使用Wireshark/Fiddler捕获真实请求 - 对比Python发送的请求特征 --- ### 五、常见错误示例 1. **SSL相关错误** ```python requests.exceptions.SSLError # 添加verify=False或安装证书 ``` 2. **超时问题** ```python requests.get(url, timeout=10) # 显式设置超时时间 ``` 3. **编码问题** ```python response.encoding = 'utf-8' # 强制指定响应编码 ``` --- ### 六、终极试方案 1. 打印完整请求信息: ```python import requests from requests_toolbelt.utils import dump def logging_hook(response, *args, **kwargs): data = dump.dump_all(response) print(data.decode('utf-8')) requests.get(url, hooks={'response': logging_hook}) ``` 建议从最简单的GET请求开始测试,逐步添加参数/头信息,直到复现错误。多数问题源于头信息缺失、数据格式错误或证书验证机制差异。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值