Flask查询Redis不存在键未返回404,反而返回200的问题求助
Redis透明代理Flask应用404状态码返回异常排查
问题描述
开发Redis透明代理的Python Flask应用时,查询Redis中不存在的键,预期返回404响应状态码,但实际始终返回200。
应用路由代码
from flask import Flask, request, jsonify import redis app = Flask(__name__) redis_client = redis.StrictRedis(host = 'localhost', port=6379, db=0) @app.route('/get/<key>', methods= ['GET']) def get_data(key): value = redis_client.get(key) if value: return jsonify({'key': key, 'value': value.decode('utf-8')}) else: return jsonify({'message': 'Key not found'}, 404) if __name__ == '__main__': app.run()
测试代码
import unittest from flask import Flask, jsonify import redis from redis_proxy import app class RedisProxyTest(unittest.TestCase): def setUp(self): self.app = app.test_client() def test_get_data(self): redis_client = redis.StrictRedis(host='localhost', port=6379, db=0) redis_client.set('test_key', 'test_value') response = self.app.get('/get/test_key') self.assertEqual(response.status_code, 200) expected_data = {'key': 'test_key', 'value': 'test_value'} self.assertEqual(response.get_json(), expected_data) def test_get_data_key_not_found(self): response = self.app.get('/get/xxx') print(response.data) print(response.status_code) self.assertEqual(response.status_code, 404) expected_data = {'message': 'Key not found'} self.assertEqual(response.get_json(), expected_data) if __name__ == '__main__': unittest.main()
测试输出
python3 -m unittest redis_proxy_test.py .b'[{"message":"Key not found"},404]\n' 200 F ====================================================================== FAIL: test_get_data_key_not_found (redis_proxy_test.RedisProxyTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/redis-proxy/redis_proxy_test.py", line 26, in test_get_data_key_not_found self.assertEqual(response.status_code, 404) AssertionError: 200 != 404 ---------------------------------------------------------------------- Ran 2 tests in 0.006s FAILED (failures=1)
Redis验证结果
127.0.0.1:6379> GET xxx (nil)
排查思路与解决方案
问题根源:从测试输出的
response.data可以看到,404被包含在了JSON响应体中(返回内容为[{"message":"Key not found"},404]),而没有被设置为HTTP响应状态码。这是因为Flask的jsonify()函数仅接受需要序列化的JSON数据作为参数,直接将状态码作为第二个参数传入jsonify(),会被当成JSON数据的一部分处理,而非设置HTTP状态码。修复方法:修改应用路由中
else分支的返回语句,将状态码作为返回元组的第二个元素:
else: return jsonify({'message': 'Key not found'}), 404
这样Flask会将第一个值作为响应体,第二个值作为HTTP状态码返回,符合预期。
- 验证:修改后重新运行测试,
test_get_data_key_not_found会返回404状态码,响应体为{"message":"Key not found"},测试通过。
内容的提问来源于stack exchange,提问作者Steven Smith
相关产品推荐
相关产品推荐

