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/
遇到两个问题:
- 连接字符串能通过Compass正常登录,但本地运行代码时无法连接MongoDB
- 在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
相关产品推荐
相关产品推荐

