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

Node.js无法连接MongoDB且Postman调用API报Cannot POST /求助

问题描述

我正在开发一个API,调用后可展示用户经纬度附近的5个地点。

  • API调用格式:http://<API URL>?latitude=48.858093&longitude=2.294694
  • MongoDB连接字符串:mongodb+srv://<username>:<password>@cluster0.<something>.mongodb.net/

遇到两个问题:

  1. 连接字符串能通过Compass正常登录,但本地运行代码时无法连接MongoDB
  2. 在Postman中测试API时,出现Cannot POST /错误

以下是相关代码:

app.js

const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const axios = require('axios');
const jwt = require('jsonwebtoken');

const app = express();

app.use(express.json());
app.use(bodyParser.json());

const config = {
  mongodbUrl: process.env.MONGODB_URL,
  foursquareClientId: process.env.FOURSQUARE_CLIENT_ID,
  foursquareClientSecret: process.env.FOURSQUARE_CLIENT_SECRET,
  foursquareApiKey: process.env.FOURSQUARE_API_KEY,
  jwtSecret: process.env.JWT_SECRET_KEY,
};

if (!config.mongodbUrl) {
  console.error('MONGODB_URL is not defined. Make sure to set the environment variable.');
  process.exit(1);
}

mongoose
  .connect(config.mongodbUrl, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
  })
  .then(() => console.log('Connected to MongoDB'))
  .catch((err) => console.error('Error connecting to MongoDB:', err));

const venueSchema = new mongoose.Schema({
  name: String,
  location: {
    lat: Number,
    lng: Number,
  },
});
const Venue = mongoose.model('Venue', venueSchema);

const authorizedUser = {
  id: 1,
  username: config.adminUser,
  password: config.adminPassword,
};

const login = (req, res) => {
  const { username, password } = req.body;

  if (username === authorizedUser.username && password === authorizedUser.password) {
    const token = jwt.sign({ userId: authorizedUser.id }, config.jwtSecret, { expiresIn: '1h' });
    res.json({ token });
  } else {
    res.status(401).json({ message: 'Invalid credentials' });
  }
};

const authenticate = (req, res, next) => {
  const token = req.headers.authorization;

  if (!token) {
    return res.status(401).json({ message: 'Missing authentication token' });
  }

  try {
    const decodedToken = jwt.verify(token, config.jwtSecret);
    req.user = decodedToken;
    next();
  } catch (err) {
    res.status(401).json({ message: 'Invalid token' });
  }
};

const getVenuesNearby = async (req, res) => {
  try {
    const { latitude, longitude } = req.query;

    const response = await axios.get('https://api.foursquare.com/v3/places/search', {
      params: {
        ll: `${latitude},${longitude}`,
        radius: 5000, // 5 miles in meters
        client_id: config.foursquareClientId,
        client_secret: config.foursquareClientSecret,
        client_api_key: config.foursquareApiKey,
        v: '20230725',
      },
    });

    if (response.status !== 200) {
      console.error('Error fetching venues from Foursquare API:', response.statusText);
      return res.status(500).json({ message: 'Error fetching venues' });
    }
    console.log('Response data:', response.data);

    const venues = response.data.response.venues.map((venue) => ({
      name: venue.name,
      location: {
        lat: venue.location.lat,
        lng: venue.location.lng,
      },
    }));

    const savedVenues = await Venue.insertMany(venues);

    res.json({ venues: savedVenues });
  } catch (err) {
    console.error('Error fetching venues from Foursquare API:', err.message);
    res.status(500).json({ message: 'Error fetching venues' });
  }
};

app.post('/api/v1/auth/login', login);
app.get('/api/v1/venues/nearby', authenticate, getVenuesNearby);

app.get('/', (req, res) => {
  res.send('Welcome');
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

config.js

module.exports = {
    mongodbURL: process.env.MONGODB_URL,
    foursquareClientId: process.env.FOURSQUARE_CLIENT_ID,
    foursquareClientSecret: process.env.FOURSQUARE_CLIENT_SECRET,
    jwtSecret: process.env.JWT_SECRET_KEY,
    adminUser: process.env.ADMIN_USER_NAME,
    adminPassword: process.env.ADMIN_PASSWORD,
  };

.env

MONGODB_URL=
FOURSQUARE_CLIENT_ID=
FOURSQUARE_CLIENT_SECRET=
FOURSQUARE_API_KEY=
JWT_SECRET_KEY=

问题分析与解决

1. Cannot POST / 错误

这个错误是因为你给根路径/发送了POST请求,但代码中仅为/配置了GET路由(app.get('/', ...)),没有POST路由。

测试核心API时注意:

  • 调用/api/v1/venues/nearby要用GET方法,不是POST
  • 必须先通过POST /api/v1/auth/login获取JWT Token,然后在请求头中携带Authorization: <你的token>
  • URL参数要带上latitude和longitude,示例:http://localhost:3000/api/v1/venues/nearby?latitude=48.858093&longitude=2.294694

2. MongoDB本地连接失败排查

原因1:环境变量未加载

代码直接使用process.env.MONGODB_URL但未加载.env文件,导致变量为空。解决:

  • 安装dotenv:npm install dotenv
  • 在app.js最顶部添加:require('dotenv').config();

原因2:Mongoose版本兼容问题

你使用的useCreateIndex等连接选项已在Mongoose 6+版本中废弃,可简化连接代码:

mongoose
  .connect(config.mongodbUrl)
  .then(() => console.log('Connected to MongoDB'))
  .catch((err) => console.error('Error connecting to MongoDB:', err));

原因3:IP白名单限制

即使Compass能连接,本地代码的IP可能不在MongoDB Atlas白名单中。去Atlas控制台检查:

  • 进入集群 -> 网络访问 -> 添加当前IP,或临时允许所有IP(仅测试用,生产环境禁用)

原因4:连接字符串缺数据库名

在连接字符串末尾添加数据库名,示例:mongodb+srv://<username>:<password>@cluster0.<something>.mongodb.net/venuesDB,避免权限或默认数据库问题。

3. 其他潜在问题

Foursquare API调用错误

Foursquare v3 API认证方式为请求头携带密钥,而非URL参数。修改代码:

const response = await axios.get('https://api.foursquare.com/v3/places/search', {
  params: {
    ll: `${latitude},${longitude}`,
    radius: 5000,
    limit: 5, // 指定返回5个地点
    v: '20230725',
  },
  headers: {
    'Authorization': `fsq3${config.foursquareApiKey}`
  }
});

同时v3 API响应结构与v2不同,调整映射逻辑:

const venues = response.data.results.map((venue) => ({
  name: venue.name,
  location: {
    lat: venue.geocodes.main.latitude,
    lng: venue.geocodes.main.longitude,
  },
}));

配置变量引用错误

app.js的config对象未包含adminUser和adminPassword,导致登录接口报错。可直接引入config.js的配置:

const config = require('./config.js');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:08:09