Node.js如何读取URL参数、遍历ServerResponse及解决Express路由冲突
问题根因
- 授权回调的
code是Spotify重定向回站点时携带的GET请求query参数,挂载在请求对象req上,你之前打印响应对象res当然找不到对应字段 - Express的路由匹配是从上到下优先匹配,两个相同路径、相同请求方法的路由只会执行第一个,因此需要拆分不同功能的路由路径
代码优化
1. 配置依赖启用
你引入了body-parser但未启用,先在初始化express后加配置:
const express = require("express"); const https = require("https"); const bodyParser = require("body-parser"); const axios = require("axios"); const app = express(); // 新增:启用body-parser解析表单和JSON请求体 app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); // 全局存储token,生产环境建议用缓存/数据库存储 let accessToken = ''; app.listen(3000, function() { console.log('服务启动在http://localhost:3000') })
2. 调整路由逻辑
// 根路径GET请求:判断是否是授权回调,是则拿code换token,否则返回首页 app.get("/", function(req, res) { // 直接从请求query里拿code,就是你要的参数 const code = req.query.code; if(code) { console.log('拿到授权code:', code); // 此处可以调用Spotify接口用code换access_token axios.post('https://accounts.spotify.com/api/token', new URLSearchParams({ grant_type: 'authorization_code', code: code, redirect_uri: 'http://localhost:3000/', client_id: '替换为你的client_id', client_secret: '替换为你的client_secret' }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(tokenRes => { accessToken = tokenRes.data.access_token; console.log('拿到accessToken:', accessToken); // 拿到token后跳转回纯根路径,避免url里带code刷新重复请求 res.redirect('/'); }).catch(err => { console.error('换token失败:', err); res.send('授权失败'); }) return; } res.sendFile(__dirname + "/index.html"); }); const authURL = "https://accounts.spotify.com/authorize?client_id=替换为你的client_id&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2F&scope=user-read-playback-state%20app-remote-control%20user-modify-playback-state%20user-read-currently-playing%20user-read-playback-position%20user-read-email%20streaming" // 授权跳转路由,单独拆分到/login路径 app.post("/login", function(req, res) { res.redirect(authURL); }); // 搜索路由,单独拆分到/search路径 app.post("/search", function(req, res) { const query = req.body.queryValue; const searchUrl = "https://api.spotify.com/v1/search?q=" + encodeURIComponent(query) + "&type=track%2Calbum%2Cartist&limit=4&market=IN"; axios.get(searchUrl, { headers: { 'Authorization': `Bearer ${accessToken}`, } }) .then((resAxios) => { console.log('搜索结果:', resAxios.data) // 此处处理返回结果返回给前端 res.json(resAxios.data) }) .catch((error) => { console.error('搜索失败:', error) res.status(500).send('搜索失败') }) });
3. 调整前端index.html代码
新增授权按钮,修改表单提交路径:
<!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title>Title</title> <link rel="stylesheet" href="index.css"> </head> <body> <!-- 新增授权按钮 --> <form action="/login" method="post" style="margin: 20px 0;"> <button type="submit">Spotify授权登录</button> </form> <div class="index-search-container"> <!-- 表单提交路径改为/search --> <form class="" action="/search" method="post"> <input id="queryId" type="text" name="queryValue" value="" placeholder="Search"> <button type="submit" name="button">HIT ME</button> </form> </div> </body> </html>
关键说明
- 直接通过
req.query.code即可拿到授权回调的code参数,不需要解析日志 - 路由拆分后不会再出现冲突,不同功能走不同路径逻辑更清晰
- 搜索请求的query参数记得用
encodeURIComponent编码,避免特殊字符导致请求错误
内容的提问来源于stack exchange,提问作者Varun
相关产品推荐
相关产品推荐

