Node.js+Express下Shopify REST API分页请求问题求助
Shopify REST API 分页解决方案(Express + 前端)
问题根源
- 前端直接请求Shopify URL触发CORS/401:Shopify Admin API的CORS策略禁止浏览器端直接发起请求,且前端无法安全携带Access Token,必然触发401权限错误。
- 服务端直接用完整分页URL请求失败:Shopify官方Rest客户端要求基于店铺域名构造请求,无需传入完整外部URL,直接传递
page_info参数即可。
解决方案
1. 修改服务端接口,支持分页参数
更新你的/inventory接口,接收page_info参数,用Shopify客户端构造分页请求:
protectedRouter.get('/inventory', async (req, res) => { try { const session = await Shopify.Utils.loadCurrentSession(req, res); const client = new Shopify.Clients.Rest(session.shop, session.accessToken); // 构造请求参数:默认每页50条,若有page_info则带上 const requestParams = { limit: 50 }; if (req.query.page_info) { requestParams.page_info = req.query.page_info; } const result = await client.get({ path: 'products', query: requestParams, }); res.render('inventory', { products: result, }); } catch (error) { console.error('库存加载失败:', error); res.status(500).send('加载库存出错'); } });
2. 调整前端模板,传递分页游标而非完整URL
不再输出Shopify的完整分页URL,改用隐藏字段存储page_info游标:
script(src="/scripts/pagination.js") div.View h3.title.my-4 Etat des stocks div.row div.col-6 <!-- 无上一页时禁用按钮 --> button.btn.btn-outline-dark.ml-4(id="previous_btn" #{!products.pageInfo.prevPageInfo ? 'disabled' : ''}) i(class="bi bi-arrow-left-circle-fill") Précédent <!-- 存储上一页游标 --> input(type="hidden" id="prevPageInfo" value="#{products.pageInfo.prevPageInfo || ''}") div.col-6 <!-- 无下一页时禁用按钮 --> button.btn.btn-outline-dark.float-right.mr-4(id="next_btn" #{!products.pageInfo.nextPageInfo ? 'disabled' : ''}) Suivant i(class="fa-solid fa-circle-arrow-right") <!-- 存储下一页游标 --> input(type="hidden" id="nextPageInfo" value="#{products.pageInfo.nextPageInfo || ''}")
3. 前端分页逻辑:调用自身服务端接口
点击按钮时,请求自己的Express接口并传递page_info参数,避免直接请求Shopify:
window.addEventListener('DOMContentLoaded', () => { const nextBtn = document.getElementById('next_btn'); const prevBtn = document.getElementById('previous_btn'); const nextPageInfo = document.getElementById('nextPageInfo').value; const prevPageInfo = document.getElementById('prevPageInfo').value; // 下一页请求 nextBtn.onclick = async () => { if (!nextPageInfo) return; try { const res = await fetch(`/inventory?page_info=${nextPageInfo}`); if (res.ok) { // 替换页面内容实现刷新 document.body.innerHTML = await res.text(); } } catch (err) { console.error('加载下一页失败:', err); } }; // 上一页请求 prevBtn.onclick = async () => { if (!prevPageInfo) return; try { const res = await fetch(`/inventory?page_info=${prevPageInfo}`); if (res.ok) { document.body.innerHTML = await res.text(); } } catch (err) { console.error('加载上一页失败:', err); } }; });
关键注意事项
- 绝对不能暴露Access Token:所有Shopify API请求必须通过服务端代理,避免Token在前端泄露。
- 使用游标分页:Shopify REST API的分页依赖
page_info游标,而非传统页码,必须用接口返回的prevPageInfo/nextPageInfo构造下一次请求。 - 局部刷新优化:如果不想替换整个页面,可以让服务端返回JSON格式的商品数据,前端仅更新商品列表区域,提升体验。
内容的提问来源于stack exchange,提问作者MounirOnGithub
相关产品推荐
相关产品推荐

