Content-Type 在错误文档中
Content-Type in ErrorDocument
我正在为我的 API 构建一个小框架,因为它们非常具体,但是当我收到 ErrorDocument 的数据时,我遇到了 Content-Type 的问题。目前,我有以下 .htaccess:
<IfModule mod_headers.c>
Header set Content-Type "text/plain"
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
RewriteRule ^([a-z]+)(/[A-Za-z0-9-\._\/]*)?$ .php [QSA,L]
ErrorDocument 404 "API_NOT_FOUND"
</IfModule>
我想实现的是错误404的不同Content-Type。 text/plain 或 application/json 都可以,但其中 none 有效。所以可能我无法像我想的那样在 .htaccess 中设置 Content-Type header 。我还尝试将 ErrorDocument 作为一个文件,但是由于目录的路径是动态的,所以如果没有像这样硬编码的路径,我就不能使用错误文档:
ErrorDocument 404 /api/index.php?error=404
.htaccess 位于 api 目录中,但可以重命名该目录。有什么办法可以实现以下目标之一吗?
- 在 .htaccess 中设置一个 Content-Type,这样 ErrorDocument 就没有带有字符集的 text/html。
- 在 .htaccess 所在的目录中将错误文档设置为 index.php。
如果第一个有效,我还能在 .php 脚本中覆盖它吗?我的一些电话是 JSON,其他是 XML 个文件。
您可以为此使用 ForceType
指令。
首先使用以下数据在 DocumentRoot/folder/
中创建一个名为 error.json
的文件:
{"error":"API_NOT_FOUND"}
然后在你的 DocumentRoot/folder/.htaccess
中这样设置:
ErrorDocument 404 /folder/error.json
<Files "/folder/error.json">
ForceType application/json
</Files>
感谢您的回答,很抱歉这么晚才提供最终答案。我找到了一个我认为可以正常工作的解决方案。
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
RewriteRule ^([A-Za-z0-9_-]+)(/[A-Za-z0-9-\._\/]*)?$ .php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([a-z]+) index.php?error=404 [L]
</IfModule>
错误被重定向到 index.php,它在自己进行日志记录后输出正确的内容,所以我相信这是一个双赢的局面。为了简单说明,下面几行会在index.php中执行:
http_response_code(404);
die(json_encode(['error' => ['code' => 'API_SCRIPT_NOT_FOUND', 'number' => 404]]);
编辑:我将解释我所做的多件事。 index.php 通常会生成一个文档,但是当 index.php 没有被称为 clean 时,我会输出 notfound 错误。它看起来像这样:
<?php
class Documentation {}
$API = new Documentation();
require_once('common/initialize.php');
Output::notfound('API_SCRIPT_NOT_FOUND');
?>
输出 class 是一个小的 class,它使用正确的 Content-Type 处理输出。当没有设置其他 Content-Type 时,它会自动设置 'application/json'。一个小例子(还有更多的功能,但这是它运行的那个):
class Output {
protected static $instance = null;
public static function instance() {
return self::$instance ?: self::$instance = new static;
}
private $finished = false;
private function finish($output, $status = null) {
if($this->finished) return; $this->finished = true;
http_response_code($status ?: 200); $content = null;
$headers = headers_list();
foreach($headers as $header) {
if(substr($header, 0, 13) == 'Content-Type:') {
$content = substr($header, 14); break;
}
}
if(!$content && !headers_sent()) {
header(sprintf('Content-Type: %s', $content = 'application/json'));
die(json_encode((http_response_code() >= 400) ? ['error' => $output] : $output));
}
die(!empty($output['code']) ? $output['code'] : $output);
}
public static function notfound($output) { self::instance()->finish(['code' => $output, 'number' => 404], 404); }
}
我正在为我的 API 构建一个小框架,因为它们非常具体,但是当我收到 ErrorDocument 的数据时,我遇到了 Content-Type 的问题。目前,我有以下 .htaccess:
<IfModule mod_headers.c>
Header set Content-Type "text/plain"
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
RewriteRule ^([a-z]+)(/[A-Za-z0-9-\._\/]*)?$ .php [QSA,L]
ErrorDocument 404 "API_NOT_FOUND"
</IfModule>
我想实现的是错误404的不同Content-Type。 text/plain 或 application/json 都可以,但其中 none 有效。所以可能我无法像我想的那样在 .htaccess 中设置 Content-Type header 。我还尝试将 ErrorDocument 作为一个文件,但是由于目录的路径是动态的,所以如果没有像这样硬编码的路径,我就不能使用错误文档:
ErrorDocument 404 /api/index.php?error=404
.htaccess 位于 api 目录中,但可以重命名该目录。有什么办法可以实现以下目标之一吗?
- 在 .htaccess 中设置一个 Content-Type,这样 ErrorDocument 就没有带有字符集的 text/html。
- 在 .htaccess 所在的目录中将错误文档设置为 index.php。
如果第一个有效,我还能在 .php 脚本中覆盖它吗?我的一些电话是 JSON,其他是 XML 个文件。
您可以为此使用 ForceType
指令。
首先使用以下数据在 DocumentRoot/folder/
中创建一个名为 error.json
的文件:
{"error":"API_NOT_FOUND"}
然后在你的 DocumentRoot/folder/.htaccess
中这样设置:
ErrorDocument 404 /folder/error.json
<Files "/folder/error.json">
ForceType application/json
</Files>
感谢您的回答,很抱歉这么晚才提供最终答案。我找到了一个我认为可以正常工作的解决方案。
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
RewriteRule ^([A-Za-z0-9_-]+)(/[A-Za-z0-9-\._\/]*)?$ .php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([a-z]+) index.php?error=404 [L]
</IfModule>
错误被重定向到 index.php,它在自己进行日志记录后输出正确的内容,所以我相信这是一个双赢的局面。为了简单说明,下面几行会在index.php中执行:
http_response_code(404);
die(json_encode(['error' => ['code' => 'API_SCRIPT_NOT_FOUND', 'number' => 404]]);
编辑:我将解释我所做的多件事。 index.php 通常会生成一个文档,但是当 index.php 没有被称为 clean 时,我会输出 notfound 错误。它看起来像这样:
<?php
class Documentation {}
$API = new Documentation();
require_once('common/initialize.php');
Output::notfound('API_SCRIPT_NOT_FOUND');
?>
输出 class 是一个小的 class,它使用正确的 Content-Type 处理输出。当没有设置其他 Content-Type 时,它会自动设置 'application/json'。一个小例子(还有更多的功能,但这是它运行的那个):
class Output {
protected static $instance = null;
public static function instance() {
return self::$instance ?: self::$instance = new static;
}
private $finished = false;
private function finish($output, $status = null) {
if($this->finished) return; $this->finished = true;
http_response_code($status ?: 200); $content = null;
$headers = headers_list();
foreach($headers as $header) {
if(substr($header, 0, 13) == 'Content-Type:') {
$content = substr($header, 14); break;
}
}
if(!$content && !headers_sent()) {
header(sprintf('Content-Type: %s', $content = 'application/json'));
die(json_encode((http_response_code() >= 400) ? ['error' => $output] : $output));
}
die(!empty($output['code']) ? $output['code'] : $output);
}
public static function notfound($output) { self::instance()->finish(['code' => $output, 'number' => 404], 404); }
}