📄 delphi&internet1.txt
字号:
ECB.lpszLogData := 'Delphi DLL Log';
ECB.dwHTTPStatusCode := 200;
ResStr := SetUpResString;
S := PChar(ECB.lpbData);
ResStr := Format(ResStr, [S]);
StrLen := Length(ResStr);
ECB.WriteClient(ECB.ConnID, Pointer(ResStr), StrLen, 0);
Result := HSE_STATUS_SUCCESS;
end;
假设您已经有了附有下面代码的HTML窗体:
<FORM ACTION="/scripts/mystuff/isapi2.dll" METHOD="POST"
ENCTYPE="application/x-www-form-urlencoded">
<P>
Enter Number to Square: <INPUT NAME="GetSquare" VALUE=""
MAXLENGTH="25" SIZE=25>
<P>
<INPUT TYPE=SUBMIT VALUE="Submit" NAME="GetSquare">
</FORM>
这段代码会产生一个包含一个供您输入数字的文本区和一个叫做“submit”按钮的窗体,按钮的名字叫做“GetSquare”。如果有了这个窗体,接着您可以预计上面的两段程序会返回如下的字符串,假设用户在窗体中的文本区输入了数字23:
lpbData = GetSquare=23&GetSquare=Submit
为了理解这时究竟发生了什么,注意一下从上面函数中摘录HTML语句中的主体部分,这部分语句驻留在服务器上,反映如下:
'<BODY>lpbData = %s </BODY>' +
如果您研究过上面 HttpExtensionProc 函数中的代码,您会发现就在这句之前,它使用了 Format 语句中的 %s 参数来代替了 ECB.lpbData 中的值。(如果您不清楚语句 Format 是怎样工作的,请参阅有关的 Delphi 文档)[注:在作者所著的 Delphi2 编程大全(Delphi2 Unleashed)中的第三章《字符串与文本文件》中有详细说明(译者)]
假设上面所示的窗体中,当用户按下“确认”按钮时,lpbData 传递给
ISAPI DLL的值是:
GetSquare=23&GetSquare=Submit
为了让您有清晰的概念,让我重复一下上面两个语句传回给浏览器的信息是下面的字符串,您已经看过了:
lpbData = GetSquare=23&GetSquare=Submit
观看这个过程的最好办法试运行下面列出的 ISAPI2 程序。 ISAPI2 和
ISAPI1 差不多,但他包含了上面显示的新的 HttpExtensionProc 函数,并且它还包含了 SetUpResString 这个实用函数。
library Isapi2;
uses
Windows, SysUtils, HTTPExt;
function GetExtensionVersion( var Ver: THSE_VERSION_INFO ):
BOOL; stdcall;
begin
Ver.dwExtensionVersion := $00010000; // 1.0 support
Ver.lpszExtensionDesc := 'DLL written in Delphi 2.0';
Result := True;
end;
function SetUpResString: string;
begin
Result := '<HTML>' +
'<TITLE>Test server result</TITLE>' +
'<H1>Test server results</H1>' +
'<BODY>lpbData = %s </BODY>' +
'</HTML>';
end;
function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ):
DWORD; stdcall;
var
ResStr: string;
StrLen: Integer;
S, S1: string;
Len: Integer;
begin
ECB.lpszLogData := 'Delphi DLL Log';
ECB.dwHTTPStatusCode := 200;
ResStr := SetUpResString;
S := PChar(ECB.lpbData);
ResStr := Format(ResStr, [S]);
StrLen := Length(ResStr);
ECB.WriteClient(ECB.ConnID, Pointer(ResStr), StrLen, 0);
Result := HSE_STATUS_SUCCESS;
end;
exports
GetExtensionVersion,
HttpExtensionProc;
begin
end.
一旦您从窗体中获得了由 lpbData 变量传来的信息,您就能分析这些信息或者把它们返回给用户。比如说,您可以从上面例子中把数字23抽出来,做平方后返回用户。通过这样做可以使您从用户中获得信息,在这里是数字,对数字进行一些数学运算,最后把结果返回给用户。这意味着您可以在电波中创建互动的网页,这可是现在因特网编程中最流行的哦!
以下是一个通过网络提交数字平方给浏览器的完整的程序代码:
library Isapi3;
{ This code shows how to take input from the user via a browser,
parse that information, and then return an answer to the user.
In particular, the user submits a number, this code squares it,
and then sends the result back to user.
Here is the form from the browser that submits the information
for parsing:
<FORM ACTION="/scripts/mystuff/isapi2.dll" METHOD="POST"
ENCTYPE="application/x-www-form-urlencoded">
<P>
Enter Number to Square: <INPUT NAME="GetSquare" VALUE=""
MAXLENGTH="25" SIZE=25>
<P>
<INPUT TYPE=SUBMIT VALUE="Submit" NAME="GetSquare">
</FORM>
}
uses
Windows, SysUtils, HTTPExt,
StrBox;
function GetExtensionVersion( var Ver: THSE_VERSION_INFO ):
BOOL; stdcall;
begin
Ver.dwExtensionVersion := $00010000; // version 1.0 support
Ver.lpszExtensionDesc := 'ISAPI3.DLL';
Result := True;
end;
// Parse lpbData and retrieve the number the user passed to us.
function ParseData(S: string): Integer;
begin
S := StripLastToken(S, '&');
S := StripFirstToken(S, '=');
Result := StrToInt(S);
end;
function SetUpResString: string;
begin
Result := '<HTML>' +
'<TITLE>Test server result</TITLE>' +
'<H1>Test server results</H1>' +
'<BODY>Answer = %d </BODY>' +
'</HTML>';
end;
function HttpExtensionProc( var ECB: TEXTENSION_CONTROL_BLOCK ):
DWORD; stdcall;
var
ResStr: string;
StrLen: Integer;
S, S1: string;
Num: Integer;
begin
ECB.lpszLogData := 'Delphi DLL Log';
ECB.dwHTTPStatusCode := 200;
ResStr := SetUpResString;
S := PChar(ECB.lpbData);
Num := ParseData(S);
Num := Sqr(Num);
ResStr := Format(ResStr, [Num]);
StrLen := Length(ResStr);
ECB.WriteClient(ECB.ConnID, Pointer(ResStr), StrLen, 0);
Result := HSE_STATUS_SUCCESS;
end;
exports
GetExtensionVersion,
HttpExtensionProc;
begin
end.
这段代码从按下确认按钮的用户那里接受下面的字符串,用户要求平方后的数字:
GetSquare=5&GetSquare=Submit
假设这样输入,这段代码会通过因特网返回用户下面的字符串:
Answer = 25
一句话,用户输入数字5,你返回用户数字25。如果用户提交数字10,那么您返回数字100。这看起来微不足道,但在这里重要的是因特网上发生的行为[注:指互动网页(译者)]
分析用户传来的函数像这样:
// Parse lpbData and retrieve the number the user passed to us.
function ParseData(S: string): Integer;
begin
S := StripLastToken(S, '&');
S := StripFirstToken(S, '=');
Result := StrToInt(S);
end;
这两个语句在单元中,在本文开头提到过,也包含在我的站点上。[注:这个文件在网络上几乎到处可见,您也可以向译者索取(译者)][
在本篇文章中,关于ISAPI我只想谈这么多了。这些内容对于启发您利用这项优越的技术并获得乐趣来说应该是够用的了。接下来我要谈一下 GetServerVariable 、ReadClient 这两个语句,在这方面我只进行了极其有限的试验。在本文中,我附加了 HTTPEXT.PAS 文件,因为除了这分关键文档,在其他地方您不会找到它。
GetServerVariable 和 ReadClient 语句
正如您的CGI应用程序中的请求信息一样,您可以使用语句来从服务器上获得信息。下面是呼叫这个语句的例子:
Len := HseMaxExtDllNameLen;
SetLength(S1, Len);
Dec(Len);
ECB.GetServerVariable(ECB.ConnID,
'CONTENT_LENGTH',
PChar(S1),
Len);
首先,这段代码设定了保留从服务器上取得的信息的缓冲区的长度。接着它呼叫服务器并发出请求,在本例中,它要求获得服务器传来的信息的"CONTENT_LENGTH"。
微软公司的文献告诉我们,您可以通过 GetServerVariable 的第二个参数来传递跟着的字符串:
AUTH_TYPE 它包含了使用授权的类型。比如,如果使用的是基本(basic)授权,那么字符串就是"basic";如果是 NT challenge 回应,字符串就是"NTLM"。其他的授权属尤其对应的字符串。因为不断有新的授权类型被增添到服务器上,列出所有可能的字符串是不可行的。如果字符串为空,那么并没有使用任何授权。
CONTENT_LENGTH 脚本预计从客户端回收到的字节数。
CONTENT_TYPE 由请求布告的主体部分提供的信息的内容类型。[注:小弟才疏学浅,a POST request 暂译作"请求布告",望方家指正(译者)]
PATH_INFO 附加的路由信息,由客户机提供。它包含了跟在脚本名字之后的URL的漫游路由。如果有的话,它在请求字符串的前面。
PATH_TRANSLATED 它是 PATH_INFO 的值,但包含了扩充到一个路径标志的所有虚拟路由的名字。
QUERY_STRING 跟在参考这个脚本的URL中的"?"后面的信息。
REMOTE_ADDR 发出请求的客户机或其代理商(例如,网关或防火墙)的IP地址。
REMOTE_HOST 发出请求的客户机或其代理商(例如,网关或防火墙)的主机名。
REMOTE_USER 它包含了由客户机提供并且由服务器授权的用户名。如果返回空串那么用户使你名的(但是经过授权)。
UNMAPPED_REMOTE_USER 它是有如下特征的用户的名称:该用户向NT用户帐目发出请求(这是他以身份出现),在此之前ISAPI应用程序过滤起映射了该用户。
REQUEST_METHOD 是 HTTP 请求方法。
SCRIPT_NAME 执行的脚本程序名称。
SERVER_NAME 当它以自参考URLs形式出现时的主机名或IP地址。
SERVER_PORT 接受请求的TCP/IP的端口。
SERVER_PORT_SECURE 一个非0即1的字符串。当请求由安全端口处理时,它是1;否则是0。
SERVER_PROTOCOL 接受与这个请求相关的协议的信息的名称和版本。他通常是 HTTP/1.0 。
SERVER_SOFTWARE 是ISAPI应用DLL程序运行时所在的网页服务器的名称和版本。
ALL_HTTP 先前的变量并没有分析全部的HTTP字段头。这些变量从HTTP_<字段头名>中得出。字段头(由行标分离)包含了各自的字符串,这些字符串并不会终止。
HTTP_ACCEPT HTTP字段头的特例。接受的值是:字段由逗号(,)分离。例如:如果下面的几行是HTTP头的一部分:
接受:*/*,q=0.1
则URL(2.0新版本的特性)给出它的基础部分。
要注意的是,上面给出的信息片是由 TExtensionControlBlock 纪录自动传递的。因此您不需要调用GetServerVariable。不过,如果您确有需要,特别是您要从 ReadClient 中获得信息和需要知道要读入多少信息时,您可以调用它。
在很多时候,您不需要调用 ReadClient 。但是,您浏览器发出的信息量大于48KB的时候,您需要调用 ReadClient 来获取其余的信息。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -