本地Python脚本无法请求ECS上的Flask服务,但Postman可正常访问
本地Python脚本POST请求ECS Flask接口无响应,Postman却正常的排查方向
在ECS上部署了Flask服务,通过本地Python脚本用requests或http.client发送POST请求到/infr接口时,请求完全未到达ECS(服务日志无相关记录),但网页版、本地版Postman发送相同请求却能成功,以下是可能的原因及排查步骤:
Flask服务代码
import flask app = flask.Flask(__name__) @app.route("/infr", methods=["POST"]) def transformation(): # 业务逻辑代码 pass if __name__ == '__main__': app.run(host='0.0.0.0', port=8080)
本地Python脚本1(http.client实现)
def exec_task(task, out): import http.client import json url = "<ecs-public-ip>" port = 8080 endpoint = "/infr" conn = http.client.HTTPConnection(url, port) headers = {"Content-Type": "application/json", "Connection": "keep-alive"} data = { "task": { "bucket": task.bucket, "prefix": task.prefix, "metadata": task.metadata } } payload = json.dumps(data) conn.request("POST", endpoint, body=payload, headers=headers) response = conn.getresponse() if response.status == 200: print("\nRequest successful") response_data = json.loads(response.read().decode()) out.put(ProcessedTask(bucket=task.bucket, prefix=task.prefix, metadata=response_data)) else: print("\nRequest failed") conn.close()
本地Python脚本2(requests实现)
def exec_task(task, out): import requests url = "http://<ecs-public-ip>:8080/infr" data = {"task": { "bucket": task.bucket, "prefix": task.prefix, "metadata": task.metadata }} print("sending: " + str(data)) headers = {"Content-Type": "application/json", "Connection": "keep-alive"} response = requests.post(url, json=data, headers=headers) if response.status_code == 200: print("\nRequest successful") response_data = response.json() out.put({ProcessedTask(bucket=task.bucket, prefix=task.prefix, metadata=response_data)}) else: print("\nRequest failed")
Postman配置说明
- 请求方法:POST
- 请求地址:
http://<ecs-public-ip>:8080/infr - 请求头:
Content-Type: application/json - 请求体:选择raw格式、JSON类型,内容结构与Python脚本中的
data一致
(注:实际使用8080端口,之前误删该信息)
可能的原因及排查步骤
1. 本地网络代理/防火墙差异
- Python脚本默认使用系统代理,而Postman可能关闭了代理。可以在脚本中强制禁用代理:
- requests脚本:添加
proxies={"http": None, "https": None}参数到post方法 - http.client脚本:在创建连接后添加
conn.set_tunnel(None)
- requests脚本:添加
- 本地安全软件/防火墙拦截了Python脚本的出站请求,但放行Postman。可以临时关闭安全软件测试,或检查防火墙规则。
2. 请求头/请求体的细微冲突
- requests脚本冗余头问题:使用
json=data参数时,requests会自动添加Content-Type: application/json,手动重复添加可能导致服务器拒绝请求。可以去掉手动设置的该头:headers = {"Connection": "keep-alive"} response = requests.post(url, json=data, headers=headers) - 序列化异常:检查
task.metadata是否包含不可JSON序列化的对象(如datetime),Postman手动输入的是合法JSON,但脚本序列化失败导致请求未正常发送。可添加print(payload)(http.client脚本)或print(requests.models.JSONEncoder().encode(data))(requests脚本)验证JSON格式。
3. ECS端的请求特征拦截
- ECS安全组/防火墙可能针对User-Agent做了限制:Postman默认UA为
PostmanRuntime/xxx,而Python脚本的UA是python-requests/xxx或Python-urllib/xxx。可以在脚本中模拟Postman的UA:# requests脚本示例 headers = {"Content-Type": "application/json", "User-Agent": "PostmanRuntime/7.32.3"}
4. Flask日志配置不全
- 确认Flask日志是否记录了所有请求,可开启DEBUG模式和详细日志:
同时检查ECS系统日志(如import logging logging.basicConfig(level=logging.DEBUG) app.run(host='0.0.0.0', port=8080, debug=True)/var/log/messages或反向代理日志),看是否有请求被拦截的记录。
5. 脚本异常未被捕获
- 脚本发送请求时可能抛出异常(如连接超时、DNS解析失败)但未处理,导致请求未发送就崩溃。添加异常捕获:
# http.client脚本示例 try: conn = http.client.HTTPConnection(url, port) conn.request("POST", endpoint, body=payload, headers=headers) response = conn.getresponse() # 后续逻辑 except Exception as e: print(f"请求发送失败:{str(e)}") finally: conn.close()
内容的提问来源于stack exchange,提问作者Benny Semyonov
相关产品推荐
相关产品推荐

