我正在尝试创建一个安全的下载插件。
我发现rest api是这个任务的最佳选择,但我不能像这样更改标题Content-Type:
. 在register_rest_route
回调已设置的这些标头。如果我设置Content-disposition: attachment, filename=asd.txt
我明白了ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
镀铬。
我知道rest不能处理这些任务,但我找不到任何替代方案。如果有,请告诉我。
下载的数据似乎是json编码的。
我讨厌wordpress的“魔法”。使用普通PHP可以很容易地完成这些任务,但wordpress只会让它变得复杂。
请有人告诉我如何禁用这些魔法头***或推荐我一种在插件中安全下载(php)的方法。
(不,我不想使用第三方插件。我已经尝试了很多插件。到目前为止,它们都没有起作用……:D这些wordpress的事情在symfony之后是一个巨大的倒退……)
这是我的experimental 代码:
add_action(\'rest_api_init\', function() {
register_rest_route(\'secure-downloads/v1\', \'/download/(?P<filename>.*)\',
array(
\'methods\' => \'GET\',
\'callback\' => \'secure_downloads_handle_download\'
));
});
function secure_downloads_handle_download(WP_REST_Request $request)
{
$filename = urldecode($request->offsetGet(\'filename\'));
if(strpos($filename, \'/..\'))
{
return new WP_REST_Response(\'\', 403);
}
$path = SECURE_DOWNLOADS_UPLOAD_DIR . $filename;
return new WP_REST_Response(file_get_contents($path), 200, array(
\'Content-Type\' => \'application/octet-stream\',
\'Content-Transfer-Encoding\' => \'Binary\',
\'Content-disposition\' => \'attachment, filename=\\\\\' . $filename . \'\\\\\'
));
}
SO网友:Walf
对于这种情况,有一个钩子可以避免过早停止脚本执行,并维护WP对HEAD
方法请求。在REST响应处理程序函数中放入类似的内容:
$your_served = false;
$your_content = $something;
add_filter(
\'rest_pre_serve_request\',
function($served, $result, $request, $rest_server) use (&$your_served, &$your_content) {
if (!$served) {
if ($your_served) {
$served = $your_served;
}
else {
add_filter(
\'rest_pre_echo_response\',
function($result, $rest_server, $request) use (&$your_served, &$your_content) {
# serve $your_content here but do not return or exit, in this case readfile() would be optimal
$your_served = true;
return null; # explicitly prevent WP sending the normal JSON response
},
10, # change priority to suit
3
);
}
}
return $served;
},
10, # change priority to suit
4
);
$result = new WP_REST_Response();
$result->set_headers([
\'Content-Type\' => $your_content_type,
# you may include others such as \'Content-Length\'
]);
return $result;