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

React应用中Axios报Invalid HTTP Response错误,求排查解决

问题:React本地应用通过Axios调用本地API获取MySQL数据时返回Invalid HTTP Response错误

我在本地运行的React应用中,使用Axios从本地MySQL数据库获取数据,调用Axios时控制台返回Invalid HTTP Response错误。我的MySQL数据库运行在3306端口,所以把API服务器也部署在了这个端口。

相关代码

API接口代码

import axios from 'axios';

const AxiosConfigured = () => {
    axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    axios.defaults.baseURL = 'http://localhost:3306/api';
    axios.defaults.withCredentials = true;
    return axios;
}

const axiosAgent = AxiosConfigured();

export default class APIInterface {
    async getCategories(id) {
        console.log("getCalegories in API_Interface called.");
        return axiosAgent.get('/cats/${id}')
        .then(catInfo => catInfo.data)
        .catch(error => (
            {
                error,
                cat: undefined
            }));
    }
}

API服务器代码

import db from './database.js'
import express from 'express';
import cors from 'kcors';
import bodyParser from 'body-parser';
import httpServer from './ssl.js';
import routes from './routes.js';

const app = express();

const corsOpstions = {
    origin: ['http://localhost:3306/api'],
   credentials: true,
   exposeHeaders: ['Access-Token', 'Cookie'],
   methods: ["GET"]
};
app.use(cors(corsOpstions));
app.use(bodyParser.json());

app.use(async (ctx, next) =>{
   await next();
   if (ctx.response.status === 204) {
       ctx.response.contentlength = 0;
   }
   console.log('in api_server.js: ctx.status is ${ctx.status}.');
    return next().catch((err) => {
        if(err.status === 401) {
            console.log('index.js: sending 401 to client.');
            ctx.status = 401;
          ctx.body = 'Something went wrong...';
        } else {
         console.log('index.js: exception fired');
         console.log('The error message is ${err}.');
        }
    });
});

routes(app);
app.listen(3306, () => {
    console.log('Server started on port 3306');
});

路由代码

import koarouter from 'koa-router';
import catController from './catController.js';

/************* DEFAULT ROUTER ***************/

const router = new koarouter({
    prefix: '/api'
})

router.get('/', function (ctx) {
    console.log('router.get(/)');
    return ctx.body = 'Default router';
})

/********************************************/

const CatController = new catController();
const catRouter = new koarouter({
    prefix: '/cats'
});
catRouter.get('/:id', CatController.getCats, (err) => console.log("router.js:     catRouter error: ", err));

router.use(
    '',
    catRouter.routes()
);

export default function (app) {
    app.use(router.routes());
    app.use(router.allowedMethods());
}

控制器代码

import db from './database.js';

class CatController {
    async getCats(ctx) {
    console.log('getCats called.');
    return new Promise((resolve, reject) => {
        let query = " SELECT * FROM Categories WHERE id = ?";
        db.query(
            {
                sql: query,
                values: ctx.params.id
            }, (error, tuples) => {
                if (error) {
                    console.log("Query error.", error)
                    return reject('Query error. Error msg: ${error}.');
                }
                if (tuples.length === 1) {
                    console.log("Category id matched: ", tuples[0]);
                    ctx.body = {
                        cat: tuples[0]
                    };
                }
                else {
                    console.log('Not able to identify category...');
                    return reject("No such category.");
                }
                return resolve();
            }
        )
    }).catch(err => {
        console.log("getCats in CatController threw an exception. Reason: ", err);
        ctx.body = {
            status: "Failed",
            error: err,
            cat: null
        };
    });
}
}

export default CatController;

数据库连接代码

import mysql from 'mysql2';

const db = mysql.createConnection({
    host: 'localhost',
    port: 3306,
    user: 'root',
    password: 'password',
    database: 'Jeoprady_QandAs'
});

db.connect((err) => {
    if(err) {
        console.error('Error connecting to MySQL: ' + err.stack);
        return;
    }
    console.log('Connected to MySQL as ID ' + db.threadId);
});

export default db;

API调用代码

const [cat, setCat] = useState([]); 
useEffect(() => { 
    const api = new API; 
    async function getCat() { 
        console.log('CatRows.js: getCat useEffect called.'); 
        api.getCategories(0) 
        .then(catInfo => { 
            console.log('API returns category info and it is :${JSON.stringify(catInfo)}'); 
            const cat = catInfo.cat; 
            setCat(cat); 
        }); 
    } 
    getCat(); 
}, []); 
console.log('In CatRows.js the category returned is: ${cat}.');

