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.
gilberto_silvaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

emadatCommented:
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;
//************************************************************************
0
gilberto_silvaAuthor Commented:
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.
0
emadatCommented:
Ok.. here is what you need then:

//************************************************************************
function PostData(sRemoteFile, sHost: String; msData: TMemoryStream) : String;
var
     hSession,
     hOpenReq,
     hConnection     : HInternet;
     buf               : array[0..4095] of char;
     bufLen, dum     : DWORD;
     sHeader          : String;
begin
     result := '';
     dum := 0;
     hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); //INTERNET_FLAG_RAW_DATA
     try
          if hSession = nil then
               result := 'Error openning internet'
          else begin
               hConnection := InternetConnect(hSession, PChar(sHost), INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
               try
                    if hConnection = nil then
                         result := 'Error openning internet connection'
                    else begin
                         hOpenReq := HTTPOpenRequest(hConnection, 'POST', PChar(sRemoteFile), 'HTTP/1.1', nil, nil, INTERNET_FLAG_RELOAD, 0);
                         try
                              if hOpenReq = nil then
                                   result := 'Error openning internet request'
                              else begin
                                   sHeader := 'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*';
                                   HttpAddRequestHeaders(hOpenReq, PChar(sHeader), Length(sHeader), HTTP_ADDREQ_FLAG_ADD);
                                   sHeader := 'Accept-Language: en-us';
                                   HttpAddRequestHeaders(hOpenReq, PChar(sHeader), Length(sHeader), HTTP_ADDREQ_FLAG_ADD);
                                   sHeader := 'Content-Type: application/octet-stream';
                                   HttpAddRequestHeaders(hOpenReq, PChar(sHeader), Length(sHeader), HTTP_ADDREQ_FLAG_ADD);
                                   sHeader := 'Accept-Encoding: gzip, deflate';
                                   HttpAddRequestHeaders(hOpenReq, PChar(sHeader), Length(sHeader), HTTP_ADDREQ_FLAG_ADD);
                                   sHeader := 'Connection: Keep-Alive';
                                   HttpAddRequestHeaders(hOpenReq, PChar(sHeader), Length(sHeader), HTTP_ADDREQ_FLAG_ADD);
                                   sHeader := 'Cache-Control: no-cache';
                                   HttpAddRequestHeaders(hOpenReq, PChar(sHeader), Length(sHeader), HTTP_ADDREQ_FLAG_ADD);
                                   HTTPSendRequest(hOpenReq, nil, 0, msData.memory, msData.Size);
                                   bufLen := SizeOf(Buf);
                                   HTTPQueryInfo(hOpenReq, HTTP_QUERY_STATUS_TEXT, @buf, bufLen, dum);
                                   result := String(buf);
                              end;
                         finally
                              InternetCloseHandle(hOpenReq);
                         end;
                    end;
               finally
                    InternetCloseHandle(hConnection);
               end;
          end;
     finally
          InternetCloseHandle(hSession);
     end;
end;
//*****************************************************************************
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

emadatCommented:
Just modify the content type; and you are all set to go
0
gilberto_silvaAuthor Commented:
Ok, emadat, you deserve your points. It worked.

Gilberto Silva
0
gilberto_silvaAuthor Commented:
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
0
emadatCommented:
Not at all.
My pleasure
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.