我有一个以前员工创建的组件。它使用Indy(IDTCPClient)和以下方法来执行请求(其中“aReadHeader”是一个 在传入之前构建的预定义Uri。)
function TMyConnector.GET(aRawHeader: String): String;
begin
if Not Connected then Connected := True;
if Connected then
begin
FRawRequest := 'GET /'+ aRawHeader + ' HTTP/'+HTTPVerText+#13#10+
'Host: '+FHost+#13#10+
'Cookie: UserHPos=IOGLO00003000090000C000BS; '+
'LOSID=qsBiy/wEDCq6tOXFzGbOlTD1lmo5AXdFnCkbzzPn6+qCeheYVyTcumRrjsqh+Hds4Fr2gZDazfDzGN1RA+nnHuQQeBy78ZUgctrZyyy9MnGl2qI/ulkV6EPxAfmmLg/lopRq99f5gAcG/dgtytAJjS+aD5DqtHGrAqjiqgtkwuA=; '+
'LoginHPos=IOGLO00003000090000C000BS; '+
'UIHPos=IOGLO00003000020000500003; '+
'LOSG=61939308-7C83-47ED-B909-2D2D10AD7026; '+
'fControllingBusiness=IOGLO000030000900001000050000200001'+#13#10+
'Connection: Close'+#13#10+
#13#10;
FSock.Socket.Write(FRawRequest);
FRawResponse := FSock.Socket.ReadLn(#13#10#13#10,nil);
Result := FRawResponse;
if ResponseStream = nil then ResponseStream := TMemoryStream.Create
else ResponseStream.SetSize(0);
FSock.Socket.ReadStream(ResponseStream,-1,True);
if Connected and (Not KeepAlive) then Connected := False;
end;
end;
质疑FRawResponse返回
HTTP / 1.0 200 OK内容长度:5560日期:星期一,2013年11月18日15:05:07 GMT内容类型:text / html; charset = UTF-8 ...,public
如何将这个html内容从ResponseStream实际获取到HTML
目前存在的一种方法是“GenerateJSON”(参见下面的代码)。我想创建一个名为“GenerateHTML”的
Function StreamToArray(Strm:TStream):TArray<Byte>;
Begin
Strm.Position := 0;
SetLength(Result,Strm.Size);
Strm.Read(Result[0],Strm.Size);
End;
Procedure TMyConnector.GenerateJSON;
begin
if ResponseStream <> nil then
Begin
ResponseJSON_V := TJSONObject.ParseJSONValue(StreamToArray(ResponseStream),0) as TJSONValue; // Note ResponseJSON_V is declared as TJSONValue in TMyConnector);
End;
end;
所以,我需要
Procedure TMyConnector.GenerateHTML;
begin
if ResponseStream <> nil then
Begin
// result:= html from stream here
End;
end;
编辑:
Procedure TMyConnector.GenerateXML;
var
S: String;
begin
if ResponseStream <> nil then
Begin
try
while FSock.IOHandler.CheckForDataOnSource(30) do
begin
S := FSock.IOHandler.InputBufferAsString;
end;
finally
ResponseStr_v:= S;
end;
End;
end;
答案 0 :(得分:4)
以前的员工显然不知道Indy的TIdHTTP
组件的存在,或者Indy的ReadStream()
方法实际上是如何工作的,或者HTTP实际上是如何工作的。您应该重新编写函数以使用TIdHTTP
并让它为您处理所有细节,例如:
function TMyConnector.GET(aRawHeader: String): String;
begin
FHTTP.ProtocolVersion := ...; // pv1_0 or pv1_1
// Indy has a TIdCookieManager component that can be attached to
// the TIdHTTP.CookieManager property, which handles parsing,
// tracking, and sending back cookies for you for each HTTP
// request, so this should be re-written to utilize that
// functionality...
//
FHTTP.Request.CustomHeaders.Values['Cookie'] := 'UserHPos=IOGLO00003000090000C000BS; '+
'LOSID=qsBiy/wEDCq6tOXFzGbOlTD1lmo5AXdFnCkbzzPn6+qCeheYVyTcumRrjsqh+Hds4Fr2gZDazfDzGN1RA+nnHuQQeBy78ZUgctrZyyy9MnGl2qI/ulkV6EPxAfmmLg/lopRq99f5gAcG/dgtytAJjS+aD5DqtHGrAqjiqgtkwuA=; '+
'LoginHPos=IOGLO00003000090000C000BS; '+
'UIHPos=IOGLO00003000020000500003; '+
'LOSG=61939308-7C83-47ED-B909-2D2D10AD7026; '+
'fControllingBusiness=IOGLO000030000900001000050000200001';
FHTTP.Request.Connection := 'Close';
if ResponseStream = nil then
ResponseStream := TMemoryStream.Create
else
ResponseStream.Size := 0;
try
try
FHTTP.Get('http://' + FHost + '/' + aRawHeader, ResponseStream);
finally
FRawResponse := FHTTP.Response.RawHeaders.Text;
Result := FRawResponse;
end;
except
on E: EIdHTTPProtocolException do
begin
// HTTP error response. You can grab the error content if you need it...
WriteStringToStream(ResponseStream, E.ErrorMessage);
end;
on E: Exception do
begin
// some other error, handle as needed...
end;
end;
end;
如果无法重写以使用TIdHTTP
,则必须更新原始代码以实际实现基本的HTTP解析。仅仅调用ReadStream()
,你必须知道 WHEN 来调用它,并且 WHAT 参数传递给它是不够的。尝试更像这样的东西:
function TMyConnector.GET(aRawHeader: String): String;
var
Headers: TIdHeaderList;
Size: integer;
function InternalReadLn: String;
begin
Result := FSock.IOHandler.ReadLn;
if FSock.IOHandler.ReadLnTimedout then begin
raise EIdReadTimeout.Create('');
end;
end;
function ChunkSize: integer;
var
j: Integer;
s: string;
begin
s := InternalReadLn;
j := Pos(';', s); {do not localize}
if j > 0 then begin
s := Copy(s, 1, j - 1);
end;
Result := StrToInt('$' + Trim(s), 0);
end;
begin
if Not Connected then Connected := True;
if Connected then
begin
FRawRequest := 'GET /'+ aRawHeader + ' HTTP/'+HTTPVerText+#13#10+
'Host: '+FHost+#13#10+
'Cookie: UserHPos=IOGLO00003000090000C000BS; '+
'LOSID=qsBiy/wEDCq6tOXFzGbOlTD1lmo5AXdFnCkbzzPn6+qCeheYVyTcumRrjsqh+Hds4Fr2gZDazfDzGN1RA+nnHuQQeBy78ZUgctrZyyy9MnGl2qI/ulkV6EPxAfmmLg/lopRq99f5gAcG/dgtytAJjS+aD5DqtHGrAqjiqgtkwuA=; '+
'LoginHPos=IOGLO00003000090000C000BS; '+
'UIHPos=IOGLO00003000020000500003; '+
'LOSG=61939308-7C83-47ED-B909-2D2D10AD7026; '+
'fControllingBusiness=IOGLO000030000900001000050000200001'+#13#10+
'Connection: Close'+#13#10+
#13#10;
FSock.IOHandler.Write(FRawRequest);
FRawResponse := FSock.IOHandler.ReadLn(#13#10#13#10,nil);
Result := FRawResponse;
if ResponseStream = nil then ResponseStream := TMemoryStream.Create
else ResponseStream.Size := 0;
Headers := TIdHeaderList.Create(QuoteHTTP);
try
Headers.Text := FRawResponse;
if Pos('chunked', LowerCase(Headers.Values['Transfer-Encoding']) > 0 then
begin
Size := ChunkSize;
while Size <> 0 do begin
FSock.IOHandler.ReadStream(ResponseStream, Size);
InternalReadLn;
Size := ChunkSize;
end;
repeat until InternalReadLn = '';
end
else if Headers.IndexOfName('Content-Length') <> -1 then
begin
FSock.IOHandler.ReadStream(ResponseStream, StrToInt64(Headers.Values['Content-Length']), False);
end
else
FSock.IOHandler.ReadStream(ResponseStream, -1, True);
finally
Headers.Free;
end;
if Connected and (Not KeepAlive) then Connected := False;
end;
end;