ETag的语法是什么?

31

Redbot报告说我的网页有无效的头部:

ETag头的语法无效。

我的头部设置为:

ETag: 4ae413bd

为什么它是无效的?

ETag 的语法是什么?

4个回答

38

尝试使用ETag: "4ae413bd"。 一个ETag的值必须遵循ABNF格式:

  entity-tag = [ weak ] opaque-tag
  weak       = "W/"
  opaque-tag = quoted-string

  quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
  qdtext         = <any TEXT except <">>
  quoted-pair    = "\" CHAR
  CHAR           = <any US-ASCII character (octets 0 - 127)>
  TEXT           = <any OCTET except CTLs, but including LWS>
  OCTET          = <any 8-bit sequence of data>
  LWS            = [CRLF] 1*( SP | HT )
  CTL            = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
  CRLF           = CR LF
  CR             = <US-ASCII CR, carriage return (13)>
  LF             = <US-ASCII LF, linefeed (10)>
  SP             = <US-ASCII SP, space (32)>
  HT             = <US-ASCII HT, horizontal-tab (9)>

这里的 <strong>ETag</strong> 基本上是正则表达式中的 ([wW]/)?"([^"]|\\" )*

请注意,"\""/" 都是有效的 etag 值。

参考资料: 14.19 节3.11 节2.2 节


虽然HTTP 1.1允许使用 "",但HTTP 1.1 bis的草案则不允许。2007年,W3C考虑了这个问题-请参见http://www.w3.org/Protocols/HTTP/1.1/rfc2616bis/issues/#i31-并决定语法有误。它在04草案中得到修复,您可以在http://greenbytes.de/tech/webdav/draft-lafon-rfc2616bis-04.html#rfc.issue.i31-qdtext-bnf中看到编辑内容。因此,无论HTTP 1.1 bis最终何时推出(假设它能够推出),""将不再有效,因此尽管今天技术上允许使用,但最好避免使用。 - Ian Griffiths
我认为计划是在2013年9月作为建议标准提交。 (相关工作组的最后通话应该在今年早些时候关闭,我认为这确实按计划进行了。)我不认为有一个计划需要多长时间才能从“建议”转变为完全成熟 - 我相信这取决于以后才会显现出来的事情(例如采用率,是否发现问题)。 - Ian Griffiths
4
通俗易懂地说,这个值必须以双引号 " 开始和结束。 - Arnaud Meuret
RFC的更新版本https://tools.ietf.org/html/rfc7232#section-2.3。不允许使用空格,例如。 - Nikolay
ETag也可以是*(不带引号) - M. Koch
显示剩余2条评论

15

正如Arnaud所提到的,确保您引用了该值。

替换

new EntityTagHeaderValue("0");

使用

new EntityTagHeaderValue("\"0\"");

7
"

ETag是由Web服务器分配给URL上找到的特定版本资源的不透明标识符。"这意味着它可以是几乎任何东西。

问题可能是语法,使用:

"
ETag: "4ae413bd"

2

如果您因下面的堆栈跟踪而到达此处,请确保在Visual Studio中取消选中“启用浏览器链接”选项,该选项会导致此错误:uncheck this

Conversion> [13:31:10 ERR] Connection id "0HLJ153E20LDJ", Request id "0HLJ153E20LDJ:00000003": An unhandled exception was thrown by the application.
Conversion> System.ObjectDisposedException: The response has been aborted due to an unhandled application exception. ---> System.FormatException: Invalid ETag name
Conversion>    at Microsoft.Net.Http.Headers.EntityTagHeaderValue..ctor(StringSegment tag, Boolean isWeak)
Conversion>    at Microsoft.Net.Http.Headers.EntityTagHeaderValue..ctor(StringSegment tag)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleWareUtil.AddToETag(ResponseHeaders responseHeader, Int32 port)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware.<>c__DisplayClass7_0.<ExecuteWithFilter>b__0()
Conversion>    at Microsoft.AspNetCore.Http.HttpResponse.<>c.<.cctor>b__30_0(Object callback)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FireOnStartingMayAwait(Stack`1 onStarting)
Conversion>    --- End of inner exception stack trace ---
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAbortedException()
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.InitializeResponseAsync(Int32 firstWriteByteCount)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.WriteAsync(ReadOnlyMemory`1 data, CancellationToken cancellationToken)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
Conversion>    at System.IO.Stream.WriteAsync(Byte[] buffer, Int32 offset, Int32 count)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.ScriptInjectionFilterStream.<>c__DisplayClass37_0.<<CreateResponseHandler>b__0>d.MoveNext()
Conversion> --- End of stack trace from previous location where exception was thrown ---
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.SocketReader.ReadBytesIntoResponseHandler(Int64 totalBytesToRead, ResponseHandler handler, CancellationToken cancellationToken)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadBytesIntoResponse(Int64 bytesToRead)
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadChunkedContent()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.HttpSocketAdapter.ResponseReader.ReadResponse()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.DelayConnectingHttpSocketAdapter.Microsoft.VisualStudio.Web.BrowserLink.IHttpSocketAdapter.WaitForResponseComplete()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.ScriptInjectionFilterStream.WaitForFilterComplete()
Conversion>    at Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware.ExecuteWithFilter(IHttpSocketAdapter injectScriptSocket, String requestId, HttpContext httpContext)
Conversion>    at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Conversion>    at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Conversion>    at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
Conversion>    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接