You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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标签中:
    <meta name="csrf-token" content="{{ csrf_token() }}">
    
    再在JS中获取:
    '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请求的详细错误信息:
    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()]);
    }
    
    通过日志查看OpenAI返回的具体错误,比如密钥无效、模型不存在等问题。

5. 修正请求参数获取方式

  • 前端以Content-Type: application/json发送请求,后端需用$request->json('message')替代$request->input('message')获取参数,因为input()主要用于表单数据。

6. 直接测试后端路由

  • 使用Postman或curl直接请求/chatgpt路由,排除前端问题:
    curl -X POST http://your-app-url/chatgpt \
    -H "Content-Type: application/json" \
    -H "X-CSRF-TOKEN: your-csrf-token" \
    -d '{"message": "Hello ChatGPT"}'
    
    观察返回结果是JSON还是HTML,定位问题来源。

提供的代码

前端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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 15:43:10