Starting from this lecture, we will enter the learning process of CGI programming. Through the previous lectures, you have mastered the basic knowledge of CGI programming. Now you can sit down and write your CGI program!
3. CGI Programming
1. Server-side attachment (SSI) and gateway
2. Gateway: connect other protocols through WEB
In the process of writing CGI programs, it is best to follow the following application design points:
(1) Ask a question--the problem you want to solve
(2) Design stage-conceive the basic framework and functions of the CGI program
(3) Encoding stage - realizing ideas with actions
(4) Program transplantation--write portable code
(5) Strive for excellence--bring the program to a higher level
1. Server-side attachment (SSI) and gateway
In this section we will introduce server side attachment SSI (Server Side Include) and gateway. Strictly speaking, SSI is not part of CGI programming, but SSI can accomplish some tasks that simple CGI programs can accomplish, and sometimes SSI is even the best choice. Therefore, a brief introduction is given here.
SSI defines a set of commands embedded in HTML text. Before the HTML text is sent to the HTTP client, the WEB server preprocesses these SSI commands and outputs the processed HTML text to the HTTP client's browser.
The command format of SSI is:
< !--# command parameter="value" -->
SSI commands are different from java or JavaScript in that they are processed on the server side rather than on the client side. This is similar to CGI programs. Of course, within the functional scope of SSI, its advantages are the same as those of CGI programs. It can improve the resource utilization of the server, and any WEB browser on the client can browse HTML text containing SSI.
The following are six commonly used SSI commands:
(1)Include command
(2) echo command
(3)exec command
(4)config command
(5) fsize command
(6) flashmod command
include command
The only supported parameter is file, which inserts the contents of the file specified by the file parameter into the current HTML text. If you know C language, you can see that it has the same function as the "#include" command in C language. For example, there are two HTML texts: main.html and header.html. Use the include command in main.html: main.html:
<html>
< tilte> Test Include SSI Command </ /title>
< !--#include file="header.html" -->
<body>
The above header comes from header.html!
< /body>
< /html>
header.html:
< H1> This is a title in header.html! < /H1>
(However, it seems that OmniHTTPD does not support the include command, :< !)
echo command
The only supported parameter is var, which is used to display server-provided variables, for example:
DOCUMENT_NAME: current file name
DOCUMENT_URL: Relative path to SSI text
DATE_LOCAL: local date
DATE_GMT: GMT (Creenwich Standard Time) date
LAST_MODIFIED: The last modified date of the file containing this SSI command
HTTP_USER_AGENT: Browser name.
For example: main.shtml <html>
This document was last updated on < !--#echo var="LAST_MODIFIED"-->
< /html>
When you open main.shtml with a browser you can see the last modified time. (It should be noted that main.shtml must be stored in the HtDocs directory of OmniHTTPD and accessed in the browser using the address http://localhost/main.shtml.)
exec command
The two parameters are cgi and cmd. The former calls an executable file, such as cgi="/cgi-bin/finger.cgi"; the latter calls a system command, such as cmd="ls". Unfortunately, OmniHTTPD does not support this SSI command (maybe the latest version does now).
config command
This command sets the way the server handles files and displays dates. It has two parameters:
(1) timefmt, determines the format for displaying dates. Use man strftime on UNIX to query available values.
(2) sizefmt, determines the format for displaying the file length. Value is bytes or addrev. This command is also not supported in OmniHTTPD.
fsize command
This command displays the size of a given file. The parameter is file, specifying the path and file name of the file.
flashmod command
This command displays the last modified date of the specified file. The parameter is file, specifying the path and file name of the file.
2. Gateway: connect other protocols through WEB
The HTTP protocol cannot access all resources on the Internet. When you want to access resources other than the HTTP protocol (such as POP3 and SMTP to send and receive emails), you need a gateway. A CGI program is a good way to implement a gateway.
Some commonly used gateways are provided in many UNIX HTTP servers, such as finger, wais, archie, etc. But in OmniHTTPD, these gateways are not provided. But we can add gateway functionality to OmniHTTPD by writing CGI programs.
Forms and their processing
HTML forms are part of WEB documents and are used to submit information filled in by users to the server. Usually, this information is passed to the CGI program, which performs a series of operations or data processing based on the input information, and then generates an HTML document representing the processing results and sends it back to the client's browser.
It can be seen that the key part of the CGI program is to obtain input data and generate HTML documents, while the operation and data processing parts are the same as most applications. In this lecture, I will introduce how to get data and output HTML documents in Perl and Delphi.
First, we create an HTML document named greeting.html:
greeting.html file (stored in the HtDocs directory of OmniHTTPD)
<html>
<head>
<title>This is a greeting page! </title>
< h1> Greeting </ /h1>
<body>
<hr>
< form action="/cgi-bin/greeting.pl" method=POST>
< p> Your First Name: < input type=text name="firstname" size=60 maxlength=80> < /p>
< p> Your Last Name: < input type=text name="lastname" size=60 maxlength=80> < /p>
<hr>
< p> < input type=submit value="All OK!"> < input type=reset value="Clear All"> </ /p>
< /form>
< /body>
< /html>
Here is the Perl CGI program greeting.pl:
greeting.pl file (stored in the cgi-bin directory of OmniHTTPD) # Greeting You!
require "cgi-lib.pl";
# ===================================
# get input values
&ReadParse(*input);
$mFirstName = $input{'firstname'};
$mLastName = $input{'lastname'};
# ===================================
# do some operations here
$mFullName = "$mFirstName $mLastName";
# ===================================
# create HTML document to output
PRint&PrintHeader;
print "< html>< head>< title> Greeting You! </ /title>< /head> ";
print "< body> Hello, < i>$mFullName< /i> ! ";
print "< hr> by Greeting.pl < /body>< /html>";
# ===================================
# All done!
Test the CGI program by browsing http://localhost/greeting.html.
In the above Perl program, as a CGI program, you must use require "cgi-lib.pl" to reference the cgi-lib.pl file. This file has many functions and procedures for CGI programming. require is equivalent to #include in C, but it should be noted that there must be a semicolon after the require statement.
The ReadParse process reads the data submitted by the HTML form, and the parameter is an array pointer. It should be noted that in Perl, function and procedure calls must be preceded by an & symbol.
mFirstName, mLastName, and mFullName are variables. In Perl, variable names must be preceded by a $ sign.
The actual return value of the PrintHeader function is "Content-type: text/html", which tells the browser that the following data is an HTML document.
Generating the HTML document is very simple, just use the print statement to output the content of the HTML document. How about it? Can you use Perl to write CGI programs?
Next, let's write a Delphi program to accomplish the same function:
First close all projects in Delphi, select the menu File/New, select the Web Server application type in the dialog box, and use the CGI Stand-alone excutable option. A new project will appear with the main window name WebModule1.
Double-click the mouse on the Actions property of WebModule1, and the Actions property editing window will appear. Create a new Action in the window, named WebActionItem1, set its Default property to True; and double-click the OnAction event in its Events, add the following code:
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
mFirstName, mLastName, mFullName: string;
HtmlDoc: string;
begin
// Get Input Values:
mFirstName := Request.ContentFields.Values['firstname'];
mLastName := Request.ContentFields.Values['lastname'];
// Do some operations here
mFullName := mFirstName + ' ' + mLastName;
// Create HTML document to output
HtmlDoc := '< html>< head>< title> Greeting You! </ /title>< /head>';
HtmlDoc := HtmlDoc + '< body> Hello, < i>' + mFullName + '< /i> !';
HtmlDoc := HtmlDoc + '< hr> by Greeting.cgi < /body>< /html>';
Response.Content := HtmlDoc;
end;
Save the unit of this project as cgimain.pas and the project as greeting.dpr. After compiling (using Ctrl+F9), copy greeting.exe to the cgi-bin directory of OmniHTTPD and rename it to greeting.cgi. At the same time, modify the greeting.html we wrote earlier as follows:
Change < form action="/cgi-bin/greeting.pl" method=POST> to
< form action="/cgi-bin/greeting.cgi" method=POST>
In this way, you can test CGI programs written in Delphi by browsing http://localhost/greeting.html.
As can be seen from this program, in Delphi, the OnAction event of WebActionItem occurs as soon as the CGI program gets a request. In this event, data input and HTML document generation are done like this:
Get the value of the form element through Request.ContentFields.Values[HTML form element name].
Generate HTML documents by assigning a value to Response.Content.
The following is the content of the three files of the Delphi program: ---------------------------------------- -------------------
greeting.dpr :
program greeting;
{$APPTYPE CONSOLE}
uses
HTTPApp,
CGIApp,
cgimain in 'cgimain.pas' {WebModule1: TWebModule};
{$E cgi}
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TWebModule1, WebModule1);
Application.Run;
end.
-------------------------------------------------- ----------
cgimain.pas:
unit cgimain;
interface
uses Windows, Messages, SysUtils, Classes, HTTPApp;
type
TWebModule1 = class(TWebModule)
procedure WebModule1WebActionItem1Action(Sender: TObject;Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
private
{Private declarations}
public
{Public declarations}
end;
var
WebModule1: TWebModule1;
implementation
{$R *.DFM}
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
mFirstName, mLastName, mFullName: string;
HtmlDoc: string;
begin
// Get Input Values:
mFirstName := Request.ContentFields.Values['firstname'];
mLastName := Request.ContentFields.Values['lastname'];
// Do some operations here
mFullName := mFirstName + ' ' + mLastName;
// Create HTML document to output
HtmlDoc := '< html>< head>< title> Greeting You! </ /title>< /head>';
HtmlDoc := HtmlDoc + '< body> Hello, < i>' + mFullName + '< /i> !';
HtmlDoc := HtmlDoc + '< hr> by Greeting.cgi < /body>< /html>';
Response.Content := HtmlDoc;
end;
end.
-------------------------------------------------- ----------
cgimain.dfm:
object WebModule1: TWebModule1
OldCreateOrder = False
Actions = <
item
Default=True
Name = 'WebActionItem1'
OnAction = WebModule1WebActionItem1Action
end>
Left = 192
Top = 107
Height = 150
Width = 215
end