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

如何在Node.js的Express中使用相对URL调用REST API?

问题:Express中使用Axios调用同应用API时的URL错误问题

我在Express控制器中有如下代码:

const http = require('axios');

module.exports = {
    login: (req, res) => {
        res.render("admin/login.ejs", { errorMessage: req.flash('message')[0] });
    },
    processLogin: (req, res) => {
        axios.post(`/api/login`, {
                "email": req.body.email,
                "password": req.body.password
            })
            .then(function(response) {
                console.log(response);
            })
            .catch(function(error) {
                console.error(error);
            });
    }
}

其中路径"/api/login"是同一应用中Express路由定义的API,但出现如下错误:

TypeError [ERR_INVALID_URL]: Invalid URL
    at new NodeError (node:internal/errors:372:5)
    at URL.onParseError (node:internal/url:553:9)
    at new URL (node:internal/url:629:5)
    at dispatchHttpRequest (D:\projects\calvarycomz.com\node_modules\axios\dist\node\axios.cjs:2394:20)    
    at new Promise (<anonymous>)
    at http (D:\projects\calvarycomz.com\node_modules\axios\dist\node\axios.cjs:2330:10)
    at Axios.dispatchRequest (D:\projects\calvarycomz.com\node_modules\axios\dist\node\axios.cjs:3260:10)  
    at Axios.request (D:\projects\calvarycomz.com\node_modules\axios\dist\node\axios.cjs:3610:33)
    at Axios.httpMethod [as post] (D:\projects\calvarycomz.com\node_modules\axios\dist\node\axios.cjs:3649:19)
    at Function.wrap [as post] (D:\projects\calvarycomz.com\node_modules\axios\dist\node\axios.cjs:27:15) {  input: '/api/login',
  code: 'ERR_INVALID_URL'
}

我知道错误源于Axios请求地址缺少主机前缀(如http://localhost:30000),请问如何仅用URL路径通过Axios发起HTTP请求?


解决方案

方法1:直接调用路由处理函数(推荐)

同应用内的API没必要走HTTP请求,直接导入对应的路由处理函数调用更高效,也能彻底避免URL问题。

假设/api/login的处理函数定义在routes/api.js中:

// 控制器中先导入路由处理函数
const { loginHandler } = require('../routes/api');

module.exports = {
    login: (req, res) => {
        res.render("admin/login.ejs", { errorMessage: req.flash('message')[0] });
    },
    processLogin: (req, res) => {
        // 直接调用路由处理函数
        loginHandler(req, res)
            .then(() => {
                // 处理成功逻辑
            })
            .catch(error => {
                console.error(error);
                // 处理错误逻辑
            });
    }
}

方法2:配置Axios的baseURL

如果必须用Axios发起请求,可通过配置baseURL让后续请求只需写路径。

全局配置Axios

在项目入口文件(如app.js)中全局配置:

const axios = require('axios');
// 用环境变量或固定端口设置baseURL
axios.defaults.baseURL = `http://localhost:${process.env.PORT || 3000}`;

之后控制器中就能直接用路径发起请求:

axios.post('/api/login', { email: req.body.email, password: req.body.password })
    .then(response => console.log(response))
    .catch(error => console.error(error));

动态生成baseURL

从当前请求对象req中获取主机信息,动态拼接baseURL,适配不同运行环境:

processLogin: (req, res) => {
    const baseURL = `${req.protocol}://${req.get('host')}`;
    axios.post(`${baseURL}/api/login`, {
        email: req.body.email,
        password: req.body.password
    })
    .then(response => console.log(response))
    .catch(error => console.error(error));
}

方法3:创建专用Axios实例

如果不想污染全局配置,可以创建一个专门用于内部请求的Axios实例:

const axios = require('axios');
// 创建实例并设置baseURL
const internalAxios = axios.create({
    baseURL: `http://localhost:${process.env.PORT || 3000}`
});

module.exports = {
    login: (req, res) => {
        res.render("admin/login.ejs", { errorMessage: req.flash('message')[0] });
    },
    processLogin: (req, res) => {
        // 使用专用实例发起请求
        internalAxios.post('/api/login', {
            email: req.body.email,
            password: req.body.password
        })
        .then(response => console.log(response))
        .catch(error => console.error(error));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:50:42