探索 ISAPI。处理 GET-POST 数据






4.67/5 (5投票s)
2002年7月14日
4分钟阅读

107105

2525
本文介绍了一种从表单中检索 GET-POST 数据到 ISAPI 扩展的方法。
引言
本文介绍了一种从 ISAPI 扩展中的表单检索 GET-POST 数据的方法。还提供了两个有用的参数集合类。由于非 MFC ISAPI 扩展在速度和同时连接数方面更可靠,因此包含了一个非 MFC 版本。
功能
MFC 和非 MFC 版本都使用基于 STL 的 Vector、Map 和 String 类,其中包含非 MFC 代码。在 MFC 版本中,string 集合基于 _bstr_t 类型。在非 MFC 版本中,string 集合基于 STL String 类型。因此,MFC 版本使用基于 ISAPI MFC 的宏来检索服务器变量和参数数据,而非 MFC 版本使用 WriteClient 和 ServerSupportFunction HTTP 函数。
默认方法会向浏览器写入一个复杂的表单,其中包含复选框、编辑框、单选按钮、文本区域——甚至还有文件类型的编辑框。其思想是将所有 POST 参数接收到同一个 DLL 扩展中。该表单使用 LoadLongResource 辅助函数从 HTML string 资源加载。这减少了构建页面的时间,因为 string 在扩展第一次调用时加载到内存中。在我的 《从 ISAPI 访问 ADO 数据》 文章中展示了如何在 Visual Studio 项目中使用 HTML string 资源。
GET 数据非常容易接收,因为这种数据是通过 URL 从浏览器发送到服务器的。POST 数据变量对用户是透明的,并且可以传输大量数据。有关 GET/POST 数据的更多信息,请参阅我的 《HTTP GET-POST 工具》 文章。
MFC 版本
用于存储数据集合中参数的 C++ 类是 Twin 和 TwinVector。ISAPI MFC 版本的 Default 方法将 IDR_HTML_FORM 资源写入客户端浏览器。FormRequest 是在单击“Submit Query”按钮后接收控制的方法。
void CPostDataExtension::FormRequest(CHttpServerContext* pCtxt,
void* pVoid, DWORD dwBytes)
{
//build the STL collection from server variables and POST data
TwinVector vecServerCtx(pCtxt, (LPTSTR)pVoid);
//write on browser stream the server context variables
WriteServerData(pCtxt);
//write on browser stream the STL collection of
//server context variables and POST data
WriteServerVar(pCtxt, vecServerCtx);
}
一个小问题是如何在 DLL 入口点获取控制到 FormRequest 方法。在 MFC 中,这非常容易实现,使用宏。
DEFAULT_PARSE_COMMAND(FormRequest, CPostDataExtension)
ON_PARSE_COMMAND(FormRequest, CPostDataExtension, ITS_RAW)
为了正确知道哪个方法将接收 POST 数据,MFC 包装器必须从 HTML 表单接收一个隐藏参数,该参数必须位于 FORM HTML 标签之后的第一位。
<form action="PostData.dll?" method=post>
<input TYPE=hidden NAME="MfcISAPICommand" VALUE="FormRequest">
在 WriteServerVar 辅助函数中,服务器上下文变量集合被写入 HTTP 流。可以直接获取所需参数的值:
bstrValue = vecServerCtx.Find(L"Filename").
for (itVec = vecServerCtx.begin(); itVec != vecServerCtx.end(); itVec++)
*pCtxt << <itvec->GetName() << " = " <<<itvec-> GetValue() << "br";
</itvec-></itvec->
在同一个 WriteServerVar 辅助函数中,POST 数据集合以这种方式写入 HTTP 流。
bstrToken = L"DATA";
index = vecServerCtx.Find(bstrToken);
if (index > -1)
{
map = vecServerCtx[index].GetValueAsMap();
if (!map.empty()) //we have values
for (itMap = map.begin(); itMap != map.end(); itMap++)
*pCtxt << (*itMap).first << " = "
<< (*itMap).second << "br";
}
可以直接获取所需参数的值:
*pCtxt << "Filename = " << map[L"Filename"] << "br".
TwinVector 类提供了 VARIANT GetVariant() 方法和 TwinVector(VARIANT varSafe) 构造函数,以便轻松地在 COM+ 组件之间通过网络传输集合。
非 MFC 版本
非 MFC 版本基于 MSDN 关于 ISAPI 扩展中 GET-POST 数据的文章。
C++ 扩展在 DWORD WINAPI HttpExtensionProc( LPEXTENSION_CONTROL_BLOCK pECB ) 方法中接收入口点。
在这里,它调用 CWriteFormExtension 类的 Run 方法——我们的 ISAPI 扩展中只有一个运行对象。
用于在数据集合中保存参数的 C++ 类是 MultipartParser 和 MultipartEntry。继承的 Map STL 类型的 cParser 变量接收整个 POST 数据集合。这是在 Initialize 方法中完成的。GetParam 是一个返回所需参数值的辅助方法。
String CWriteFormExtension::GetParam(MultipartParser& cParser, String sName)
{
String sValue; //the output string
MultipartEntry* pEntry = cParser[sName.c_str()];
if(pEntry != NULL) //we have data
{
sValue = (LPCTSTR) pEntry->Data(); //get value from collection
int nLen = sValue.size();
if(sValue[nLen - 1] == '\n' && sValue[nLen - 2] == '\r')
sValue = sValue.substr(0, nLen - 2);
}
return sValue;
}
这是 Run 方法的结果
LoadLongResource 私有函数与 MFC 版本相比略有修改。输入输出 str 字符串参数是 STL string 类型。在 szPath char 变量中,我们必须放入 DLL 文件的名称,以便加载正确的资源库。
BOOL CWriteLayoutExtension::LoadLongResource(String &str, UINT nID)
{
HRSRC hRes;
BOOL bResult = FALSE;
CHAR szPath[MAX_PATH];
strcpy(szPath, "WriteForm.dll");
HINSTANCE hInst = LoadLibrary(szPath);
//if you want standard html type
hRes = FindResource(hInst, MAKEINTRESOURCE(nID), RT_HTML);
if (hRes == NULL)
{
//trace error
str = "Error: Resource could not be found\r\n";
}
else
{
DWORD dwSize = SizeofResource(hInst, hRes);
if (dwSize == 0)
{
str.empty();
bResult = TRUE;
}
else
{
HGLOBAL hGlob = LoadResource(hInst, hRes);
if (hGlob != NULL)
{
LPVOID lpData = LockResource(hGlob);
if (lpData != NULL)
{
str = (LPCTSTR)lpData;
bResult = TRUE;
}
FreeResource(hGlob);
}
}
if (!bResult)
str = "Error: Resource could not be load\r\n";
}
return bResult;
}
历史
- 2002 年 7 月 16 日 - 更新了 MFC.zip 下载(缺少一个类)
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。