本地正常但WP-Engine上React调用WordPress自定义API返回index.html
React + WordPress 用户管理部署WP-Engine后API返回HTML的问题
问题描述
本地WordPress环境中,React通过Axios调用自定义REST API(登录/注册)功能正常,但部署到WP-Engine后,API请求返回的是React项目的public/index.html内容,而非预期的JSON响应。
相关代码
functions.php 自定义登录端点
function custom_login_user($request){ $params = $request->get_json_params(); // 从请求体获取数据 $username = sanitize_text_field($params['username']); $password = wp_kses_post($params['password']); $user = wp_authenticate($username, $password); if(is_wp_error($user)){ return new WP_Error('login_failed', $user->get_error_message(), array('status' => 401)); } // 生成用户令牌(可使用JWT或其他安全方式) $access_token_payload = array( "user_id" => $user->ID, "username" => $user->user_login, "email" => $user->user_email, "exp" => time() + 3600, // 令牌有效期1小时 ); // 使用自定义函数生成访问令牌 $access_token = generate_jwt_token($access_token_payload); // 生成有效期更长的刷新令牌(30天) $refresh_token_payload = array( "user_id" => $user->ID, "exp" => time() + 2592000, // 刷新令牌有效期30天 ); // 使用自定义函数生成刷新令牌 $refresh_token = generate_jwt_token($refresh_token_payload); // 为当前用户保存刷新令牌(可使用用户元数据或其他存储方式) update_user_meta($user->ID, 'refresh_token', $refresh_token); // 返回用户信息、访问令牌和刷新令牌 return [ 'email' => $user->user_email, 'username' => $user->user_login, 'access_token' => $access_token, 'refresh_token' => $refresh_token, ]; } function custom_login_user_endpoint() { register_rest_route('custom/v1', '/login-user', array( 'methods' => 'POST', 'callback' => 'custom_login_user', )); } add_action('rest_api_init', 'custom_login_user_endpoint');
React Axios 登录请求
const loginHandler = (e) => { e.preventDefault(); const apiEndpoint = `${apiHost}/wp-json/custom/v1/login-user`; console.log(email); axios .post(apiEndpoint, { username: email, password: password, }) .then((response) => { console.log("用户登录成功:", response); const { data } = response; localStorage.setItem("access_token", data.access_token); localStorage.setItem("refresh_token", data.refresh_token); const userInfo = { email: data.email, name: data.email, }; localStorage.setItem("userInfo", JSON.stringify(userInfo)); navigate('/') }) .catch((error) => { console.error("登录失败:", error); }); };
错误响应内容
<!DOCTYPE html> <html lang="en"> <head> <script src='/wp-content/themes/fmn-react-wp-theme/react-src/node_modules/@devloco/create-react-wptheme-utils/wpThemeClient.js'></script> <script src='/wp-content/themes/fmn-react-wp-theme/react-src/node_modules/@devloco/create-react-wptheme-utils/wpThemeErrorOverlay.js'></script> <script> wpThemeClient.start("ws", "127.0.0.1", "8090"); </script> <meta charset="utf-8" /> <link rel="icon" type="image/x-icon" href="https://findmyneighdev.wpengine.com/wp-content/themes/fmn-react-wp-theme/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-wptheme" /> <link rel="apple-touch-icon" href="/wp-content/themes/fmn-react-wp-theme/logo192.png" /> <link rel="manifest" href="/wp-content/themes/fmn-react-wp-theme/manifest.json" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" /> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700;800;900&display=swap" rel="stylesheet"> <title>My Next Neighborhood</title> <link href="/wp-content/themes/fmn-react-wp-theme/static/css/main.chunk.css?d02c8c7b01d859f67ff0" rel="stylesheet"></head> <body> <noscript> 请启用JavaScript以运行此应用。 </noscript> <div id="root"></div> <script src="/wp-content/themes/fmn-react-wp-theme/static/js/bundle.js?d02c8c7b01d859f67ff0"></script><script src="/wp-content/themes/fmn-react-wp-theme/static/js/0.chunk.js?d02c8c7b01d859f67ff0"></script><script src="/wp-content/themes/fmn-react-wp-theme/static/js/main.chunk.js?d02c8c7b01d859f67ff0"></script></body> </html>
解决方案
1. 修正API端点URL
- 确认
apiHost变量在生产环境设置为WP-Engine的正式域名(如https://findmyneighdev.wpengine.com),避免残留本地localhost地址。 - 直接在浏览器访问
https://你的域名/wp-json/custom/v1/login-user,若返回HTML,说明路由被React客户端路由接管。
2. 调整服务器重写规则
WP-Engine的服务器规则可能将所有请求指向React的index.html,需优先让wp-json开头的请求交给WordPress处理:
- 若使用Apache,在主题根目录的
.htaccess中添加以下规则(放在React路由重写之前):RewriteRule ^wp-json/ - [L] - 若使用Nginx,联系WP-Engine支持添加类似规则:
location ^~ /wp-json/ { try_files $uri $uri/ /index.php?$args; }
3. 确保React生产构建
当前响应中包含开发模式的WebSocket脚本(wpThemeClient.start),说明部署的是开发版本:
- 执行
npm run wpbuild生成生产构建包,替换WP-Engine上的React文件。 - 检查React构建配置,确保
publicPath正确指向主题路径,避免路由冲突。
4. 验证REST端点注册
- 在WP-Engine的WordPress后台,添加临时代码输出端点URL:
确认输出的URL和前端调用的一致。echo get_rest_url(null, 'custom/v1/login-user'); - 安装REST API调试插件,查看自定义端点是否成功注册,排除端点未加载的问题。
5. 规范请求头与CORS配置
- Axios请求需明确设置
Content-Type为application/json,WP-Engine对请求头要求更严格:axios.post(apiEndpoint, { username: email, password: password }, { headers: { 'Content-Type': 'application/json' } }) - 若存在跨域问题,在
functions.php中添加CORS头:add_action('rest_api_init', function() { add_filter('rest_pre_serve_request', function($value) { header('Access-Control-Allow-Origin: ' . esc_url_raw($_SERVER['HTTP_ORIGIN'])); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type'); return $value; }); });
内容的提问来源于stack exchange,提问作者Veera Silamban
相关产品推荐
相关产品推荐

