我有一些使用THTTPReqResp
的旧代码,它针对Exchange Web Services的SOAP请求调用Execute
。
我正在将其修改为(也)使用OAuth登录。效果很好,但是我无法检测访问令牌何时过期。
在使用来自nSoftware IP * Works的TipwHTTP
组件的测试应用程序中,我可以遍历响应标头来检测指示令牌已过期的标头:
with ipwHTTP do
try
PostData := ABody;
Post(cBaseURL);
except
on e:Exception do
begin
// A special header is returned when the token has expired:
// Header x-ms-diagnostics: 2000002;reason="The token has expired.";error_category="invalid_lifetime"
for l := 0 to ParsedHeaders.Count-1 do
if (Pos('x-ms-diagnostics',ParsedHeaders[l].Field) <> 0)
and (Pos('2000002',ParsedHeaders[l].Value) <> 0) then
begin
FTokenExpired := true;
Break;
end;
...
end;
end;
使用THTTPReqResp
或THTTPReqResp.HTTP
时在哪里/如何访问标头?
该组件包含类型为HTTP
的{{1}}属性,但我对此一无所知。
文档Using an HTTP Client指出THTTPClient
具有
OnRequestError和OnRequestcompleted事件,但是在THTTPClient
或其类帮助程序的代码中找不到这些事件。
这些事件的文档指的是THTTPClient
而不是System.Net.HttpClientComponent.TNetHTTPRequest
, System.Net.THTTPClient
中没有HttpClientComponent
。
注意:
System.Net
进行了重要的代码更改。THTTPReqResp
有一个包含这两个事件的System.Net.HttpClientComponent
,并且注释说它是管理HTTPClient的组件,但是该代码似乎没有链接到(即从未使用过TNetHTTPClient
)HttpClientComponent
(而TNetHTTPClient
是Net文件夹中仅有的两个),但没有TNetHTTPRequest
。这似乎表明THTTPClient
仅用于“幕后”。 THTTPClient
还具有HTTP(TNetHTTPClient
)属性,例如THTTPClient
,但两者之间没有继承。答案 0 :(得分:1)
您已经发现THTTPReqResp
在Delphi 10.3中进行了shot弹枪手术。最初,它是在Windows上使用WinINet,在Linux上是在Linux上使用Indy,但是他们将其更改为THTTPClient
(我想是为了支持移动平台)。
在此新实现中,THTTPReqResp
方法(Get
,Execute
)和事件(OnBeforePost
,OnReceivingData
)中都没有暴露Request
或Response
个对象。
但是,如果服务器以错误的HTTP状态代码(> = 300)响应,则有机会通过全局Response
处理程序访问OnHttpError
对象。使用过程Soap.SOAPHTTPTrans.SetOnHttpError
安装全局处理程序。它以HTTPResponse: IHTTPResponse
作为第二个参数,可让您检查返回的标题。如果服务器以1xx或2xx状态响应,那么您不走运,应该考虑实现自定义THTTPReqResp
后代或迁移到更合适的HTTP客户端实现(例如,直接THTTPClient
或类似的方式)。>
{ assuming HTTPReqResp1: THTTPReqResp is a component on TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
SetOnHttpError(HTTPReqRespError);
end;
procedure TForm1.HTTPReqRespError(const HTTPReqResp: THTTPReqResp;
const HTTPResponse: IHTTPResponse; const Error: ESOAPHTTPException;
var Action: TSOAPHttpErrorAction);
begin
if (HTTPReqResp = HTTPReqResp1) and StartsText('2000002', HTTPResponse.HeaderValue['x-ms-diagnostics']) then
begin
FTokenExpired := True;
Action := TSOAPHttpErrorAction.heaAbort; { or whatever }
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
FTokenExpired := False;
try
{ ... }
{ HTTPReqResp1.Get or HTTPReqResp1.Execute or whatever }
{ ... }
except
if not FTokenExpired then
raise;
{ handle token expiration here }
end;
end;
我个人认为这是处理此类情况的非常丑陋的方式,我只是不明白为什么它们在 new 代码中引入了全局处理程序,从而影响了THTTPReqResp
的所有实例。我对这个新设计完全没有印象。
鹰眼:您是否注意到THTTPReqResp
(THTTPClient
,ESOAPHTTPException
)和SetOnHttpError
(TSOAPHttpErrorEvent
之间的字符大小写不一致,TSOAPHttpErrorAction
)?