Link to home
Start Free TrialLog in
Avatar of gilberto_silva
gilberto_silva

asked on

POST a form using wininet.dll

How to submit a POST with Delphi and wininet.dll?

I believe I followed the recipe (from MSDN) very strictly, but indeed I did something wrong, because my code doesn't work. The input fields are correct, the host and object addresses are correct, no error is returned from any wininet routine, but the answer doesn't come. When I try the post through a proxy (a SQUID proxy) using INTERNET_OPEN_TYPE_PRECONFIG, it complains with a vague "Invalid Request". HTML returned follows.

<HTML><HEAD>
<TITLE>ERROR: The requested URL could not be retrieved</TITLE>
</HEAD><BODY>
<H1>ERROR</H1>
<H2>The requested URL could not be retrieved</H2>
<HR>
<P>
While trying to process the request:
<PRE>
POST http://10.0.65.31/susfone/listaserv.asp HTTP/1.1
Accept: , ,
Content-Type: application/x-www-form-urlencoded
</PRE>
<P>
The following error was encountered:
<UL>
<LI>
<STRONG>
Invalid Request
</STRONG>
</UL>

<P>
Some aspect of the HTTP Request is invalid.  Possible problems:
<UL>
<LI>Missing or unknown request method
<LI>Missing URL
<LI>Missing HTTP Identifier (HTTP/1.0)
<LI>Request is too large
<LI>Content-Length missing for POST or PUT requests
<LI>Illegal character in hostname; underscores are not allowed
</UL>
<P>Your cache administrator is <A HREF="...(edited)...r">...</A>.

<br clear="all">
<hr noshade size=1>
Generated Wed, 26 Mar 2003 14:15:53 GMT by ...edited...MyCompany.com (Squid/2.4.STABLE6)
</BODY></HTML>

When I don't use the proxy (with INTERNET_OPEN_TYPE_DIRECT), the outcome is a timeout. With a browser (IE6), both with or without a proxy, the post works fine.

So, any suggestion?

My code is below.

Gilberto Silva

program poster0;
{$APPTYPE CONSOLE}
uses
  SysUtils,
  WinINet,
  Windows,
  supmon in 'supmon.pas';

const
    url_objeto = 'susfone/listaserv.asp';
    url_verbo  = 'POST';
    url_origem:  array [0..99] of char = '10.0.65.31';
    url_accept:  array [0..99] of char = 'Accept: */*';
    url_cttype:  array [0..99] of char = 'Content-Type: application/x-www-form-urlencoded';
    url_delay: dword = 10000;

var
    i: integer;
    nread: dword;
    sessao, conexao, pedido: hinternet;
    parnome, resnome, renavam, retorno: string;
    parfile: textfile;
    buffer: array [0..1023] of char;
    renavdata: array [0..99] of char;
begin
// initialization, file open, etc ...
sessao := internetopen ('MyAgent', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if sessao = nil then
    begin
    // error handling ...
    halt;
    end;
InternetSetOption (sessao, INTERNET_OPTION_CONNECT_TIMEOUT, @url_delay,  sizeof (dword));
InternetSetOption (sessao, INTERNET_OPTION_RECEIVE_TIMEOUT, @url_delay,  sizeof (dword));
conexao := internetconnect (sessao, @url_origem, INTERNET_DEFAULT_HTTP_PORT, nil, nil,
                                                                       INTERNET_SERVICE_HTTP, 0, 1);
if conexao = nil then ...
pedido := httpopenrequest (conexao, url_verbo, url_objeto, nil, nil, @url_accept, 0, 1);
if pedido = nil then ...
readln (parfile, renavam);
renavam := 'radfiltro=Sim&txtFiltro=' + renavam;
for i := 1 to length (renavam) do
    renavdata [i -1] := renavam [i];
renavdata [length (renavam)] := #0;
if httpsendrequest (pedido, @url_cttype, sizeof (url_cttype), @renavdata, sizeof (renavdata)) then
    begin
    retorno := '';
    repeat
        buffer := #0;
        if internetreadfile (pedido, @buffer, sizeof (buffer), nread) then
            if nread > 0 then
                retorno := retorno + buffer;
    until nread = 0;
    writeln (retorno);
    end
else
    writeln ('#GetLastError = ', getlasterror);
writeln;
internetclosehandle (pedido);
internetclosehandle (conexao);
internetclosehandle (sessao);
end.
Avatar of emadat
emadat
Flag of United States of America image

Use this function:

//************************************************************************
function PostHTML(strURL: String): String;
const BufferSize = 1024;
var
     hSession, hURL: HInternet;
     Buffer: array[1..BufferSize] of Byte;
     BufferLen: DWORD;
     sResult: string;
     mStrm: TMemoryStream;
begin
     Result := '';
     hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
     if hSession<>nil then try
          hURL := InternetOpenURL(hSession, PChar(strURL), nil, 0, 0, 0);
          if hURL<>nil then try
               sResult := '';
               mStrm := TMemoryStream.Create;
               try
                    repeat
                         InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
                         if BufferLen>0 then mStrm.WriteBuffer(Buffer, BufferLen);
                    until BufferLen = 0;
                    SetLength(sResult, mStrm.Size);
                    CopyMemory(@sResult[1], mStrm.memory, mStrm.Size);
               finally
                    mStrm.Free;
               end;
               Result := sResult;
          finally
               InternetCloseHandle(hURL);
          end
     finally
          InternetCloseHandle(hSession);
     end;
end;
//************************************************************************
Avatar of gilberto_silva
gilberto_silva

ASKER

Sorry, emadat, but my concern isn't on how to retrieve the contents of a URL, but instead on how to submit a POST to an Active Server Page.
ASKER CERTIFIED SOLUTION
Avatar of emadat
emadat
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Just modify the content type; and you are all set to go
Ok, emadat, you deserve your points. It worked.

Gilberto Silva
Maybe the only - and crucial - difference from my code was the use of a tMemoryStrem instead of an array of char. Anyway, sometimes a little point makes all the difference. Thank you, emadat!

Gilberto Silva
Not at all.
My pleasure