如何配置Flask应用仅接受Content-Type: text/plain请求头
Hey there! Let's get your Flask app set up to only accept text/plain requests and fix that annoying 500 error. Here's what's going wrong and how to fix it step by step:
问题根源
Right now, your code relies on request.get_json() which only works when the request has Content-Type: application/json. When a request comes in with any other content type (like text/plain), get_json() returns None—and trying to access data['kategori'] throws a KeyError, which triggers the 500 internal server error.
修复步骤
1. 强制验证Content-Type请求头
First, add a check to make sure incoming requests have the correct Content-Type header. If they don't, return a clear 400 Bad Request error instead of letting the app crash.
2. 正确读取text/plain请求体
Instead of get_json(), use request.get_data(as_text=True) to read the raw plain text content. How you parse this text depends on the format your clients will send—let's cover two common scenarios:
场景A:请求体是JSON格式但Content-Type为text/plain
If your clients are sending JSON strings but setting Content-Type: text/plain, you can manually parse the text into a Python dictionary:
from flask import Flask, request from flask_restful import Api, Resource from flask_cors import CORS from flask_sqlalchemy import SQLAlchemy import json app = Flask(__name__) api = Api(app) cors = CORS(app) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' db = SQLAlchemy(app) class Priser(db.Model): pris = db.Column(db.Integer, primary_key=True) kategori = db.Column(db.Text) class getPriser(Resource): def post(self): # 检查请求头是否为text/plain if request.content_type != 'text/plain': return {'error': 'Only Content-Type: text/plain is allowed'}, 400 # 读取纯文本请求体 raw_text = request.get_data(as_text=True) try: # 将纯文本解析为JSON格式 data = json.loads(raw_text) except json.JSONDecodeError: return {'error': 'Invalid JSON format in plain text body'}, 400 # 验证必要字段是否存在 if 'kategori' not in data or 'pris' not in data: return {'error': 'Missing required fields: kategori and pris'}, 400 # 确保pris是整数类型 try: pris_value = int(data['pris']) except ValueError: return {'error': 'pris must be an integer'}, 400 # 创建并保存数据库记录 newPris = Priser(kategori=data['kategori'], pris=pris_value) db.session.add(newPris) db.session.commit() # 返回201状态码(符合RESTful最佳实践) return {'kategori': newPris.kategori, 'pris': newPris.pris}, 201 api.add_resource(getPriser, '/getpriser') if __name__ == '__main__': with app.app_context(): db.create_all() # 确保启动时创建数据库表 app.run(debug=True)
场景B:请求体是自定义纯文本格式(比如键值对)
If your clients send something like kategori=Electronics;pris=100 (a custom plain text format), replace the parsing part with this:
# 在getPriser的post方法中替换解析逻辑 raw_text = request.get_data(as_text=True) data = {} try: for pair in raw_text.split(';'): key, value = pair.split('=') data[key.strip()] = value.strip() except ValueError: return {'error': 'Invalid plain text format. Use "kategori=xxx;pris=xxx"'}, 400 # 后续的字段验证和保存逻辑和上面一致
额外优化点
- Added explicit error handling for invalid formats and missing fields, so clients get clear feedback instead of generic 500 errors.
- Wrapped
db.create_all()in an app context to ensure the database table is created correctly on app startup. - Returned a 201 Created status code when the record is successfully added—this is standard for resource creation in REST APIs.
内容的提问来源于stack exchange,提问作者Kresten




