且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用WinInet api在Delphi中发送HTTP POST请求

更新时间:2022-11-27 21:38:09

我得到了所有的url / filename部分搞砸了以前的代码。我现在正在使用来自Jeff DeVore ,并且正常工作:

 函数请求(const AUrl,AData:AnsiString; blnSSL:Boolean = True):AnsiString; 
var
aBuffer:Char [0..4096]的Char;
标题:TStringStream;
BufStream:TMemoryStream;
sMethod:AnsiString;
BytesRead:Cardinal;
pSession:HINTERNET;
pConnection:HINTERNET;
pRequest:HINTERNET;
parsedURL:TStringArray;
port:整数;
标志:DWord;
begin
ParsedUrl:= ParseUrl(AUrl);

结果:='';

pSession:= InternetOpen(nil,INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);

如果分配(pSession)然后
尝试
如果blnSSL然后
端口:= INTERNET_DEFAULT_HTTPS_PORT
else
端口:= INTERNET_DEFAULT_HTTP_PORT;
pConnection:= InternetConnect(pSession,PChar(ParsedUrl [0]),port,nil,nil,INTERNET_SERVICE_HTTP,0,0);

如果分配(pConnection)然后
尝试
如果(AData ='')然后
sMethod:='GET'
else
sMethod:='POST';

如果blnSSL然后
标志:= INTERNET_FLAG_SECURE或INTERNET_FLAG_KEEP_CONNECTION
else
标志:= INTERNET_SERVICE_HTTP;

pRequest:= HTTPOpenRequest(pConnection,PChar(sMethod),PChar(ParsedUrl [1]),nil,nil,nil,flags,0);

如果分配(pRequest)然后
尝试
标题:= TStringStream.Create('');
尝试
与标题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);
结束

HttpAddRequestHeaders(pRequest,PChar(Header.DataString),Length(Header.DataString),HTTP_ADDREQ_FLAG_ADD);

如果HTTPSendRequest(pRequest,nil,0,指针(AData),长度(AData))则
begin
BufStream:= TMemoryStream.Create;
尝试
而InternetReadFile(pRequest,@aBuffer,SizeOf(aBuffer),BytesRead)do
begin
if(BytesRead = 0)then Break;
BufStream.Write(aBuffer,BytesRead);
结束

aBuffer [0]:=#0;
BufStream.Write(aBuffer,1);
结果:= PChar(BufStream.Memory);
finally
BufStream.Free;
结束
结束
finally
Header.Free;
结束
finally
InternetCloseHandle(pRequest);
结束
finally
InternetCloseHandle(pConnection);
结束
finally
InternetCloseHandle(pSession);
结束
结束

ParseUrl是一个在主机名/文件名中分割URL的功能,而TStringArray是字符串数组。我还需要检查明天的代码,但看起来不错,在我的嗅探器中,我看到发送的数据和头信息。


I am trying to make HTTP Requests from Delphi using the WinInet functions.

So far I have:

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;

But this doesn't do anything (I am sniffing network http traffic to see if it works). I have successfully used InternetOpenURL but I also need to send POST request and that function doesn't do that.

Could someone show me a simple example? The result I want is to get the http response page in a var as string.

I got all the url/filename part messed up with the previous code. I'm using this from Jeff DeVore now and it's working fine:

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 is a function that splits a URL in "hostname / filename" and TStringArray is an array of strings. I still have to review the code tomorrow but it looks fine and in my sniffer I saw the post data and headers being sent.