Postman可正常发送POST请求,axios/fetch却失败(Lumen+React)
看起来你遇到的问题是前端React通过fetch发送POST请求时,后端Lumen无法正确解析请求体,导致数据库字段为空,但Postman却能正常工作。我来帮你一步步排查解决:
1. 先排查后端请求解析问题
你的日志显示$request->all()为空,但Postman请求正常,这说明Lumen在处理前端的JSON请求时没有正确解析请求体。可以先在createEvent方法里添加日志查看原始请求内容:
public function createEvent(Request $request){ // 添加这两行日志,查看请求原始内容和解析结果 \Log::warning('Raw Request Body: ' . $request->getContent()); \Log::warning('Parsed Request Data: ' . print_r($request->all(), true)); // 你的原有代码... }
如果Raw Request Body能看到前端发送的JSON字符串,但Parsed Request Data是空数组,说明Lumen没有启用JSON解析的必要中间件。
打开bootstrap/app.php,确保全局中间件包含以下内容:
$app->middleware([ Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, Illuminate\Routing\Middleware\SubstituteBindings::class, ]);
这些中间件负责解析请求体、处理空字符串等,Lumen默认可能只启用了CheckForMaintenanceMode,补充其他中间件后应该能正确解析JSON。
2. 调整前端fetch请求的配置
虽然你已经设置了content-type,但可以做两个小调整,确保请求符合标准:
- 把请求头的键改为标准的驼峰格式(HTTP头不区分大小写,但部分服务器对格式敏感)
- 添加
credentials: 'same-origin'确保会话相关信息(如果有的话)被正确传递 - 手动将moment日期对象转换为ISO字符串(避免JSON.stringify可能的意外)
修改后的fetch代码:
let event = { title: values.title, description: values.description, start_time: values.date[0].toISOString(), // 手动转换为ISO字符串,确保格式统一 end_time: values.date[1].toISOString(), category_id: values.category }; fetch(api_url + 'event', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', // 修正键的格式为标准写法 'Cache-Control': 'no-cache', 'Accept': '*/*', }, body: JSON.stringify(event) })
3. 检查Event模型的fillable字段
虽然这不是当前请求为空的直接原因,但为了以后的扩展性,确保你需要填充的字段都在$fillable数组里。比如如果以后要动态设置category_id,需要把它加入:
protected $fillable = ['title', 'description', 'start_time', 'end_time', 'category_id'];
你当前在代码里用了$Event->category()->associate($Category);硬编码设置分类,所以暂时不会影响,但补充进去能避免后续的填充问题。
4. 排除CSRF验证问题
虽然你说前后端在同一主机,但如果你的Lumen应用启用了CSRF验证(API路由通常不需要,但如果是从Web路由组过来的可能会有),需要确保请求携带CSRF令牌:
- 在HTML模板头部添加CSRF元标签:
<meta name="csrf-token" content="{{ csrf_token() }}"> - 在fetch请求头中添加令牌:
headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, 'Cache-Control': 'no-cache', 'Accept': '*/*', }
如果是纯API路由,更推荐在bootstrap/app.php中给API路由组设置api中间件,该中间件默认不包含CSRF验证:
$router->group(['prefix' => 'api/v1', 'middleware' => 'api'], function () use ($router) { $router->post('/event', 'EventController@createEvent'); // 其他API路由... });
按照以上步骤排查后,应该就能解决前端POST请求无法被后端正确解析的问题了。
内容的提问来源于stack exchange,提问作者Mainz007

