如何使用WinInet API来发送一个HTTP POST请求在Delphi
题
我试图使用WinInet功能距离Delphi作出HTTP请求。
到目前为止,我有:
function request:string;
var
hNet,hURL,hRequest: HINTERNET;
begin
hNet := InternetOpen(PChar('User Agent'),INTERNET_OPEN_TYPE_PRECONFIG or INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(hNet) then
begin
try
hURL := InternetConnect(hNet,PChar('http://example.com'),INTERNET_DEFAULT_HTTP_PORT,nil,nil,INTERNET_SERVICE_HTTP,0,DWORD(0));
if(hURL<>nil) then
hRequest := HttpOpenRequest(hURL, 'POST', PChar('param=value'),'HTTP/1.0',PChar(''), nil, INTERNET_FLAG_RELOAD or INTERNET_FLAG_PRAGMA_NOCACHE,0);
if(hRequest<>nil) then
HttpSendRequest(hRequest, nil, 0, nil, 0);
InternetCloseHandle(hNet);
except
on E : Exception do
ShowMessage(E.ClassName+' error raised, with message : '+E.Message);
end;
end
end;
但是,这并不做任何事情(我嗅探网络的HTTP流量,看看它的工作原理)。 我已经成功地使用InternetOpenUrl中,但我也需要发送POST请求,该功能没有做到这一点。
有人能告诉我一个简单的例子吗?我想要的结果是获得HTTP响应页面在var当成字符串。
解决方案
我得到了所有的URL /文件名部分弄乱与前一代码。我使用这个从杰夫·德沃尔现在和它的正常工作:
function request(const AUrl, AData: AnsiString; blnSSL: Boolean = True): AnsiString;
var
aBuffer : Array[0..4096] of Char;
Header : TStringStream;
BufStream : TMemoryStream;
sMethod : AnsiString;
BytesRead : Cardinal;
pSession : HINTERNET;
pConnection : HINTERNET;
pRequest : HINTERNET;
parsedURL : TStringArray;
port : Integer;
flags : DWord;
begin
ParsedUrl := ParseUrl(AUrl);
Result := '';
pSession := InternetOpen(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(pSession) then
try
if blnSSL then
Port := INTERNET_DEFAULT_HTTPS_PORT
else
Port := INTERNET_DEFAULT_HTTP_PORT;
pConnection := InternetConnect(pSession, PChar(ParsedUrl[0]), port, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
if Assigned(pConnection) then
try
if (AData = '') then
sMethod := 'GET'
else
sMethod := 'POST';
if blnSSL then
flags := INTERNET_FLAG_SECURE or INTERNET_FLAG_KEEP_CONNECTION
else
flags := INTERNET_SERVICE_HTTP;
pRequest := HTTPOpenRequest(pConnection, PChar(sMethod), PChar(ParsedUrl[1]), nil, nil, nil, flags, 0);
if Assigned(pRequest) then
try
Header := TStringStream.Create('');
try
with Header do
begin
WriteString('Host: ' + ParsedUrl[0] + sLineBreak);
WriteString('User-Agent: Custom program 1.0'+SLineBreak);
WriteString('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'+SLineBreak);
WriteString('Accept-Language: en-us,en;q=0.5' + SLineBreak);
WriteString('Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7'+SLineBreak);
WriteString('Keep-Alive: 300'+ SLineBreak);
WriteString('Connection: keep-alive'+ SlineBreak+SLineBreak);
end;
HttpAddRequestHeaders(pRequest, PChar(Header.DataString), Length(Header.DataString), HTTP_ADDREQ_FLAG_ADD);
if HTTPSendRequest(pRequest, nil, 0, Pointer(AData), Length(AData)) then
begin
BufStream := TMemoryStream.Create;
try
while InternetReadFile(pRequest, @aBuffer, SizeOf(aBuffer), BytesRead) do
begin
if (BytesRead = 0) then Break;
BufStream.Write(aBuffer, BytesRead);
end;
aBuffer[0] := #0;
BufStream.Write(aBuffer, 1);
Result := PChar(BufStream.Memory);
finally
BufStream.Free;
end;
end;
finally
Header.Free;
end;
finally
InternetCloseHandle(pRequest);
end;
finally
InternetCloseHandle(pConnection);
end;
finally
InternetCloseHandle(pSession);
end;
end;
的parseURL的是,在“主机名/文件名”分裂的URL的功能和TStringArray是一个字符串数组。我还是要检查代码的明天,但它看起来很好,在我的嗅探器,我看到正在发送的POST数据和头。
其他提示
我个人更喜欢使用href="http://synapse.ararat.cz/doku.php/download" rel="nofollow noreferrer">突触库我所有的TCP / IP的
图书馆是写得很好,很容易修改,以满足您的特定需求。最新发布的颠覆作品,未经两个德尔福2009年和2010年德尔福任何问题,这个框架不基于组件,而是是一种很好的多线程环境的一系列类和过程。 uses
httpsend;
function testpost;
begin
stm := tStringstream.create('param=value');
try
HttpPostBinary('http://example.com',Stm);
finally
stm.free;
end;
end;
第三个参数(lpszObjectName)至 HttpOpenRequest
应该是 URL 的要申请。这就是为什么文档描述作为第五个参数(lpszReferer)“的指针指定从中获得在请求(lpszObjectName)的URL的文档的URL的空终止字符串”
在发布数据获取与 HttpSendRequest
发送;该lpOptional参数这样描述:
指向包含任何可选的数据的缓冲器被请求头之后立即发送。此参数一般用于POST和PUT操作。可选的数据可以是资源或信息被发送到服务器。该参数可以是NULL如果没有可选的数据要发送。
的第二个参数 InternetOpen
应刚服务器名称;它不应该包括协议。该协议你与第六参数指定。
你已经发送的请求后,可以读取 InternetReadFile
响应和 InternetQueryDataAvailable
。
不要只检查API函数是否回零,然后继续下一行。如果他们失败了,叫GetLastError
找出原因。你已经发布的代码不会产生异常,所以这是徒劳捕捉任何。 (它是愚蠢的“处理”他们你正在这样做无论如何方式。不要捕捉你已经不知道如何解决一个例外。让一切去到主叫方,或来电者的来电显示等。)