打开浏览器,敲个/wp-json/wp/v2/posts,看到一串JSON回来,心里美滋滋,觉得好简单,然后呢?线上环境一跑,要么401拒绝访问,要么跨域直接给你报红,要么请求慢得像蜗牛,更惨的是,数据库被刷爆,网站直接挂了,别问我怎么知道的,老子当年为了省几个插件的钱,自己手撸REST API调用,结果客户凌晨三点打电话骂娘,老板差点把我祭天,今天我就把这些年踩过的坑、用过的土办法、以及真正能省钱的方案,一股脑倒给你,你照着做,少走三年弯路。

WordPress REST API调用?别他妈瞎折腾,老子用十年挨过的坑给你铺条路
坑一:认证和授权——别把钥匙挂门上
最蠢的错误是什么?把API密钥直接写在前端代码里,或者用Basic Auth裸奔,你以为做了个隐藏接口就安全?爬虫一分钟就能给你薅光,老子亲眼见过一个电商站,用/wp-json/wc/v3/orders没加认证,退货地址全暴露,差点被撸空库存。
解决方案:别折腾JWT插件了,那玩意儿版本一多就冲突,令牌过期、刷新逻辑写到你吐,WordPress 5.6以后自带Application Passwords,后台用户页面就能生成,简单、安全、官方维护,调用时用Basic Auth的格式,但密码本身是随机字符串,比你自己写的JWT靠谱一百倍,如果非要用JWT,记得用firebase/php-jwt库自己写端点,但老子劝你省省——除非你是安全专家,否则直接上Application Passwords。
权限控制别偷懒,每个应用申请独立密码,前端只给最低权限,比如只读文章,就用subscriber角色生成密码,别顺手给管理员,老子见过外包公司图省事,一个密码走天下,结果员工离职后数据被删光。
坑二:跨域问题——前端报错看不懂
前端同事找你:“大哥,接口返回200,浏览器说跨域!”你一看,Access-Control-Allow-Origin没设置,然后你百度,抄了一段代码丢进functions.php:
add_action('rest_api_init', function() {
remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
add_filter('rest_pre_serve_request', function($value) {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
return $value;
});
});
然后呢?网站被刷得飞起,因为把大门打开了,任何域名都能调你的API,更好的做法是指定白名单,比如只允许你的前端域名,如果多个环境(本地、测试、生产),弄个数组判断。
推荐直接用插件WP CORS,配置界面选“Allow specific origins”,加上域名就行,别手动改代码,除非你记得每次部署更新环境变量。
坑三:性能杀手——一条API拖垮整个站
默认的/wp-json/wp/v2/posts返回几十个字段,甚至包括_links、featured_media里的大图URL,如果前端只想要标题和日期,后端的数据库查询量却跟取全量一样,更可怕的是,如果没加缓存,每个用户刷新一次,服务器就查一次,并发一高直接503。
实战经验:用_fields参数限制返回字段,例如/wp-json/wp/v2/posts?_fields=id,title,date,但这只是治标,因为每次请求还是走了完整的REST路由,该执行的钩子一个不少。
推荐配置:启用WP REST Cache插件,它能缓存API响应到数据库或者Redis,TTL可以按端点设,如果你用Redis对象缓存(推荐Redis Object Cache插件),把REST API的缓存时间设成300秒,大部分场景够用,如果数据更新频繁,用Webhook或者save_post动作清除对应缓存,别一把全清。
别在REST回调里用WP_Query再查一遍数据库,直接用get_posts配合pre_get_posts钩子优化,老子有一次写自定义端点,用了new WP_Query,结果每调一次API就多一次查询,页面还重复加载,气得脸都绿了。
坑四:数据一致性与钩子陷阱
你调了/wp-json/wp/v2/posts,以为拿到了最新数据,结果发现发布状态不对,或者post_meta少了字段,原因是WordPress的REST API回调里,很多钩子会被触发两次(比如rest_pre_insert和wp_insert_post),或者你的主题/插件在rest_pre_serve_request里做了修改。
解决方案:用rest_pre_dispatch钩子在路由开始前干掉多余的查询,或者用rest_after_insert_xxx只处理创建后的逻辑,更省事的办法:别依赖默认端点,自己写自定义端点,虽然多几行代码,但不会被动到屎山。
add_action('rest_api_init', function() {
register_rest_route('myplugin/v1', '/posts', [
'methods' => 'GET',
'callback' => 'my_custom_posts_callback',
'permission_callback' => '__return_true',
]);
});
在回调里用pre_get_posts过滤,或者直接用SQL缓存结果,比默认端点快10倍。
长期维护建议
- 版本化接口:在路由里加版本号,比如
/api/v1/posts,以后改参数不打断旧版,别用默认的wp/v2,那玩意升级WordPress可能改字段名。 - 日志监控:用Query Monitor插件记录每个API请求的耗时和调用来源,发现慢的端点赶紧优化,线上环境配合New Relic或Sentry监控错误。
- 安全扫描:每季度用WPScan扫一次,看看有没有公开的REST API漏洞,2023年就有个插件因为REST端点没权限检查,导致任意文件读取。
- 预算省法:不要买贵得离谱的REST API管理插件(比如某些年付$199的),Lightning、免费版就能满足95%需求,实在缺功能,自己写个简单缓存中间件,加个IP白名单,比插件靠谱。
最后一句:别他妈把API当儿戏,上线前用Postman把所有端点跑一遍,测试认证、限流、错误返回值,老子当年就是因为没测/wp-json/wp/v2/users,结果公开了所有用户的邮箱和用户名,被客户骂到换公司,你不听,这些坑早晚轮到你的头上。
发表评论