📄 idhttp.pas
字号:
Connect(ReadTimeout);
except
on E: EIdSSLProtocolReplyError do
begin
Disconnect;
raise;
end;
end;
end;
procedure TIdCustomHTTP.ConnectToHost(ARequest: TIdHTTPRequest; AResponse: TIdHTTPResponse);
var
LLocalHTTP: TIdHTTPProtocol;
begin
ARequest.FUseProxy := SetHostAndPort;
if ARequest.UseProxy = ctProxy then
begin
ARequest.URL := FURI.URI;
end;
case ARequest.UseProxy of
ctNormal:
if (ProtocolVersion = pv1_0) and (Length(ARequest.Connection) = 0) then
ARequest.Connection := 'keep-alive';
ctSSL, ctSSLProxy: ARequest.Connection := '';
ctProxy:
if (ProtocolVersion = pv1_0) and (Length(ARequest.Connection) = 0) then
ARequest.ProxyConnection := 'keep-alive';
end;
if ARequest.UseProxy = ctSSLProxy then begin
LLocalHTTP := TIdHTTPProtocol.Create(Self);
with LLocalHTTP do begin
Request.UserAgent := ARequest.UserAgent;
Request.Host := ARequest.Host;
Request.ContentLength := ARequest.ContentLength;
Request.Pragma := 'no-cache';
Request.URL := URL.Host + ':' + URL.Port;
Request.Method := hmConnect;
Request.ProxyConnection := 'keep-alive';
Response.ContentStream := TMemoryStream.Create;
try
try
repeat
CheckAndConnect(Response);
BuildAndSendRequest(nil);
Response.ResponseText := ReadLn;
if Length(Response.ResponseText) = 0 then begin
Response.ResponseText := 'HTTP/1.0 200 OK'; // Support for HTTP responses whithout Status line and headers
Response.Connection := 'close';
end
else begin
RetrieveHeaders;
ProcessCookies(LLocalHTTP.Request, LLocalHTTP.Response);
end;
if Response.ResponseCode = 200 then
begin
// Connection established
(IOHandler as TIdSSLIOHandlerSocket).PassThrough := false;
break;
end
else begin
ProcessResponse;
end;
until false;
except
raise;
// TODO: Add property that will contain the error messages.
end;
finally
LLocalHTTP.Response.ContentStream.Free;
LLocalHTTP.Free;
end;
end;
end
else begin
CheckAndConnect(AResponse);
end;
FHTTPProto.BuildAndSendRequest(URL);
if (ARequest.Method in [hmPost, hmPut]) then
begin
WriteStream(ARequest.Source, True, false);
end;
end;
procedure TIdCustomHTTP.DoRequest(const AMethod: TIdHTTPMethod; AURL: string;
const ASource, AResponseContent: TStream);
var
LResponseLocation: Integer;
begin
if Assigned(AResponseContent) then
begin
LResponseLocation := AResponseContent.Position;
end
else
LResponseLocation := 0; // Just to avoid the waringing message
FAuthRetries := 0;
FAuthProxyRetries := 0;
Request.URL := AURL;
Request.Method := AMethod;
Request.Source := ASource;
Response.ContentStream := AResponseContent;
try
repeat
Inc(FRedirectCount);
PrepareRequest(Request);
ConnectToHost(Request, Response);
// Workaround for servers wich respond with 100 Continue on GET and HEAD
// This workaround is just for temporary use until we have final HTTP 1.1
// realisation
repeat
Response.ResponseText := ReadLn;
FHTTPProto.RetrieveHeaders;
ProcessCookies(Request, Response);
until Response.ResponseCode <> 100;
case FHTTPProto.ProcessResponse of
wnAuthRequest: begin
Dec(FRedirectCount);
Request.URL := AURL;
end;
wnReadAndGo: begin
ReadResult(Response);
if Assigned(AResponseContent) then
begin
AResponseContent.Position := LResponseLocation;
AResponseContent.Size := LResponseLocation;
end;
FAuthRetries := 0;
FAuthProxyRetries := 0;
end;
wnGoToURL: begin
if Assigned(AResponseContent) then
begin
AResponseContent.Position := LResponseLocation;
AResponseContent.Size := LResponseLocation;
end;
FAuthRetries := 0;
FAuthProxyRetries := 0;
end;
wnJustExit: begin
break;
end;
wnDontKnow:
// TODO: This is for temporary use. Will remove it for final release
raise EIdException.Create('Undefined situation');
end;
until false;
finally
if not Response.KeepAlive then begin
Disconnect;
end;
end;
FRedirectCount := 0;
end;
procedure TIdCustomHTTP.SetAllowCookies(AValue: Boolean);
begin
FAllowCookies := AValue;
end;
procedure TIdCustomHTTP.ProcessCookies(ARequest: TIdHTTPRequest; AResponse: TIdHTTPResponse);
var
Cookies, Cookies2: TStringList;
i: Integer;
begin
Cookies := nil;
Cookies2 := nil;
try
if not Assigned(FCookieManager) and AllowCookies then
begin
CookieManager := TIdCookieManager.Create(Self);
FFreeOnDestroy := true;
end;
if Assigned(FCookieManager) then
begin
Cookies := TStringList.Create;
Cookies2 := TStringList.Create;
AResponse.RawHeaders.Extract('Set-cookie', Cookies);
AResponse.RawHeaders.Extract('Set-cookie2', Cookies2);
for i := 0 to Cookies.Count - 1 do
CookieManager.AddCookie(Cookies[i], FURI.Host);
for i := 0 to Cookies2.Count - 1 do
CookieManager.AddCookie2(Cookies2[i], FURI.Host);
end;
finally
FreeAndNil(Cookies);
FreeAndNil(Cookies2);
end;
end;
procedure TIdCustomHTTP.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if Operation = opRemove then
begin
if (AComponent = FCookieManager) then
begin
FCookieManager := nil;
end;
if AComponent = FAuthenticationManager then
begin
FAuthenticationManager := nil;
end;
end;
end;
procedure TIdCustomHTTP.SetCookieManager(ACookieManager: TIdCookieManager);
begin
if Assigned(FCookieManager) then
begin
if FFreeOnDestroy then begin
FCookieManager.Free;
end;
end;
FCookieManager := ACookieManager;
FFreeOnDestroy := false;
if Assigned(FCookieManager) then
begin
FCookieManager.FreeNotification(Self);
end;
end;
function TIdCustomHTTP.DoOnAuthorization(ARequest: TIdHTTPRequest; AResponse: TIdHTTPResponse): Boolean;
var
i: Integer;
S: string;
Auth: TIdAuthenticationClass;
begin
Inc(FAuthRetries);
if not Assigned(ARequest.Authentication) then
begin
// Find wich Authentication method is supported from us.
for i := 0 to AResponse.WWWAuthenticate.Count - 1 do
begin
S := AResponse.WWWAuthenticate[i];
Auth := FindAuthClass(Fetch(S));
if Auth <> nil then
break;
end;
if Auth = nil then begin
result := false;
exit;
end;
if Assigned(FOnSelectAuthorization) then
begin
OnSelectAuthorization(self, Auth, AResponse.WWWAuthenticate);
end;
ARequest.Authentication := Auth.Create;
end;
// Clear password and reset autorization if previous failed
{if (AResponse.FResponseCode = 401) then begin
ARequest.Password := '';
ARequest.Authentication.Reset;
end;}
result := Assigned(FOnAuthorization);
if Result then
begin
with ARequest.Authentication do
begin
Username := ARequest.Username;
Password := ARequest.Password;
Params.Values['Authorization'] := ARequest.Authentication.Authentication;
AuthParams := AResponse.WWWAuthenticate;
end;
result := false;
repeat
case ARequest.Authentication.Next of
wnAskTheProgram:
begin // Ask the user porgram to supply us with authorization information
if Assigned(FOnAuthorization) then
begin
ARequest.Authentication.UserName := ARequest.Username;
ARequest.Authentication.Password := ARequest.Password;
OnAuthorization(self, ARequest.Authentication, result);
if result then begin
ARequest.BasicAuthentication := true;
ARequest.Username := ARequest.Authentication.UserName;
ARequest.Password := ARequest.Authentication.Password;
end
else begin
break;
end;
end;
end;
wnDoRequest:
begin
result := true;
break;
end;
wnFail:
begin
result := False;
Break;
end;
end;
until false;
end;
end;
function TIdCustomHTTP.DoOnProxyAuthorization(ARequest: TIdHTTPRequest; AResponse: TIdHTTPResponse): Boolean;
var
i: Integer;
S: string;
Auth: TIdAuthenticationClass;
begin
Inc(FAuthProxyRetries);
if not Assigned(ProxyParams.Authentication) then
begin
// Find wich Authentication method is supported from us.
for i := 0 to AResponse.ProxyAuthenticate.Count - 1 do
begin
S := AResponse.ProxyAuthenticate[i];
try
Auth := FindAuthClass(Fetch(S));
break;
except
end;
end;
if i = AResponse.ProxyAuthenticate.Count then
begin
result := false;
exit;
end;
if Assigned(FOnSelectProxyAuthorization) then
begin
OnSelectProxyAuthorization(self, Auth, AResponse.ProxyAuthenticate);
end;
ProxyParams.Authentication := Auth.Create;
end;
result := Assigned(OnProxyAuthorization);
// Clear password and reset autorization if previous failed
if (AResponse.FResponseCode = 407) then begin
ProxyParams.ProxyPassword := '';
ProxyParams.Authentication.Reset;
end;
if Result then
begin
with ProxyParams.Authentication do
begin
Username := ProxyParams.ProxyUsername;
Password := ProxyParams.ProxyPassword;
AuthParams := AResponse.ProxyAuthenticate;
end;
result := false;
repeat
case ProxyParams.Authentication.Next of
wnAskTheProgram: // Ask the user porgram to supply us with authorization information
begin
if Assigned(OnProxyAuthorization) then
begin
ProxyParams.Authentication.Username := ProxyParams.ProxyUsername;
ProxyParams.Authentication.Password := ProxyParams.ProxyPassword;
OnProxyAuthorization(self, ProxyParams.Authentication, result);
if result then begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -