BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Help with Function Conversion, Win32 -> CGI

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock
View previous topic :: View next topic  
Author Message
Bob
Guest





PostPosted: Sun Feb 29, 2004 5:00 am    Post subject: Help with Function Conversion, Win32 -> CGI Reply with quote



I'm a longtime Delphi (desktop) developer and now need to create my first
web server app. I've got to convert a very intense calculation function that
is in a unit of a desktop app, about 9,000 lines of code, into web server
app. The function doesn't access a database and I'm going for max
compatibility so I think my target app is CGI.

The app itself is real simple (even though its big). It has about 200
arguments which it pulls from INI files, if I can't work with INI's in CGI I
could take from an HTML file, load it into a TStringList and parse out my
args. Then I do a bunch of calcs... hopefully I can use Delphi's Math unit
in a CGI app? Then the app produces an HTML file. Currently the app builds
the HTML file in a TStringList then just uses StringList1.SaveToFile() with
an HTML extension. Thats it.

Here are a couple questions I have:
- How do I pass the name and location of the file containing the args,
like this:
www.myserver.com/calc.exe/?args=www.clientserver.com/calcargs.html
- if so how do I retrieve the the file name within the app... is there a
function that returns the URL used to call the app?
- How do I return the name and location of the file containing the results
back to the client?

Thanks in advance...

-Bob


Back to top
Ben Hochstrasser
Guest





PostPosted: Sun Feb 29, 2004 10:32 am    Post subject: Re: Help with Function Conversion, Win32 -> CGI Reply with quote



Bob wrote:

Quote:
Here are a couple questions I have:
- How do I pass the name and location of the file containing the
args,
like this:
www.myserver.com/calc.exe/?args=www.clientserver.com/calcargs.html

The environment variable "SCRIPT_NAME" contains the name of the .exe.
The environment variable "QUERY_STRING" contains "args=www.client......"

Quote:
- if so how do I retrieve the the file name within the app... is
there a
function that returns the URL used to call the app?

HTTP_HOST contains "www.myserver.com"; So the complete URI would be
%HTTP_HOST%%SCRIPT_NAME%?%QUERY_STRING%

Quote:
- How do I return the name and location of the file containing the
results
back to the client?

You simply write them to stdout:

writeln("Content-type: text/html");
writeln; // important - empty lines after the header
writeln(myStringList.Text);

cgi applications are console applications; below is a very very simple
example:


program cgitest;
{$APPTYPE CONSOLE}

uses Windows;

{$R *.RES}

function GetEnv(EnvString: String): String;
var
EnvVar: Array[0..255] of Char;
n: integer;
begin
n := GetEnvironmentVariable(PChar(EnvString), @EnvVar, SizeOf(EnvVar));
if n > 0 then
Result := Copy(EnvVar, 0, n)
else
Result := '(not set)';
end;

procedure PrintVar(Varname: string);
begin
writeln('<tr><td>',VarName,'</td><td>',GetEnv(VarName),'</td></tr>');
end;

begin
writeln('Content-type: text/html');
writeln;
writeln('<http><head><title>CGI Test</title></head>');
writeln('<body><h1>CGI Test</h1>');
writeln('<table border=1>');
writeln('<tr><th>Variable</th><th>Contents</th></tr>');
PrintVar('PATH_INFO');
PrintVar('PATH_TRANSLATED');
PrintVar('REMOTE_HOST');
PrintVar('REMOTE_ADDR');
PrintVar('GATEWAY_INTERFACE');
PrintVar('SCRIPT_NAME');
PrintVar('SCRIPT_FILENAME');
PrintVar('REQUEST_METHOD');
PrintVar('HTTP_ACCEPT');
PrintVar('HTTP_ACCEPT_CHARSET');
PrintVar('HTTP_ACCEPT_ENCODING');
PrintVar('HTTP_ACCEPT_LANGUAGE');
PrintVar('HTTP_FROM');
PrintVar('HTTP_HOST');
PrintVar('HTTP_REFERER');
PrintVar('HTTP_USER_AGENT');
PrintVar('QUERY_STRING');
PrintVar('SERVER_SOFTWARE');
PrintVar('SERVER_NAME');
PrintVar('SERVER_PROTOCOL');
PrintVar('SERVER_PORT');
PrintVar('CONTENT_TYPE');
PrintVar('CONTENT_LENGTH');
PrintVar('USER_NAME');
PrintVar('USER_PASSWORD');
PrintVar('AUTH_TYPE');
writeln('</table></body></html>');
end.


--
Ben

Back to top
Bob
Guest





PostPosted: Sun Feb 29, 2004 5:19 pm    Post subject: Re: Help with Function Conversion, Win32 -> CGI Reply with quote



Quote:
You simply write them to stdout:

writeln("Content-type: text/html");
writeln; // important - empty lines after the header
writeln(myStringList.Text);


So, if I have the headers (with empty lines after) in the string list I only
need to do
writeln(myStringList.Text); ?

How does the client know the CGI app is done? In your example you writing
writeln's until you end with
writeln('</table></body></html>');
Does this tell the client your done or does it not matter?

Thanks, -Bob



Back to top
Ben Hochstrasser
Guest





PostPosted: Sun Feb 29, 2004 7:29 pm    Post subject: Re: Help with Function Conversion, Win32 -> CGI Reply with quote

Bob wrote:

Quote:
So, if I have the headers (with empty lines after) in the string list
I only need to do
writeln(myStringList.Text); ?

Yes.

Quote:
How does the client know the CGI app is done? In your example you
writing writeln's until you end with
writeln('</table></body></html>');
Does this tell the client your done or does it not matter?

The client doesn't know - the server who is running your cgi via
CreateProcess() (or the unix equivalent) knows when the cgi ended. Then
it will [usually] close the connection. At which point the client has no
alternative (this is the case when you have eg "Content-type:
text/plain")
It is considered good practice, however, to put a
"Content-Length: 12345" in the cgi header, so the client has a vague idea
how much data will be coming. For the sake of simplicity I skipped that
one. So, to be complete, you'd have to say:

writeln('Content-type: text/html');
writeln('Content-length: ', Length(myStringList.Text));
writeln;
writeln(myStringList.Text);

Note that for static pages the http server supplies a suitable header. A
cgi must do that itself - the server will just execute the cgi and
redirect its output to the client.

I recommend you to bookmark http://www.htmlhelp.com/faq/cgifaq.html
unless you want to skim through a whole lot of RFCs.

There's only two or three things that are important:

- cgi applets are console applications as they employ stdin and stdout
- cgi applets gather information from the hosting server's environment
variables
- cgi applets better don't crash. Be sure to use try...except clauses so
that at least the header plus some error messages are generated.
- cgi applets better be small. If you expect a lot of concurrent users,
move stuff into a common dll. (Ideally the cgi.exe is only a stub which
parses the arguments and then calls the dll)

Oops, that's four things already ;-)

--
Ben

Back to top
Bob
Guest





PostPosted: Mon Mar 01, 2004 4:05 pm    Post subject: Re: Help with Function Conversion, Win32 -> CGI Reply with quote

Quote:
There's only two or three things that are important:

- cgi applets are console applications as they employ stdin and stdout
- cgi applets gather information from the hosting server's environment
variables
- cgi applets better don't crash. Be sure to use try...except clauses so
that at least the header plus some error messages are generated.
- cgi applets better be small. If you expect a lot of concurrent users,
move stuff into a common dll. (Ideally the cgi.exe is only a stub which
parses the arguments and then calls the dll)

Oops, that's four things already ;-)

--
Ben

(you got me on the 4th one)
What is too big? This is a really big calculation, maybe a 1MB compiled.
What kind of DLL do I create? Just a regular DLL or a ISAPI DLL?
Seems creating two processes would take longer, use more resources?
Thanks, -Bob



Back to top
Ben Hochstrasser
Guest





PostPosted: Mon Mar 01, 2004 4:37 pm    Post subject: Re: Help with Function Conversion, Win32 -> CGI Reply with quote

Bob wrote:

Quote:
(you got me on the 4th one)
What is too big? This is a really big calculation, maybe a 1MB
compiled.

well, if you have 20 concurrent uses you'd need 20..80 MB RAM (depends
how these applications behave memory-wise).

Quote:
What kind of DLL do I create? Just a regular DLL or a ISAPI DLL?

It would be just a standard DLL, because the cgi is a plain old console
application. ISAPI DLLs have the same use - load once, use multiple; but
they're loaded by the web server, not a cgi process (thus modifying an
ISAPI DLL [usually] means to stop the server, update the ISAPI DLL,
restart the server...)

Quote:
Seems creating two processes would take longer, use more resources?

Well, ideally the .cgi alone could be loaded off the disk cache. The dll
would have to be loaded only the first time and would remain in memory
until the last instance of your cgi unloaded it. (You may start a dummy
process just to ensure the dll remains loaed...)

So - go ahead and try w/o creating a dll. If your system load exceeds
some healthy maximum over extended periods of time consider splitting
off a dll.

--
Ben

Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Internet Winsock All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.