1

我遇到了一个关于 Indy 10 IdHTTP 客户端的奇怪问题。

我编写了一个应用程序,它连接到托管在 IIS 8.5 上的 .NET HTTPS 网站,执行 GET,提取 Viewstate 等,然后对登录表单执行 POST,传回 viewstate 和登录参数。

我的应用程序需要每 30 分钟重复一次,作为一种心跳形式。

我发现如果我将 TIdHTTP、TIdSSLIOHandlerSocketOpenSSL 和 TIdCookieManager 放在表单上,​​然后将它们连接起来,并设置它们的各种参数,那么我可以先执行 GET,然后执行 POST,一切正常。

但是,如果没有关闭表单,我再做一次,那么我在第二个 GET 上从服务器返回的响应要么是空的,要么是少量字节,所以我提取 Viewstate 的逻辑失败,随后的 POST包含不正确的数据,导致服务器出现 500 错误。

这是一个日志摘录来说明:

2018-07-14 14:03:49 - Service Started
2018-07-14 14:04:48 - Configuration loaded
2018-07-14 14:04:48 - Service Executed
2018-07-14 14:04:48 - sending GET request
2018-07-14 14:04:49 - Get response = HTTP/1.1 200 OK
2018-07-14 14:04:49 - sending POST request
2018-07-14 14:04:49 - __EVENTTARGET=&__EVENTARGUMENT=&    __VIEWSTATE=%2FwEPDwUJODIyMTE4ODg2D2QWAmYPZBYCAgMPZBYOAgMPDxYCHgdWaXNpYmxlaGRkAgUPDxYCHwBoZGQCCQ8PFgIfAGhkFgJmDxYCHgtfIUl0ZW1Db3VudGZkAgsPPCsABQEADxYCHwBoZGQCDQ8WAh8AaGQCEw9kFgICAQ8PFgIfAGdkFgICAQ9kFgICAQ9kFgJmD2QWAgIBD2QWAmYPZBYCAg0PEA8WAh4HQ2hlY2tlZGhkZGRkAhUPFgIeBFRleHQFHCYjMTY5OyAyMDE4IFN0YW5zdGVkIEV4cHJlc3NkGAIFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBSVjdGwwMCRDcE1haW4kTG9naW4xJExvZ2luMSRSZW1lbWJlck1lBSJjdGwwMCRDcE1haW4kTG9naW4xJExvZ2luTXVsdGlWaWV3Dw9kZmQMaw6DwiWb7Dsi6X%2BgNBnXKQcEqw%3D%3D&__EVENTVALIDATION=%2FwEdAAVTevg71fLSFTbKbOw%2F93SHsrUT%2BQjdDS15mCJiqiynuBdZ2pvBHooH4AJuhXVIPc1mZjzeA4EOClAyNHHGNchy3%2FmkJIoBKJzRpOCUtULeTi1Kr73J8c%2B%2BfFWSSK7ysEo5hJkL&ctl00$CpMain$Login1$Login1$UserName=--------&ctl00$CpMain$Login1$Login1$Password=---------&ctl00$CpMain$Login1$Login1$LoginButton=Log%2Bin
2018-07-14 14:04:49 - Post response = HTTP/1.1 200 OK
2018-07-14 14:05:50 - Configuration loaded
2018-07-14 14:05:50 - Service Executed
2018-07-14 14:05:50 - sending GET request
2018-07-14 14:05:50 - Get response = HTTP/1.1 200 OK
2018-07-14 14:05:50 - sending POST request
2018-07-14 14:05:50 - __EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=&__EVENTVALIDATION=&ctl00$CpMain$Login1$Login1$UserName=------&ctl00$CpMain$Login1$Login1$Password=--------&ctl00$CpMain$Login1$Login1$LoginButton=Log%2Bin
2018-07-14 14:05:50 - Post request failed
2018-07-14 14:05:50 - Post response = HTTP/1.1 500 Internal Server Error

我发现第二个 GET 请求从服务器获取此响应,而不是正确的文档:

2018-07-14 14:27:45 - Service Executed
2018-07-14 14:27:45 - sending GET request
2018-07-14 14:27:45 - ?
2018-07-14 14:27:45 - Get response = HTTP/1.1 200 OK

所以它仍然返回 200 OK 但没有内容。

我尝试了各种方法来弄清楚为什么会发生这种情况,我以为我无意中在我的请求或其他东西上设置了一个范围,但一切都检查了。我检查了我使用的所有变量、MemoryStreams、StringLists 等是否在对 GET 的调用之间被重置。

因此,在绝望中,我考虑了某种可能性,即 TIdHTTP 组件以某种方式没有发出相同的请求,或者正在持久化第一个响应的数据。

所以我从表单中删除了组件,并在运行时在我的 DoGetRequest 和 DoPostRequest 过程中重新创建它们,如下所示:

procedure TBackofficeHeartbeat.DoGetRequest;
var
  GetResponse: string;
begin
     LogActivity('sending GET request');
     IdHTTP1 := TIdHTTP.Create(nil);
     IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
     IdSSL.SSLOptions.SSLVersions := [sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2];
     IdSSL.SSLOptions.Method := sslvSSLv23;
     IdCookie := TIdCookieManager.Create(nil);
     IdHTTP1.CookieManager := IdCookie;
     IdHTTP1.IOHandler := IdSSL;
     IdHTTP1.Request.CacheControl := 'no-cache';
     IdHTTP1.Request.Connection := 'close';
     IdHTTP1.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
     try
          try
               GetResponse := idHTTP1.Get(cfgLiveURL);
          except
               LogActivity('Get request failed');
          end;
          //if cfgDebug then LogActivity(GetResponse);
          html := GetResponse;
          LogActivity('Get response = ' + IdHTTP1.ResponseText);
      finally
           IdCookie.Free;
           IdSSL.Free;
           IdHTTP1.Free;
      end;
end;

奇怪的是,这样做之后,对 GET 和 POST 进行后续调用就不再有问题了,它们总是有效的。

这表明以某种方式存在数据的持久性,这会导致 TIdHTTP 组件上的第二个 GET 请求出现差异,该组件不会在调用之间被销毁和重新创建。

谁能建议这可能是什么原因?例如,可能是会话没有关闭,因此服务器认为您正在进行刷新,而不是完整的请求?

查看 IIS 日志并使用 Fiddler,我找不到第一个和第二个 GET 请求之间的任何区别,但服务器的响应不同。

我的应用程序正在运行,所以这不是一个大问题。只是好奇雷米或其他人是否可以解释。

编辑:

根据 Remy 的建议,我添加了一个 TIdLogFile,从它的输出可以明显看出,第一次和第二次 GET 调用存在差异。

Sent 15/07/2018 10:07:37: GET / HTTP/1.1<EOL>
Host:backoffice.stanstedexpress.com<EOL>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<EOL>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0<EOL><EOL>

在做 POST 之后:

Sent 15/07/2018 10:07:57: GET / HTTP/1.1<EOL>
Connection: Keep-Alive<EOL>
Content-Type: application/x-www-form-urlencoded; charset=UTF-8<EOL>
Host: backoffice.stanstedexpress.com<EOL>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<EOL>
Accept-Encoding: gzip,deflate, identity<EOL>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0<EOL>
Cookie: ASP.NET_SessionId=w1b5tdn4uks5qn4zxthybq2f<EOL><EOL>

我认为这可以解释不同的服务器响应。

4

0 回答 0