我尝试调整Axios请求头与CORS配置,但无效果;也尝试将API服务器切换至其他端口,问题依旧。期望API调用能返回与给定ID匹配的数据库分类数据。


问题分析与修复方案

1. 核心问题:Express与Koa框架混用

你的API服务器用express()创建了应用实例,但中间件使用了Koa的ctx上下文语法,路由用了koa-router——这两个框架完全不兼容,导致服务器无法正确处理HTTP请求,直接返回无效响应,这是Invalid HTTP Response的根本原因。

2. 其他关键错误

  • 端口冲突:MySQL已经占用3306端口,API服务器必须换用其他端口(比如3001),否则无法启动。
  • 模板字符串语法错误:API接口中axiosAgent.get('/cats/${id}')使用单引号,模板变量不会被解析,应该改用反引号:axiosAgent.get(`/cats/${id}`)。
  • CORS配置错误:origin应该设置为React应用的地址(比如http://localhost:3000),而非API自身地址,否则浏览器会拦截跨域请求。
  • API实例化错误:调用时new API应该改为new APIInterface,因为导出的类是APIInterface。
  • 控制器Promise处理问题:查询成功后设置ctx.body即可,无需额外返回Promise;错误处理应直接设置响应状态码和body,避免Promise嵌套导致的响应异常。

修复后的代码示例

改用Koa作为API服务器(推荐,因为路由用了koa-router)

// api_server.js
import db from './database.js'
import Koa from 'koa';
import cors from '@koa/cors';
import bodyParser from 'koa-bodyparser';
import routes from './routes.js';

const app = new Koa();

const corsOptions = {
    origin: 'http://localhost:3000', // React应用地址
    credentials: true,
    exposeHeaders: ['Access-Token', 'Cookie'],
    methods: ["GET"]
};
app.use(cors(corsOptions));
app.use(bodyParser());

app.use(async (ctx, next) =>{
    try {
        await next();
        if (ctx.response.status === 204) {
            ctx.response.length = 0;
        }
        console.log(`in api_server.js: ctx.status is ${ctx.status}.`);
    } catch (err) {
        if(err.status === 401) {
            console.log('index.js: sending 401 to client.');
            ctx.status = 401;
            ctx.body = 'Something went wrong...';
        } else {
            console.log('index.js: exception fired');
            console.log(`The error message is ${err}.`);
            ctx.status = 500;
            ctx.body = { status: 'Failed', error: err.message };
        }
    }
});

routes(app);
app.listen(3001, () => { // 换用3001端口,避免和MySQL冲突
    console.log('Server started on port 3001');
});

修复后的API接口代码

// APIInterface.js
import axios from 'axios';

const AxiosConfigured = () => {
    axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
    axios.defaults.baseURL = 'http://localhost:3001/api'; // 对应API服务器新端口
    axios.defaults.withCredentials = true;
    return axios;
}

const axiosAgent = AxiosConfigured();

export default class APIInterface {
    async getCategories(id) {
        console.log("getCategories in API_Interface called.");
        try {
            const catInfo = await axiosAgent.get(`/cats/${id}`); // 改用反引号
            return catInfo.data;
        } catch (error) {
            console.error('Axios request error:', error);
            return { error, cat: undefined };
        }
    }
}

修复后的API调用代码

// CatRows.js
const [cat, setCat] = useState(null); // 初始值设为null更合理
useEffect(() => { 
    const api = new APIInterface; // 修正类名
    async function getCat() { 
        console.log('CatRows.js: getCat useEffect called.'); 
        const catInfo = await api.getCategories(0); // 改用async/await更清晰
        console.log(`API returns category info: ${JSON.stringify(catInfo)}`); // 反引号
        setCat(catInfo.cat); 
    } 
    getCat(); 
}, []); 
console.log(`In CatRows.js the category returned is: ${JSON.stringify(cat)}.`); // 反引号+JSON.stringify

验证步骤

  1. 确保MySQL服务在3306端口正常运行。
  2. 启动修复后的API服务器(端口3001)。
  3. 启动React应用(默认3000端口),检查控制台是否还有错误,查看是否成功获取分类数据。

内容的提问来源于stack exchange,提问作者Ethan Zogg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:29:50