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_PRECONF IG, 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-url encoded
</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-url encoded';
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_PRECONF IG, nil, nil, 0);
if sessao = nil then
begin
// error handling ...
halt;
end;
InternetSetOption (sessao, INTERNET_OPTION_CONNECT_TI MEOUT, @url_delay, sizeof (dword));
InternetSetOption (sessao, INTERNET_OPTION_RECEIVE_TI MEOUT, @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.
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_PRECONF
<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-url
</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">...
<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)
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-url
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_PRECONF
if sessao = nil then
begin
// error handling ...
halt;
end;
InternetSetOption (sessao, INTERNET_OPTION_CONNECT_TI
InternetSetOption (sessao, INTERNET_OPTION_RECEIVE_TI
conexao := internetconnect (sessao, @url_origem, INTERNET_DEFAULT_HTTP_PORT
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='
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.
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Just modify the content type; and you are all set to go
ASKER
Ok, emadat, you deserve your points. It worked.
Gilberto Silva
Gilberto Silva
ASKER
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
Gilberto Silva
Not at all.
My pleasure
My pleasure
//************************
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(sAppNam
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(hSessi
end;
end;
//************************