我使用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 %{AccessControlAllowOrigin}e 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实际返回一个空体。
谢谢!
答案 0 :(得分:11)
对OPTIONS请求的204代码(无内容)的响应。
例如:
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=204,L]
答案 1 :(得分:9)
204应该足以进行CORS限制。但是,在其他情况下,可能需要使用不同的状态代码进行空响应。
警告: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
RewriteRule
按预期工作,但主流浏览器处理的方式与其他状态代码(如200和301,内容为空)不同。
如MDN: 204 No Content中所述,
HTTP 204无内容成功状态响应代码表示请求已成功,但客户端无需离开当前页面。
如果您访问某个网址并返回204,则Firefox和Chromium将会发生任何事情,保持导航栏中页面和网址的内容不变。
这可能是需要与否。
但是,如果你想要200响应与空内容相同的效果并关心Firefox / Chromium / etc,或者想要使用其他HTTP状态代码,那么带{204的RewriteRule
不是解决方案。
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并在文档中查找“space”和“quote”之后,我找不到令人满意的解释,或者将空字符串作为参数的任何提示。它仅在包含空格的参数的情况下提及引号。
ErrorDocument
正如Apache的Custom Error Responses所说,
ErrorDocument指令的语法是:
ErrorDocument <3-digit-code> <action>
将操作视为:
- 要重定向到的本地网址(如果操作以“/")开头。
- 要重定向到的外部网址(如果操作是有效的网址)。
- 要显示的文本(如果不是上述内容)。如果文本由多个单词组成,则必须用引号(“)括起来。
醇>
还在Apache的ErrorDocument Directive中注意到,
从2.4.13开始,可以在指令中使用expression syntax来生成动态字符串和URL。
我们应该可以使用2.4.13 on 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路径以处理问题/错误
- 重定向到外部网址以处理问题/错误
醇>
由于未指定200的错误文档,Apache决定使用200的硬编码错误消息。
有关硬编码错误消息的详细信息不在文档中,必须在源代码中找到。但我想200没有这样的错误消息,所以我们有这个内部错误/配置错误的东西。
问题中提到的完全相同的答案可以通过
获得ErrorDocument 200 default
因为Apache的ErrorDocument Directive提到了这个,
此外,特殊值默认可用于指定Apache httpd的简单硬编码消息。