Laravel集成ChatGPT返回HTML而非JSON的报错排查求助
Laravel 8.x集成ChatGPT时AJAX返回HTML而非JSON的问题排查
问题描述
在Laravel 8.x应用中通过AJAX请求后端集成ChatGPT时,提交消息后浏览器控制台持续报错:Error: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
后端接收到消息后请求OpenAI API,但返回的不是预期的JSON对象,而是以<!DOCTYPE开头的HTML文档。已排查以下方向但未解决:
- 路由配置:确认
web.php中/chatgpt路由指向对应控制器方法,但怀疑Laravel请求失败时返回404/500等HTML错误页 - API请求错误:已检查
.env中OpenAI密钥配置,仍怀疑API响应或请求本身存在问题 - CSRF Token:AJAX请求中已携带Token,但可能存在传递错误或Token无效的情况
- Laravel错误日志:已启用但未捕获到相关错误
环境信息:Laravel 8.x,使用Guzzle HTTP客户端请求OpenAI API,密钥存储在.env中。
排查与解决建议
1. 确认Laravel路由是否被正确命中
- 在控制器方法开头添加日志,验证路由是否触发:
查看\Log::info('ChatGPT route hit with request: ', $request->all());storage/logs/laravel.log,若未出现该日志,说明路由未被触发,需检查路由定义是否正确,或执行php artisan route:clear清除路由缓存。 - 确保
web.php中路由定义正确:Route::post('/chatgpt', [ChatGptController::class, 'getChatGptResponse']);
2. 排查CSRF Token传递问题
- 若JS代码不在Blade模板中,
"{{csrf_token()}}"语法不会被解析,需将Token放在页面meta标签中:
再在JS中获取:<meta name="csrf-token" content="{{ csrf_token() }}">'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content - 查看浏览器Network面板,确认请求头中
X-CSRF-TOKEN是否正确携带。
3. 强制Laravel返回JSON错误响应
- Laravel默认返回HTML错误页,可修改异常处理逻辑,让期望JSON的请求返回JSON格式错误:
在app/Exceptions/Handler.php的render方法中添加:public function render($request, Throwable $exception) { if ($request->expectsJson()) { return response()->json(['error' => $exception->getMessage()], $exception->getStatusCode() ?: 500); } return parent::render($request, $exception); }
4. 调试Guzzle请求细节
- 扩展异常捕获逻辑,打印OpenAI请求的详细错误信息:
通过日志查看OpenAI返回的具体错误,比如密钥无效、模型不存在等问题。catch (\Exception $e) { \Log::error('Guzzle error details: ', [ 'message' => $e->getMessage(), 'request' => $e->getRequest() ? $e->getRequest()->getBody()->getContents() : null, 'response' => $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null, ]); return response()->json(['error' => 'API request failed: ' . $e->getMessage()]); }
5. 修正请求参数获取方式
- 前端以
Content-Type: application/json发送请求,后端需用$request->json('message')替代$request->input('message')获取参数,因为input()主要用于表单数据。
6. 直接测试后端路由
- 使用Postman或curl直接请求
/chatgpt路由,排除前端问题:
观察返回结果是JSON还是HTML,定位问题来源。curl -X POST http://your-app-url/chatgpt \ -H "Content-Type: application/json" \ -H "X-CSRF-TOKEN: your-csrf-token" \ -d '{"message": "Hello ChatGPT"}'
提供的代码
前端AJAX代码
document.getElementById('chatForm').addEventListener('submit', function (e) { e.preventDefault(); let message = document.getElementById('message').value; // Send the message to the Laravel controller using AJAX fetch('/chatgpt', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': "{{csrf_token()}}", }, body: JSON.stringify({ message: message }), }) .then(response => response.json()) .then(data => { if (data.response) { // Display the response in the textarea document.getElementById('message').value = 'data.response'; } else { // Display error if any document.getElementById('chatResponse').innerText = 'Error: ' + (data.error || 'An error occurred'); } }) .catch(error => { document.getElementById('chatResponse').innerText = 'Error: ' + error.message; }); });
后端控制器代码
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use GuzzleHttp\Client; class ChatGptController extends Controller { public function getChatGptResponse(Request $request) { $client = new Client(); $apiKey = env('OPENAI_API_KEY'); if (!$apiKey) { return response()->json(['error' => 'API key is not set.']); } try { $response = $client->post('https://api.openai.com/v1/completions', [ 'headers' => [ 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $apiKey, ], 'json' => [ 'model' => 'text-davinci-003', // Or another model you want to use 'prompt' => $request->input('message'), 'max_tokens' => 150, 'temperature' => 0.7, ], ]); $body = $response->getBody()->getContents(); // Log the raw response to check the content \Log::info('ChatGPT API Response: ' . $body); // Decode the response $body = json_decode($body, true); // Check for the response if (isset($body['choices'][0]['text'])) { return response()->json(['response' => $body['choices'][0]['text']]); } else { return response()->json(['error' => 'Unexpected response from API.']); } } catch (\Exception $e) { \Log::error('ChatGPT API error: ' . $e->getMessage()); return response()->json(['error' => 'Error connecting to the API: ' . $e->getMessage()]); } } }
内容的提问来源于stack exchange,提问作者Emre
相关产品推荐
相关产品推荐

