仔细研究WordPress之后REST API Handbook 关于
Home / REST API Handbook / Extending the REST API / Routes and Endpoints
Home / REST API Handbook / Extending the REST API / Adding Custom Endpoints
我意识到我犯了几个错误。
因此,我想与大家分享我的发现。
此外,出于好奇,最后我还有一些额外的问题。
将对象请求传递给回调函数1。)将对象“$request”传递给回调函数:之前:function get_your_data() { ...
之后:function get_your_data($request) { ...
2。)在外部创建命名空间和路由wp/v2
使用您自己的版本号:
之前:
register_rest_route( \'wp/v2/your_private_page\', \'/data\', array( ...
之后:
register_rest_route( \'your_private_page/v1\', \'/data\', array( ...
还要在客户端脚本中调整http请求URL:
之前:let url = \'https://example.com/wp-json/wp/v2/your_private_page/data\';
之后:let url = \'https://example.com/wp-json/your_private_page/v1/data\';
3。)将“permission\\u callback”添加到您的路由:
之前:我没有它(只是有主回调)
之后:添加
prefix_get_private_data_permissions_check()
像
Permission Callback 作用
// Permission Callback
// \'ypp\' is the Prefix I chose (ypp = Your Private Page)
function ypp_get_private_data_permissions_check() {
// Restrict endpoint to browsers that have the wp-postpass_ cookie.
if ( !isset($_COOKIE[\'wp-postpass_\'. COOKIEHASH] )) {
return new WP_Error( \'rest_forbidden\', esc_html__( \'OMG you can not create or edit private data.\', \'my-text-domain\' ), array( \'status\' => 401 ) );
};
// This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check.
return true;
};
// And then add the permission_callback to your POST and PUT routes:
add_action(\'rest_api_init\', function() {
/**
* Register here your custom routes for your CRUD functions
*/
register_rest_route( \'your_private_page/v1\', \'/data\', array(
array(
\'methods\' => WP_REST_Server::READABLE,
\'callback\' => \'get_your_data\',
// Always allow.
\'permission_callback\' => \'__return_true\' // <-- good practice, according to docs
),
array(
\'methods\' => WP_REST_Server::CREATABLE,
\'callback\' => \'insert_your_data\',
// Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
\'permission_callback\' => \'ypp_get_private_data_permissions_check\', // <-- that was the missing part
),
array(
\'methods\' => WP_REST_Server::EDITABLE,
\'callback\' => \'update_your_data\',
// Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
\'permission_callback\' => \'ypp_get_private_data_permissions_check\', // <-- that was the missing part
),
));
});
显然,这很有意义,因为它在服务器端(WordPress、php)必须进行授权(虚设我,呵呵)
(完整代码)完整代码:以下代码片段适用于我的自托管WordPress安装:
WordPress: 版本5.7.2PHP: 7.4版host: hostmonster。com
client: Windows 10browsers: 在Chrome、Firefox甚至Edge上进行了测试
Code (HTML 带内联<script> ... </script>
):
<form id="form1" name="form1">
<button id="get" onclick="getValues()">GET</button>
<button id="insert" onclick="insertValues()">CREATE</button>
<button id="update" onclick="updateValues()">UPDATE</button>
</form>
<script>
let yourData = [];
let yourDataNew = {};
let yourDataUpdated = {};
let token = "";
function getValues() {
event.preventDefault();
//READ data
getYourData();
};
function insertValues() {
event.preventDefault();
//CREATE new datarecord
yourDataNew = {"column_1": "test-1", "column_2": "test-2"};
insertYourData(yourDataNew);
};
function updateValues() {
event.preventDefault();
//UPDATE datarecord
let idOfLastRecord = yourData[yourData.length-1].id;
yourDataUpdated = {"id": idOfLastRecord, "column_1": "test-1-modified", "column_2": "test-2-modified"};
updateYourData(yourDataUpdated);
};
// We don\'t need to retrieve token form Cookie. See my EDIT at the end
//GET value of Access Cookie wp-postpass_{hash}
//token = ("; "+document.cookie).split("; wp-postpass_675xxxxxx =").pop().split(";").shift();
//console.log(\'TOKEN: \' + token);
// Here comes the REST API part:
// HTTP requests with fetch() promises
function getYourData() {
let url = \'https://example.com/wp-json/your_private_page/v1/data\';
fetch(url, {
method: \'GET\',
credentials: \'same-origin\',
headers:{
\'Content-Type\': \'application/json\',
\'Accept\': \'application/json\',
//\'Authorization\': \'Bearer \' + token <-- not needed, see EDIT at end
}
}).then(res => res.json())
.then(response => get_success(response))
.catch(error => failure(error));
};
function insertYourData(data) {
let url = \'https://example.com/wp-json/your_private_page/v1/data\';
fetch(url, {
method: \'POST\',
credentials: \'same-origin\',
headers:{
\'Content-Type\': \'application/json\',
\'Accept\': \'application/json\',
//\'Authorization\': \'Bearer \' + token <-- not needed, see EDIT at end
},
body: JSON.stringify(data)
}).then(res => res.json())
.then(response => create_success(response))
.catch(error => failure(error));
};
function updateYourData(data) {
let url = \'https://example.com/wp-json/your_private_page/v1/data\';
fetch(url, {
method: \'PUT\',
credentials: \'same-origin\',
headers:{
\'Content-Type\': \'application/json\',
\'Accept\': \'application/json\',
//\'Authorization\': \'Bearer \' + token <-- not needed, see EDIT at end
},
body: JSON.stringify(data)
}).then(res => res.json())
.then(response => update_success(response))
.catch(error => failure(error));
};
// fetch() promises success functions:
function get_success(json) {
data = JSON.stringify(json);
yourData = JSON.parse(data);
console.log(\'GET\');
console.log(yourData);
};
function create_success(json) {
let insertResponse = JSON.stringify(json);
insertResponse = JSON.parse(insertResponse);
console.log(\'CREATE\');
console.log(insertResponse);
};
function update_success(json) {
let updateResponse = JSON.stringify(json);
updateResponse = JSON.parse(updateResponse);
console.log(\'UPDATE\');
console.log(updateResponse);
};
function failure(error) {
console.log("Error: " + error);
};
</script>
Code (
PHP 代码输入
function.php
我的已安装主题):
/**
* Add here your custom CRUD functions
*/
/**
* This is our callback function to return (GET) our data.
*
* @param WP_REST_Request $request This function accepts a rest request to process data.
*/
function get_your_data($request) {
global $wpdb;
$yourdata = $wpdb->get_results("SELECT * FROM your_custom_table");
return rest_ensure_response( $yourdata );
};
/**
* This is our callback function to insert (POST) new data record.
*
* @param WP_REST_Request $request This function accepts a rest request to process data.
*/
function insert_your_data($request) {
global $wpdb;
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : \'\';
if ($contentType === "application/json") {
$content = trim(file_get_contents("php://input"));
$decoded = json_decode($content, true);
$newrecord = $wpdb->insert( \'your_custom_table\', array( \'column_1\' => $decoded[\'column_1\'], \'column_2\' => $decoded[\'column_2\']));
};
if($newrecord){
return rest_ensure_response($newrecord);
}else{
//something gone wrong
return rest_ensure_response(\'failed\');
};
header("Content-Type: application/json; charset=UTF-8");
};
/**
* This is our callback function to update (PUT) a data record.
*
* @param WP_REST_Request $request This function accepts a rest request to process data.
*/
function update_your_data($request) {
global $wpdb;
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : \'\';
if ($contentType === "application/json") {
$content = trim(file_get_contents("php://input"));
$decoded = json_decode($content, true);
$updatedrecord = $wpdb->update( \'your_custom_table\', array( \'column_1\' => $decoded[\'column_1\'], \'column_2\' => $decoded[\'column_2\']), array(\'id\' => $decoded[\'id\']), array( \'%s\' ));
};
if($updatedrecord){
return rest_ensure_response($updatedrecord);
}else{
//something gone wrong
return rest_ensure_response(\'failed\');
};
header("Content-Type: application/json; charset=UTF-8");
};
// \'ypp\' is the Prefix I chose (ypp = Your Private Page)
function ypp_get_private_data_permissions_check() {
// Restrict endpoint to browsers that have the wp-postpass_ cookie.
if ( !isset($_COOKIE[\'wp-postpass_\'. COOKIEHASH] )) {
return new WP_Error( \'rest_forbidden\', esc_html__( \'OMG you can not create or edit private data.\', \'my-text-domain\' ), array( \'status\' => 401 ) );
};
// This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check.
return true;
};
add_action(\'rest_api_init\', function() {
/**
* Register here your custom routes for your CRUD functions
*/
register_rest_route( \'your_private_page/v1\', \'/data\', array(
array(
\'methods\' => WP_REST_Server::READABLE,
\'callback\' => \'get_your_data\',
// Always allow.
\'permission_callback\' => \'__return_true\'
),
array(
\'methods\' => WP_REST_Server::CREATABLE,
\'callback\' => \'insert_your_data\',
// Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
\'permission_callback\' => \'ypp_get_private_data_permissions_check\',
),
array(
\'methods\' => WP_REST_Server::EDITABLE,
\'callback\' => \'update_your_data\',
// Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
\'permission_callback\' => \'ypp_get_private_data_permissions_check\',
),
));
});
5.) Testing
终于得到了我如此绝望的期待
FAILURE 最后一个问题,尽管:
Is \'Authorization\': \'Bearer \' + token
necessary in header of HTTP request?
经过一些测试,我意识到
if ( !isset($_COOKIE[\'wp-postpass_\'. COOKIEHASH] )) {
在权限回调中,不仅检查是否在客户端浏览器上设置了Cookie,而且似乎还检查其值(JWT标记)。
因为我用我的初始代码进行了dobble检查,传递了一个错误的令牌,消除了cookie,或者让会话保持打开状态,但在后端更改了站点的密码(因此WordPress将创建一个新的令牌,因此set的值wp_postpass_
cookie将更改)并且所有测试都正确进行-REST API被阻止,not only verifying presence of cookie, but also its value (这很好-谢谢WordPress团队)。
My Questions here: