从 Apache 返回空响应
Posted
技术标签:
【中文标题】从 Apache 返回空响应【英文标题】:Return empty response from Apache 【发布时间】:2015-02-26 12:35:50 【问题描述】:我正在使用 Apache 返回 CORS 响应以加快请求速度(以前我在应用程序代码中处理过这个问题,但这太慢了)。在我的 VirtualHost 中,我有以下 Apache 代码:
SetEnvIfNoCase Access-Control-Request-Method "(GET|POST|PUT|DELETE|OPTIONS)" IsPreflight=1
SetEnvIfNoCase Origin "http(s)?://(myorigin.com)$" AccessControlAllowOrigin=$0$1
Header always set Access-Control-Allow-Origin %AccessControlAllowOrigine env=AccessControlAllowOrigin
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" env=IsPreflight
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, Accept" env=IsPreflight
Header always set Access-Control-Max-Age "7200" env=IsPreflight
RewriteEngine On
RewriteCond %REQUEST_METHOD OPTIONS
RewriteCond %ENV:IsPreflight 1
RewriteRule ^(.*)$ $1 [R=200,L]
这实际上非常有效。它检测请求是否是预检请求,如果是,则发送适当的标头。只有一个问题:预检请求返回 200(所以浏览器发送正常请求),但正文是 200 ERROR(哈哈):
<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>200 OK</title>
</head><body>
<h1>OK</h1>
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p>
<p>Please contact the server administrator at
you@example.com to inform them of the time this error occurred,
and the actions you performed just before this error.</p>
<p>More information about this error may be available
in the server error log.</p>
</body></html>
虽然这可以正常工作,但我想从预检正文中删除这个丑陋的错误,但我没有找到任何方法告诉 Apache 实际上返回一个空正文。
谢谢!
【问题讨论】:
你找到解决这个问题的方法了吗?? 【参考方案1】:使用 204 代码(无内容)响应 OPTIONS 请求。
例如:
RewriteCond %REQUEST_METHOD OPTIONS
RewriteRule ^(.*)$ $1 [R=204,L]
【讨论】:
值得指出的是,返回 204 可能存在浏览器兼容性问题 - 例如 Firefox:***.com/a/58794243/514192【参考方案2】:204 应该足以满足 CORS 限制。但是,在其他情况下,可能需要具有不同状态代码的空响应。
TL;DR
警告:ErrorDocument
带有 2xx 和 3xx 是未记录的行为。
要发送带有空正文的响应,请将RewriteRule
与ErrorDocument
组合在一起。
# for 2xx, 4xx, 5xx, with or without flag [L]
RewriteRule ^ - [R=code,L]
# for 3xx
RewriteRule pattern substitution [R=code,L]
# for apache 2.4.13 and later
ErrorDocument code %unescape:%00
# for older versions,
# this can't be done without an empty file,
# the closest you can get using only the configuration is
ErrorDocument code " "
# if you're willing to use an empty file
ErrorDocument code /path/to/empty/file
关于204无内容
RewriteRule
with 204 No Content 按预期工作,只是主要浏览器处理它的方式与其他状态代码不同,例如带有空内容的 200 和 301。
如MDN: 204 No Content中指定,
HTTP 204 No Content 成功状态响应代码表示请求已成功,但客户端不需要离开其当前页面。
如果你访问一个 URL 并且它返回 204,Firefox 和 Chromium 将像什么都没发生一样,保持页面内容和导航栏中的 URL 不变。
这可能需要也可能不需要。
但是如果你想要和 200 响应一样的效果,内容为空并且关心 Firefox/Chromium/etc,或者想要使用其他 HTTP 状态码,那么 RewriteRule
和 204 不是解决方案。
带有ErrorDocument
的自定义响应正文
我能找到的最接近的返回空响应的方法是return a custom response body using ErrorDocument,然后设置所需的正文内容。
尽管 Apache 的 Custom Error Responses 文档指出:
可以为任何指定为错误条件的 HTTP 状态代码定义自定义错误响应 - 即任何 4xx 或 5xx 状态。
事实证明,ErrorDocument
可以为 2xx 和 3xx 状态码指定自定义响应。
而我们可以使用RewriteRule
's [R]
flag进入这种状态,让ErrorDocument
生效。
然而,这并不是故事的结局,如下面的配置,
ErrorDocument 200 ""
将引发此错误消息,
ErrorDocument takes two arguments, Change responses for HTTP errors
似乎引用的“空字符串”并没有让位给ErrorDocument
指令,Apache 将此配置行解析为带有单个参数的指令。
在阅读 Apache 的 Syntax of the Configuration Files 并在文档中查找“空格”和“引号”后,我找不到对此的令人满意的解释或将空字符串作为参数的任何提示。它只在参数包含空格的情况下提到引号。
深入了解ErrorDocument
正如 Apache 的 Custom Error Responses 所说,
ErrorDocument 指令的语法是:
ErrorDocument <3-digit-code> <action>
操作将被视为:
要重定向到的本地 URL(如果操作以“/”开头)。 要重定向到的外部 URL(如果操作是有效 URL)。 要显示的文本(如果以上都不是)。如果文本包含多个单词,则必须用引号 (") 括起来。
在 Apache 的 ErrorDocument Directive 中也有提及,
从 2.4.13 开始,expression syntax 可以在指令内部使用以生成动态字符串和 URL。
从 2.4.13 开始,我们应该可以在 ErrorDocument
中使用表达式了。
挖掘表达式
经过一些实验,我发现并非所有表达式都适用于ErrorDocument
。但expression's BNF notation中指定的variable
可以在ErrorDocument
中解释,
variable ::= "%" varname ""
| "%" funcname ":" funcargs ""
(rebackref
也可能有效,但我不确定如何在 ErrorDocument
中使用它。)
现在我们只需要一些可以计算为空字符串的空变量或函数。
还有一个空字符串表达式,形式为function,
unescape
Unescape
%hex
编码字符串,只留下编码斜线;如果找到%00
,则返回一个空字符串
所以这里是返回空响应体的解决方案,
ErrorDocument 200 %unescape:%00
更多关于ErrorDocument
为什么首先有问题中提到的非空响应体?
我在 apache 的 ErrorDocument Directive 中找到了这个,
如果出现问题或错误,Apache httpd 可以配置为执行以下四种操作之一,
输出一个简单的硬编码错误信息 输出自定义消息 内部重定向到本地 URL 路径以处理问题/错误 重定向到外部 URL 以处理问题/错误
由于未指定 200 的错误文档,Apache 决定使用 200 的硬编码错误消息。
有关硬编码错误消息的详细信息不在文档中,必须在源代码中找到。但我想 200 没有这样的错误消息,所以我们有这个内部错误/错误配置的东西。
可以通过以下方式获得与问题中提到的完全相同的响应
ErrorDocument 200 default
由于 Apache 的 ErrorDocument Directive 提到了这一点,
此外,特殊值 default 可用于指定 Apache httpd 的简单硬编码消息。
【讨论】:
以上是关于从 Apache 返回空响应的主要内容,如果未能解决你的问题,请参考以下文章