Indy Header Last-Modified - 日期编码参数无效
Indy Header Last-Modified - Invalid argument to date encode
我正在使用 Indy 的 TIdHTTP。我发出了 2 个不同的请求,一个 header 包含 'Last-Modified' 标签,另一个不包含。带标签的header,抛出异常:
'Invalid Argument to date encode'
我已经遇到 this question where Remy Lebeau 说,TIdHttp 现在可以解析 ISO8601 日期,但它似乎对我不起作用。正如您在下面看到的,除了更改 UserAgent 之外,我没有对该组件执行任何操作。我错过了什么吗?
url := 'https://api.priceapi.com/v2/jobs/' + JobID+ '?token=' + Token;
http := TIdHTTP.Create(nil);
http.Request.UserAgent := 'XXXXX'; //Some UserAgent
try
ssl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
http.IOHandler := ssl;
try
jo := TJsonObject.ParseJSONValue(http.get(url)) as TJSONObject;
result := jo.GetValue('status').Value;
finally
end;
finally
ssl.Free;
end;
finally
http.Free;
end;
Header 与 Last-Modified:
Cache-Control: no-cache
Content-Disposition: attachment;
filename="20181025145103_google_shopping_de_5bd1d857bbd7e520c12841d7.json"
Content-Transfer-Encoding: binary
Content-Type: application/json
Last-Modified: 2018-10-25 14:51:23 +0000
Vary: Origin
X-Accel-Buffering: no
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: b05aa8fe-7ea9-4152-8470-a75f9816549f
X-Runtime: 0.099212
X-XSS-Protection: 1; mode=block
transfer-encoding: chunked
Connection: keep-alive
Header 没有 Last-Modified:
Cache-Control: max-age=0, private, must-revalidate', nil
Content-Type: application/json; charset=utf-8', nil
ETag: W/"43c4a8865a5ebe565f3920779a962e93"', nil
Vary: Origin', nil
X-Content-Type-Options: nosniff', nil
X-Frame-Options: SAMEORIGIN', nil
X-Request-Id: 344ac82e-0d14-4838-ae7e-627c79b78edc', nil
X-Runtime: 0.062357', nil
X-XSS-Protection: 1; mode=block', nil
Content-Length: 157', nil
Connection: Close', nil
堆栈跟踪:
:744717d2 KERNELBASE.RaiseException + 0x62
HIWBase.System.SysUtils.ConvertError(B68860)
HIWBase.System.SysUtils.EncodeDate(???,???,???)
HIWBase.IdGlobalProtocols.RawStrInternetToDateTime('07:53:37 +0000',0)
HIWBase.IdGlobalProtocols.GMTToLocalDateTime('07:53:37 +0000')
HIWBase.IdHTTPHeaderInfo.TIdEntityHeaderInfo.ProcessHeaders
HIWBase.IdHTTPHeaderInfo.TIdResponseHeaderInfo.ProcessHeaders
HIWBase.IdHTTP.TIdHTTPProtocol.RetrieveHeaders(255)
HIWBase.IdHTTP.TIdCustomHTTP.DoRequest('GET','My URL',nil,$ADF09E0,(...))
HIWBase.IdHTTP.TIdCustomHTTP.Get('My URL',$ADF09E0,(...))
HIWBase.IdHTTP.TIdCustomHTTP.Get('My URL',(...))
HIWBase.IdHTTP.TIdCustomHTTP.Get('My URL')
我使用的是 Indy 版本 10.6.2.5311
Last-Modified
header在RFC 2616 Section 14.291中定义为:
Last-Modified = "Last-Modified" ":" HTTP-date
中出现了等效的定义
HTTP-date
在 RFC 2616 Section 3.3 2 中定义为:
HTTP-date = rfc1123-date | rfc850-date | asctime-date
rfc1123-date = wkday "," SP date1 SP time SP "GMT"
rfc850-date = weekday "," SP date2 SP time SP "GMT"
asctime-date = wkday SP date3 SP time SP 4DIGIT
date1 = 2DIGIT SP month SP 4DIGIT
; day month year (e.g., 02 Jun 1982)
date2 = 2DIGIT "-" month "-" 2DIGIT
; day-month-year (e.g., 02-Jun-82)
date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
; month day (e.g., Jun 2)
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; 00:00:00 - 23:59:59
wkday = "Mon" | "Tue" | "Wed"
| "Thu" | "Fri" | "Sat" | "Sun"
weekday = "Monday" | "Tuesday" | "Wednesday"
| "Thursday" | "Friday" | "Saturday" | "Sunday"
month = "Jan" | "Feb" | "Mar" | "Apr"
| "May" | "Jun" | "Jul" | "Aug"
| "Sep" | "Oct" | "Nov" | "Dec"
2:等效定义出现在 RFC 7231 Section 7.1.1.1.
您显示的 Last-Modified
值与 HTTP 允许的任何格式都不匹配。
TIdHTTP
使用 Indy 的 GMTToLocalDateTime()
函数来解析 Last-Modified
(以及 Date
和 Expires
)header。该功能由 HTTP、IMAP、NNTP 和电子邮件组件共享,因此它 little 在其支持的 date/time 格式方面更加灵活。例如,它确实解析 ISO 8601,您声称 Last-Modified
值是。但是,您显示的值实际上也不符合 ISO 8601。如果有,它看起来会更像这样:
Last-Modified: 2018-10-26T08:37:01+00:00
更糟糕的是,根据您提供的堆栈跟踪,调用 GMTToLocalDateTime()
时根本没有任何日期部分:
HIWBase.IdGlobalProtocols.GMTToLocalDateTime('07:53:37 +0000')
如果 HTTP 服务器发送 Last-Modified
(或 Date
或 Expires
) header 具有该确切值,这也不符合 HTTP 或 ISO 8601 标准,并且 GMTToLocalDateTime()
未处理 as-is。
简而言之,您查询的API正在发送非法date/time格式,TIdHTTP
不支持解析(这是具有讽刺意味的是,因为主 https://www.priceapi.com
网站确实会发送格式正确的 HTTP date/time 字符串)。您应该联系网站管理员并报告他们的 API 服务器在这方面违反了 HTTP 协议标准。
也就是说,GMTToLocalDateTime()
在遇到格式错误的 date/time 字符串时不会引发 'Invalid Argument to date encode'
异常。它是 returns TDateTime
的 0.0
。 只有 你可以看到异常的方式是如果你是 运行 你的代码在调试器中。当 GMTToLocalDateTime()
被赋予格式错误的 date/time 字符串时,它可能会提取它认为有效的数字组件,但在尝试用它们编码最终的 TDateTime
时失败。当给定一个无效的 month/day/year 作为输入时,您看到的异常来自 RTL 的 EncodeDate()
函数。但是 GMTToLocalDateTime()
在内部捕获了该异常。您的代码在运行时永远看不到它,只有调试器可以看到它。
我正在使用 Indy 的 TIdHTTP。我发出了 2 个不同的请求,一个 header 包含 'Last-Modified' 标签,另一个不包含。带标签的header,抛出异常:
'Invalid Argument to date encode'
我已经遇到 this question where Remy Lebeau 说,TIdHttp 现在可以解析 ISO8601 日期,但它似乎对我不起作用。正如您在下面看到的,除了更改 UserAgent 之外,我没有对该组件执行任何操作。我错过了什么吗?
url := 'https://api.priceapi.com/v2/jobs/' + JobID+ '?token=' + Token;
http := TIdHTTP.Create(nil);
http.Request.UserAgent := 'XXXXX'; //Some UserAgent
try
ssl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
http.IOHandler := ssl;
try
jo := TJsonObject.ParseJSONValue(http.get(url)) as TJSONObject;
result := jo.GetValue('status').Value;
finally
end;
finally
ssl.Free;
end;
finally
http.Free;
end;
Header 与 Last-Modified:
Cache-Control: no-cache
Content-Disposition: attachment;
filename="20181025145103_google_shopping_de_5bd1d857bbd7e520c12841d7.json"
Content-Transfer-Encoding: binary
Content-Type: application/json
Last-Modified: 2018-10-25 14:51:23 +0000
Vary: Origin
X-Accel-Buffering: no
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: b05aa8fe-7ea9-4152-8470-a75f9816549f
X-Runtime: 0.099212
X-XSS-Protection: 1; mode=block
transfer-encoding: chunked
Connection: keep-alive
Header 没有 Last-Modified:
Cache-Control: max-age=0, private, must-revalidate', nil
Content-Type: application/json; charset=utf-8', nil
ETag: W/"43c4a8865a5ebe565f3920779a962e93"', nil
Vary: Origin', nil
X-Content-Type-Options: nosniff', nil
X-Frame-Options: SAMEORIGIN', nil
X-Request-Id: 344ac82e-0d14-4838-ae7e-627c79b78edc', nil
X-Runtime: 0.062357', nil
X-XSS-Protection: 1; mode=block', nil
Content-Length: 157', nil
Connection: Close', nil
堆栈跟踪:
:744717d2 KERNELBASE.RaiseException + 0x62
HIWBase.System.SysUtils.ConvertError(B68860)
HIWBase.System.SysUtils.EncodeDate(???,???,???)
HIWBase.IdGlobalProtocols.RawStrInternetToDateTime('07:53:37 +0000',0)
HIWBase.IdGlobalProtocols.GMTToLocalDateTime('07:53:37 +0000')
HIWBase.IdHTTPHeaderInfo.TIdEntityHeaderInfo.ProcessHeaders
HIWBase.IdHTTPHeaderInfo.TIdResponseHeaderInfo.ProcessHeaders
HIWBase.IdHTTP.TIdHTTPProtocol.RetrieveHeaders(255)
HIWBase.IdHTTP.TIdCustomHTTP.DoRequest('GET','My URL',nil,$ADF09E0,(...))
HIWBase.IdHTTP.TIdCustomHTTP.Get('My URL',$ADF09E0,(...))
HIWBase.IdHTTP.TIdCustomHTTP.Get('My URL',(...))
HIWBase.IdHTTP.TIdCustomHTTP.Get('My URL')
我使用的是 Indy 版本 10.6.2.5311
Last-Modified
header在RFC 2616 Section 14.291中定义为:
Last-Modified = "Last-Modified" ":" HTTP-date中出现了等效的定义
HTTP-date
在 RFC 2616 Section 3.3 2 中定义为:
HTTP-date = rfc1123-date | rfc850-date | asctime-date rfc1123-date = wkday "," SP date1 SP time SP "GMT" rfc850-date = weekday "," SP date2 SP time SP "GMT" asctime-date = wkday SP date3 SP time SP 4DIGIT date1 = 2DIGIT SP month SP 4DIGIT ; day month year (e.g., 02 Jun 1982) date2 = 2DIGIT "-" month "-" 2DIGIT ; day-month-year (e.g., 02-Jun-82) date3 = month SP ( 2DIGIT | ( SP 1DIGIT )) ; month day (e.g., Jun 2) time = 2DIGIT ":" 2DIGIT ":" 2DIGIT ; 00:00:00 - 23:59:59 wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" weekday = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday" month = "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"
2:等效定义出现在 RFC 7231 Section 7.1.1.1.
您显示的 Last-Modified
值与 HTTP 允许的任何格式都不匹配。
TIdHTTP
使用 Indy 的 GMTToLocalDateTime()
函数来解析 Last-Modified
(以及 Date
和 Expires
)header。该功能由 HTTP、IMAP、NNTP 和电子邮件组件共享,因此它 little 在其支持的 date/time 格式方面更加灵活。例如,它确实解析 ISO 8601,您声称 Last-Modified
值是。但是,您显示的值实际上也不符合 ISO 8601。如果有,它看起来会更像这样:
Last-Modified: 2018-10-26T08:37:01+00:00
更糟糕的是,根据您提供的堆栈跟踪,调用 GMTToLocalDateTime()
时根本没有任何日期部分:
HIWBase.IdGlobalProtocols.GMTToLocalDateTime('07:53:37 +0000')
如果 HTTP 服务器发送 Last-Modified
(或 Date
或 Expires
) header 具有该确切值,这也不符合 HTTP 或 ISO 8601 标准,并且 GMTToLocalDateTime()
未处理 as-is。
简而言之,您查询的API正在发送非法date/time格式,TIdHTTP
不支持解析(这是具有讽刺意味的是,因为主 https://www.priceapi.com
网站确实会发送格式正确的 HTTP date/time 字符串)。您应该联系网站管理员并报告他们的 API 服务器在这方面违反了 HTTP 协议标准。
也就是说,GMTToLocalDateTime()
在遇到格式错误的 date/time 字符串时不会引发 'Invalid Argument to date encode'
异常。它是 returns TDateTime
的 0.0
。 只有 你可以看到异常的方式是如果你是 运行 你的代码在调试器中。当 GMTToLocalDateTime()
被赋予格式错误的 date/time 字符串时,它可能会提取它认为有效的数字组件,但在尝试用它们编码最终的 TDateTime
时失败。当给定一个无效的 month/day/year 作为输入时,您看到的异常来自 RTL 的 EncodeDate()
函数。但是 GMTToLocalDateTime()
在内部捕获了该异常。您的代码在运行时永远看不到它,只有调试器可以看到它。