📄 idhttp.pas
字号:
DoRequest(hmGet, AURL, nil, AResponseContent);
end;
procedure TIdCustomHTTP.Trace(AURL: string; const AResponseContent: TStream);
begin
DoRequest(hmTrace, AURL, nil, AResponseContent);
end;
procedure TIdCustomHTTP.Head(AURL: string);
begin
DoRequest(hmHead, AURL, nil, nil);
end;
procedure TIdCustomHTTP.Post(AURL: string; const ASource, AResponseContent: TStream);
var
OldProtocol: TIdHTTPProtocolVersion;
begin
// PLEASE READ CAREFULLY
// Currently when issuing a POST, IdHTTP will automatically set the protocol
// to version 1.0 independently of the value it had initially. This is because
// there are some servers that don't respect the RFC to the full extent. In
// particular, they don't respect sending/not sending the Expect: 100-Continue
// header. Until we find an optimum solution that does NOT break the RFC, we
// will restrict POSTS to version 1.0.
if Connected then
begin
Disconnect;
end;
OldProtocol := FProtocolVersion;
// If hoKeepOrigProtocol is SET, is possible to assume that the developer
// is sure in operations of the server
if not (hoKeepOrigProtocol in FOptions) then
FProtocolVersion := pv1_0;
DoRequest(hmPost, AURL, ASource, AResponseContent);
FProtocolVersion := OldProtocol;
end;
procedure TIdCustomHTTP.EncodeRequestParams(const AStrings: TStrings);
var
i: Integer;
S: string;
begin
for i := 0 to AStrings.Count - 1 do begin
S := AStrings.Names[i];
if Length(AStrings.Values[S]) > 0 then begin
AStrings.Values[S] := TIdURI.ParamsEncode(AStrings.Values[S]);
end;
end;
end;
function TIdCustomHTTP.SetRequestParams(const AStrings: TStrings): string;
var
S: string;
begin
if Assigned(AStrings) then begin
if hoForceEncodeParams in FOptions then
EncodeRequestParams(AStrings);
if AStrings.Count > 1 then
S := StringReplace(AStrings.Text, sLineBreak, '&', [rfReplaceall])
else
S := AStrings.Text;
// break trailing CR&LF
Result := Trim(S);
end else
Result := '';
end;
procedure TIdCustomHTTP.Post(AURL: string; const ASource: TStrings; const AResponseContent: TStream);
var
LParams: TStringStream;
begin
// Usual posting request have default ContentType is application/x-www-form-urlencoded
if (Request.ContentType = '') or (AnsiSameText(Request.ContentType, 'text/html')) then
Request.ContentType := 'application/x-www-form-urlencoded';
LParams := TStringStream.Create(SetRequestParams(ASource));
try
Post(AURL, LParams, AResponseContent);
finally
LParams.Free;
end;
end;
function TIdCustomHTTP.Post(AURL: string; const ASource: TStrings): string;
var
LResponse: TStringStream;
begin
LResponse := TStringStream.Create('');
try
Post(AURL, ASource, LResponse);
finally
result := LResponse.DataString;
LResponse.Free;
end;
end;
function TIdCustomHTTP.Post(AURL: string; const ASource: TStream): string;
var
LResponse: TStringStream;
begin
LResponse := TStringStream.Create('');
try
Post(AURL, ASource, LResponse);
finally
result := LResponse.DataString;
LResponse.Free;
end;
end;
procedure TIdCustomHTTP.Put(AURL: string; const ASource, AResponseContent: TStream);
begin
DoRequest(hmPut, AURL, ASource, AResponseContent);
end;
function TIdCustomHTTP.Put(AURL: string; const ASource: TStream): string;
var
LResponse: TStringStream;
begin
LResponse := TStringStream.Create('');
try
Put(AURL, ASource, LResponse);
finally
result := LResponse.DataString;
LResponse.Free;
end;
end;
function TIdCustomHTTP.Get(AURL: string): string;
var
Stream: TMemoryStream;
begin
Stream := TMemoryStream.Create;
try
Get(AURL, Stream);
finally
if Stream.Size > 0 then // DO we have result?
begin
SetLength(result, Stream.Size);
Move(PChar(Stream.Memory)^, result[1], Stream.Size);
end;
Stream.Free;
end;
end;
function TIdCustomHTTP.Trace(AURL: string): string;
var
Stream: TStringStream;
begin
Stream := TStringStream.Create(''); try
Trace(AURL, Stream);
result := Stream.DataString;
finally Stream.Free; end;
end;
function TIdCustomHTTP.DoOnRedirect(var Location: string; var VMethod: TIdHTTPMethod; RedirectCount: integer): boolean;
begin
result := HandleRedirects;
if assigned(FOnRedirect) then
begin
FOnRedirect(self, Location, RedirectCount, result, VMethod);
end;
end;
procedure TIdCustomHTTP.SetCookies(AURL: TIdURI; ARequest: TIdHTTPRequest);
var
S: string;
begin
if Assigned(FCookieManager) then
begin
// Send secure cookies only if we have Secured connection
S := FCookieManager.GenerateCookieList(AURL, (IOHandler is TIdSSLIOHandlerSocket));
if Length(S) > 0 then
begin
ARequest.RawHeaders.Values['Cookie'] := S;
end;
end;
end;
// This function sets the Host and Port and returns a boolean depending on
// whether a PROXY is being used or not.
function TIdCustomHTTP.SetHostAndPort: TIdHTTPConnectionType;
begin
// First check to see if a Proxy has been specified.
if Length(ProxyParams.ProxyServer) > 0 then
begin
if ((not AnsiSameText(Host, ProxyParams.ProxyServer)) or
(Port <> ProxyParams.ProxyPort)) and (Connected) then
begin
Disconnect;
end;
FHost := ProxyParams.ProxyServer;
FPort := ProxyParams.ProxyPort;
if AnsiSameText(URL.Protocol, 'HTTPS') then
begin
Result := ctSSLProxy;
if Assigned(IOHandler) then
begin
if not (IOHandler is TIdSSLIOHandlerSocket) then
begin
raise EIdIOHandlerPropInvalid.Create(RSIOHandlerPropInvalid);
end else begin
(IOHandler as TIdSSLIOHandlerSocket).PassThrough := true;
end;
end;
end
else begin
Result := ctProxy;
if Assigned(IOHandler) and (IOHandler is TIdSSLIOHandlerSocket) then
begin
(IOHandler as TIdSSLIOHandlerSocket).PassThrough := true;
end;
end;
end
else begin
Result := ctNormal;
if ((not AnsiSameText(Host, URL.Host)) or (Port <> StrToInt(URL.Port))) then begin
if Connected then begin
Disconnect;
end;
Host := URL.Host;
Port := StrToInt(URL.Port);
end;
if AnsiSameText(URL.Protocol, 'HTTPS') then
begin
// Just check can we do SSL
if not Assigned(IOHandler) or (not (IOHandler is TIdSSLIOHandlerSocket)) then
raise EIdIOHandlerPropInvalid.Create(RSIOHandlerPropInvalid)
else begin
(IOHandler as TIdSSLIOHandlerSocket).PassThrough := false;
result := ctSSL;
end;
end
else
begin
if Assigned(IOHandler) then
begin
if (IOHandler is TIdSSLIOHandlerSocket) then
begin
(IOHandler as TIdSSLIOHandlerSocket).PassThrough := true;
end;
end;
end;
end;
end;
procedure TIdCustomHTTP.ReadResult(AResponse: TIdHTTPResponse);
var
Size: Integer;
function ChunkSize: integer;
var
j: Integer;
s: string;
begin
s := ReadLn;
j := AnsiPos(' ', s);
if j > 0 then
begin
s := Copy(s, 1, j - 1);
end;
Result := StrToIntDef('$' + s, 0);
end;
begin
if Assigned(AResponse.ContentStream) then // Only for Get and Post
begin
if AResponse.ContentLength > 0 then // If chunked then this is also 0
begin
try
ReadStream(AResponse.ContentStream, AResponse.ContentLength);
except
on E: EIdConnClosedGracefully do
end;
end
else
begin
if AnsiPos('chunked', AResponse.RawHeaders.Values['Transfer-Encoding']) > 0 then {do not localize}
begin // Chunked
DoStatus(hsStatusText, [RSHTTPChunkStarted]);
Size := ChunkSize;
while Size > 0 do
begin
ReadStream(AResponse.ContentStream, Size);
ReadLn; // blank line
Size := ChunkSize;
end;
ReadLn; // blank line
end
else begin
if not AResponse.HasContentLength then
ReadStream(AResponse.ContentStream, -1, True);
end;
end;
end;
end;
procedure TIdCustomHTTP.PrepareRequest(ARequest: TIdHTTPRequest);
var
LURI: TIdURI;
begin
LURI := TIdURI.Create(ARequest.URL);
if Length(LURI.Username) > 0 then
begin
ARequest.Username := LURI.Username;
ARequest.Password := LURI.Password;
end;
FURI.Username := ARequest.Username;
FURI.Password := ARequest.Password;
FURI.Path := ProcessPath(FURI.Path, LURI.Path);
FURI.Document := LURI.Document;
FURI.Params := LURI.Params;
if Length(LURI.Host) > 0 then begin
FURI.Host := LURI.Host;
end;
if Length(LURI.Protocol) > 0 then begin
FURI.Protocol := LURI.Protocol;
end else begin
FURI.Protocol := 'http';
end;
if Length(LURI.Port) > 0 then begin
FURI.Port := LURI.Port;
end
else begin
case StrToIntDef(FURI.Port, 0) of
0, IdPORT_HTTP, IdPORT_SSL: begin
if AnsiSameText(FURI.Protocol, 'http') then begin
FURI.Port := IntToStr(IdPORT_HTTP);
end else begin
if AnsiSameText(FURI.Protocol, 'https') then begin
FURI.Port := IntToStr(IdPORT_SSL);
end else begin
raise EIdUnknownProtocol.Create('');
end;
end;
end;
end;
end;
// The URL part is not URL encoded at this place
ARequest.URL := URL.Path + URL.Document + URL.Params;
if ARequest.Method = hmOptions then
begin
if AnsiSameText(LURI.Document, '*') then
begin
ARequest.URL := LURI.Document;
end;
end;
LURI.Free; // Free URI Object;
// Check for valid HTTP request methods
if ARequest.Method in [hmTrace, hmPut, hmOptions, hmDelete] then
begin
if ProtocolVersion <> pv1_1 then
begin
raise EIdException.Create('This request method is supported in HTTP 1.1');
end;
end;
if ARequest.Method in [hmPost, hmPut] then
begin
ARequest.ContentLength := ARequest.Source.Size;
end
else ARequest.ContentLength := -1;
if FURI.Port <> IntToStr(IdPORT_HTTP) then
ARequest.Host := FURI.Host + ':' + FURI.Port
else
ARequest.Host := FURI.Host;
end;
procedure TIdCustomHTTP.CheckAndConnect(AResponse: TIdHTTPResponse);
begin
if not AResponse.KeepAlive then begin
Disconnect;
end;
CheckForGracefulDisconnect(false);
if not Connected then try
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -