📄 idhttp.pas
字号:
ProxyParams.ProxyUsername := ProxyParams.Authentication.Username;
ProxyParams.ProxyPassword := ProxyParams.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.GetResponseCode: Integer;
begin
result := Response.ResponseCode;
end;
function TIdCustomHTTP.GetResponseText: string;
begin
result := Response.FResponseText;
end;
function TIdCustomHTTP.GetResponseHeaders: TIdHTTPResponse;
begin
result := FHTTPProto.Response;
end;
function TIdCustomHTTP.GetRequestHeaders: TIdHTTPRequest;
begin
result := FHTTPProto.Request;
end;
procedure TIdCustomHTTP.DoOnDisconnected;
begin
inherited DoOnDisconnected;
if Assigned(Request.Authentication) and
(Request.Authentication.CurrentStep = Request.Authentication.Steps) then begin
if Assigned(AuthenticationManager) then begin
AuthenticationManager.AddAuthentication(Request.Authentication, URL);
end;
FreeAndNil(Request.Authentication);
end;
if Assigned(ProxyParams.Authentication) then begin
ProxyParams.Authentication.Reset;
end;
end;
procedure TIdCustomHTTP.SetAuthenticationManager(const Value: TIdAuthenticationManager);
begin
FAuthenticationManager := Value;
if Assigned(FAuthenticationManager) then
begin
FAuthenticationManager.FreeNotification(self);
end;
end;
procedure TIdCustomHTTP.SetHost(const Value: string);
begin
inherited SetHost(Value);
URL.Host := Value;
end;
procedure TIdCustomHTTP.SetPort(const Value: integer);
begin
inherited SetPort(Value);
URL.Port := IntToStr(Value);
end;
procedure TIdCustomHTTP.SetRequestHEaders(const Value: TIdHTTPRequest);
begin
FHTTPProto.Request.Assign(Value);
end;
procedure TIdCustomHTTP.Post(AURL: string;
const ASource: TIdMultiPartFormDataStream; AResponseContent: TStream);
begin
Request.ContentType := ASource.RequestContentType;
Post(AURL, TStream(ASource), AResponseContent);
end;
function TIdCustomHTTP.Post(AURL: string;
const ASource: TIdMultiPartFormDataStream): string;
begin
Request.ContentType := ASource.RequestContentType;
result := Post(AURL, TStream(ASource));
end;
{ TIdHTTPResponse }
constructor TIdHTTPResponse.Create(AParent: TIdCustomHTTP);
begin
inherited Create;
FHTTP := AParent;
end;
function TIdHTTPResponse.GetKeepAlive: Boolean;
var
S: string;
i: TIdHTTPProtocolVersion;
begin
S := Copy(FResponseText, 6, 3);
for i := Low(TIdHTtpProtocolVersion) to High(TIdHTtpProtocolVersion) do
if AnsiSameText(ProtocolVersionString[i], S) then
begin
ResponseVersion := i;
break;
end;
FHTTP.CheckForDisconnect(false);
FKeepAlive := FHTTP.Connected;
if FKeepAlive then
case FHTTP.ProtocolVersion of
pv1_1: // By default we assume that keep-alive is by default and will close the connection only there is "close"
begin
FKeepAlive :=
not (AnsiSameText(Trim(Connection), 'CLOSE') or
AnsiSameText(Trim(ProxyConnection), 'CLOSE'));
end;
pv1_0: // By default we assume that keep-alive is not by default and will keep the connection only if there is "keep-alive"
begin
FKeepAlive := AnsiSameText(Trim(Connection), 'KEEP-ALIVE') or
AnsiSameText(Trim(ProxyConnection), 'KEEP-ALIVE') {or
((ResponseVersion = pv1_1) and (Length(Trim(Connection)) = 0) and
(Length(Trim(ProxyConnection)) = 0))};
end;
end;
result := FKeepAlive;
end;
function TIdHTTPResponse.GetResponseCode: Integer;
var
S: string;
begin
S := FResponseText;
Fetch(S);
S := Trim(S);
FResponseCode := StrToIntDef(Fetch(S, ' ', False), -1);
Result := FResponseCode;
end;
{ TIdHTTPRequest }
constructor TIdHTTPRequest.Create(AHTTP: TIdCustomHTTP);
begin
inherited Create;
FHTTP := AHTTP;
FUseProxy := ctNormal;
end;
{ TIdHTTPProtocol }
constructor TIdHTTPProtocol.Create(AConnection: TIdCustomHTTP);
begin
inherited Create;
FHTTP := AConnection;
// Create the headers
FRequest := TIdHTTPRequest.Create(FHTTP);
FResponse := TIdHTTPResponse.Create(FHTTP);
end;
destructor TIdHTTPProtocol.Destroy;
begin
FreeAndNil(FRequest);
FreeAndNil(FResponse);
inherited Destroy;
end;
procedure TIdHTTPProtocol.BuildAndSendRequest(AURI: TIdURI);
var
i: Integer;
begin
Request.SetHeaders;
FHTTP.ProxyParams.SetHeaders(Request.RawHeaders);
if Assigned(AURI) then
FHTTP.SetCookies(AURI, Request);
// This is a wrokaround for some HTTP servers wich does not implement properly the HTTP protocol
FHTTP.OpenWriteBuffer;
case Request.Method of
hmHead: FHTTP.WriteLn('HEAD ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
hmGet: FHTTP.WriteLn('GET ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
hmPost: FHTTP.WriteLn('POST ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
// HTTP 1.1 only
hmOptions: FHTTP.WriteLn('OPTIONS ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
hmTrace: FHTTP.WriteLn('TRACE ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
hmPut: FHTTP.WriteLn('PUT ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
hmConnect: FHTTP.WriteLn('CONNECT ' + Request.URL + ' HTTP/' + ProtocolVersionString[FHTTP.ProtocolVersion]); {do not localize}
end;
// write the headers
for i := 0 to Request.RawHeaders.Count - 1 do
if Length(Request.RawHeaders.Strings[i]) > 0 then
FHTTP.WriteLn(Request.RawHeaders.Strings[i]);
FHTTP.WriteLn('');
FHTTP.CloseWriteBuffer;
end;
procedure TIdHTTPProtocol.RetrieveHeaders;
var
S: string;
begin
// Set the response headers
// Clear headers
// Don't use Capture.
Response.RawHeaders.Clear;
s := FHTTP.ReadLn;
try
while Length(s) > 0 do
begin
Response.RawHeaders.Add(S);
s := FHTTP.ReadLn;
end;
except
on E: EIdConnClosedGracefully do begin
FHTTP.Disconnect;
end;
end;
Response.ProcessHeaders;
end;
function TIdHTTPProtocol.ProcessResponse: TIdHTTPWhatsNext;
procedure RaiseException;
var
LRespStream: TStringStream;
LTempStream: TStream;
LTemp: Integer;
begin
LTemp := FHTTP.ReadTimeout;
FHTTP.ReadTimeout := 2000; // Lets wait 2 seconds for any kind of content
LRespStream := TStringStream.Create('');
LTempStream := Response.ContentStream;
Response.ContentStream := LRespStream;
try
FHTTP.ReadResult(Response);
// raise EIdHTTPProtocolException.CreateError(Response.ResponseCode, FHTTP.ResponseText, LRespStream.DataString);
finally
Response.ContentStream := LTempStream;
LRespStream.Free;
FHTTP.ReadTimeout := LTemp;
end;
end;
procedure ReadContent;
Var
LTempResponse: TStringStream;
LTempStream: TStream;
begin
LTempResponse := TStringStream.Create('');
LTempStream := Response.ContentStream;
Response.ContentStream := LTempResponse;
try
FHTTP.ReadResult(Response);
finally
LTempResponse.Free;
Response.ContentStream := LTempStream;
end;
end;
var
LTemp: Integer;
LLocation: string;
LMethod: TIdHTTPMethod;
LResponseDigit: Integer;
LNeedAutorization: Boolean;
begin
result := wnDontKnow;
LNeedAutorization := False;
LResponseDigit := Response.ResponseCode div 100;
// Handle Redirects
if ((LResponseDigit = 3) and (Response.ResponseCode <> 304)) or (Length(Response.Location) > 0) then
begin
// LLocation := TIdURI.URLDecode(Response.Location);
LLocation := Response.Location;
if (FHTTP.FHandleRedirects) and (FHTTP.FRedirectCount < FHTTP.FRedirectMax) then
begin
LMethod := Request.Method;
if FHTTP.DoOnRedirect(LLocation, LMethod, FHTTP.FRedirectCount) then
begin
result := wnGoToURL;
Request.URL := LLocation;
Request.Method := LMethod;
end
else
RaiseException;
end
else // Just fire the event
begin
LMethod := Request.Method;
result := wnJustExit;
if not FHTTP.DoOnRedirect(LLocation, LMethod, FHTTP.FRedirectCount) then // If not Handled
RaiseException
else
Response.Location := LLocation;
end;
if FHTTP.Connected then
begin
// This is a workaround for buggy HTTP 1.1 servers which
// does not return any body with 302 response code
LTemp := FHTTP.ReadTimeout;
FHTTP.ReadTimeout := 4000; // Lets wait 4 seconds for any kind of content
try
ReadContent;
except end;
FHTTP.ReadTimeout := LTemp;
end;
end
else
begin
// GREGOR Workaround
// if we get an error we disconnect if we use SSLIOHandler
if Assigned(FHTTP.IOHandler) then
begin
Response.KeepAlive := not (FHTTP.Connected and (FHTTP.IOHandler is TIdSSLIOHandlerSocket) and Response.KeepAlive);
end;
if LResponseDigit <> 2 then
begin
result := wnGoToURL;
case Response.ResponseCode of
401:
begin // HTTP Server authorization requered
if (FHTTP.FAuthRetries >= FHTTP.AuthRetries) or not FHTTP.DoOnAuthorization(Request, Response) then
begin
if Assigned(Request.Authentication) then
Request.Authentication.Reset;
RaiseException;
end else begin
if hoInProcessAuth in FHTTP.HTTPOptions then
LNeedAutorization := True;
end;
end;
407:
begin // Proxy Server authorization requered
if (FHTTP.FAuthProxyRetries >= FHTTP.AuthRetries) or not FHTTP.DoOnProxyAuthorization(Request, Response) then
begin
if Assigned(FHTTP.ProxyParams.Authentication) then
FHTTP.ProxyParams.Authentication.Reset;
RaiseException;
end else begin
if hoInProcessAuth in FHTTP.HTTPOptions then
LNeedAutorization := True;
end;
end;
else begin
// RaiseException;
end;
end;
end;
if FHTTP.Connected then begin
if LNeedAutorization then begin
// Read the content of Error message in temporary stream
LTemp := FHTTP.ReadTimeout;
FHTTP.ReadTimeout := 4000; // Lets wait 4 seconds for any kind of content
try
ReadContent;
except end;
FHTTP.ReadTimeout := LTemp;
result := wnAuthRequest
end
else if (Response.ResponseCode <> 204) then
begin
FHTTP.ReadResult(Response);
result := wnJustExit;
end
else
result := wnJustExit;
end;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -