如何使用WinInet api在Delphi中发送HTTP POST请求
我试图使用WinInet函数从Delphi发出HTTP请求 到目前为止,我已经:如何使用WinInet api在Delphi中发送HTTP POST请求,delphi,http,post,request,wininet,Delphi,Http,Post,Request,Wininet,我试图使用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) th
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;
函数请求:字符串;
变量
hNet,hURL,hRequest:HINTERNET;
开始
hNet:=互联网开放(PChar(“用户代理”)、互联网开放类型预配置或互联网开放类型预配置,无,无,0);
如果已分配(hNet),则
开始
尝试
hURL:=互联网连接(hNet、PChar)http://example.com'),INTERNET_默认_HTTP_端口,nil,nil,INTERNET_服务_HTTP,0,DWORD(0));
如果(零)那么
hRequest:=HttpOpenRequest(hURL,'POST',PChar('param=value'),'HTTP/1.0',PChar(''),nil,INTERNET标志重新加载或INTERNET标志重新加载,0);
如果(hRequestnil)那么
HttpSendRequest(hRequest,nil,0,nil,0);
InternetCloseHandle(hNet);
除了
关于E:Exception-do
ShowMessage(E.ClassName+'引发错误,消息为:'+E.message);
结束;
结束
结束;
但这没有任何作用(我正在嗅探网络http流量,看看它是否有效)。
我已经成功地使用了InternetOpenURL,但我还需要发送POST请求,而该函数不能做到这一点
有人能给我举个简单的例子吗?我希望得到的结果是以字符串形式获取var中的http响应页面。第三个参数(lpszObjectName)应该是您希望请求的URL。这就是为什么文档将第五个参数(lpszReferer)描述为“指向以null结尾的字符串的指针,该字符串指定从中获取请求(lpszObjectName)中URL的文档的URL。”
已发布的数据与一起发送;lpOptional参数描述如下:
指向缓冲区的指针,该缓冲区包含在请求头之后立即发送的任何可选数据。此参数通常用于POST和PUT操作。可选数据可以是发布到服务器的资源或信息。如果没有要发送的可选数据,则此参数可以为NULL
第二个参数应该只是服务器名称;它不应该包括协议。使用第六个参数指定的协议
发送请求后,可以使用和读取响应
不要只检查API函数是否返回零,然后继续下一行。如果失败,请调用
GetLastError
查找原因。您发布的代码不会引发异常,因此捕获任何异常都是徒劳的。(不管怎么说,以这种方式“处理”它们是愚蠢的。不要捕获一个你还不知道如何修复的异常。让其他一切都由调用方或调用方的调用方决定,等等。)我把前面的代码中的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是一个字符串数组。明天我还需要检查代码,但看起来不错,在我的嗅探器中,我看到了发送的帖子数据和标题。就我个人而言,我更喜欢使用库来完成所有TCP/IP工作。例如,一个简单的HTTP post可以编码为:
uses
httpsend;
function testpost;
begin
stm := tStringstream.create('param=value');
try
HttpPostBinary('http://example.com',Stm);
finally
stm.free;
end;
end;
该库编写得很好,很容易修改以满足您的特定需求。最新的subversion版本对Delphi2009和Delphi2010都没有任何问题。这个框架不是基于组件的,而是一系列类和过程,它们在多线程环境中运行良好 我为您找到了代码的源代码,因此您可以引用原始作者。我更改了代码,删除了构思不周的布尔case语句,并更改了referer,这样它就不会说谎并声称是Firefox 3.0.10。我找不到哪个单元包含ParseURL,或者它可能是一个自定义例程。:处的代码有些不同,并且没有使用ParseURL。如何向post请求添加自定义头值?