?
Solved

POST a form using wininet.dll

Posted on 2003-03-26
7
Medium Priority
?
4,140 Views
Last Modified: 2008-10-17
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.
0
Comment
Question by:gilberto_silva
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 3

Expert Comment

by:emadat
ID: 8210974
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
 

Author Comment

by:gilberto_silva
ID: 8211049
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
 
LVL 3

Accepted Solution

by:
emadat earned 1000 total points
ID: 8211180
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:emadat
ID: 8211191
Just modify the content type; and you are all set to go
0
 

Author Comment

by:gilberto_silva
ID: 8211833
Ok, emadat, you deserve your points. It worked.

Gilberto Silva
0
 

Author Comment

by:gilberto_silva
ID: 8211929
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
 
LVL 3

Expert Comment

by:emadat
ID: 8212280
Not at all.
My pleasure
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question