返回Apache的空响应

时间:2014-12-30 10:36:26

标签: apache cors

我使用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实际返回一个空体。

谢谢!

2 个答案:

答案 0 :(得分:11)

对OPTIONS请求的204代码(无内容)的响应。

例如:

RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=204,L]

答案 1 :(得分:9)

204应该足以进行CORS限制。但是,在其他情况下,可能需要使用不同的状态代码进行空响应。​​

TL; DR

警告:ErrorDocument 2xx和3xx是无证件行为。

要发送空体的回复,请将RewriteRuleErrorDocument合并。

# 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无内容

带有204 No Content的

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] flagErrorDocument输入此状态以使其生效。

然而,这不是故事的结尾,如下面的配置,

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>
     

将操作视为:

     
      
  1. 要重定向到的本地网址(如果操作以“/")开头。
  2.   
  3. 要重定向到的外部网址(如果操作是有效的网址)。
  4.   
  5. 要显示的文本(如果不是上述内容)。如果文本由多个单词组成,则必须用引号(“)括起来。
  6.   

还在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配置为执行以下四种操作之一

     
      
  1. 输出简单的硬编码错误消息
  2.   
  3. 输出自定义消息
  4.   
  5. 在内部重定向到本地URL路径以处理问题/错误
  6.   
  7. 重定向到外部网址以处理问题/错误
  8.   

由于未指定200的错误文档,Apache决定使用200的硬编码错误消息。

有关硬编码错误消息的详细信息不在文档中,必须在源代码中找到。但我想200没有这样的错误消息,所以我们有这个内部错误/配置错误的东西。

问题中提到的完全相同的答案可以通过

获得
ErrorDocument 200 default

因为Apache的ErrorDocument Directive提到了这个,

  

此外,特殊值默认可用于指定Apache httpd的简单硬编码消息。