在 IIS 7 中运行 CGI 以使用 GET,而无需 POST 请求

在 IIS 7 中运行 CGI 以使用 GET,而无需 POST 请求

我正在尝试将一个旧的 CGI 应用程序从现有的 Windows 2003 服务器(IIS 6.0)迁移到运行良好的新 Windows 2008 服务器(IIS 7.0),但我们遇到了以下问题:

设置模块处理程序和所有内容后,我发现只有通过 POST 请求(从另一个页面提交表单)调用它时,我才能访问 CGI 应用程序(rdbweb.exe)文件。

如果我只是尝试输入文件的 URL(发出 GET 请求),我会收到以下错误:

HTTP 错误 502.2 - 错误网关

指定的 CGI 应用程序行为不当,未返回完整的 HTTP 标头集。它返回的标头是“模块 rdbweb.exe 中的异常 EInOutError,位于 00039B44。I/O 错误 6。”。

对于我们的一位客户来说,这是一个非常老的应用程序。当我们试图打电话给供应商时,他们说我们需要支付约 3000 美元的年度支持费才能开始讨论。当然,我尽量避免这种情况!

注意:

  • 如果我们创建一个提交给“rdbweb.exe”的普通 HTML 表单,CGI 就可以正常工作。但是我们不能用这种方法作为解决方法,因为应用程序中的某些页面链接到“rdbweb.exe”时使用的是普通链接,而不是表单提交。
  • 如果我们从控制台(命令提示符)窗口而不是 IIS 运行“rdbweb.exe”,我们会得到我们通常期望的正常 HTML,没有问题。

我们尝试了以下方法:

  • 确保在 IIS 中映射到“rdbweb.exe”的 CGI 模块启用了所有权限(读取、写入、执行),并且允许所有动词而不仅仅是特定的动词,还尝试明确允许 GET、POST。
  • 确保应用程序布尔值已将“启用 32 位应用程序”设置为 true。确保网站使用对“rdbweb.exe”文件和整个网站具有完全权限的帐户运行(尽管我们知道“读取”、“执行”应该足够了)。
  • 确保计算机范围的 IIS 设置“ISAPI 和 CGI​​ 限制”具有“rdbweb.exe”的完整路径。
  • 将模块从 CGI 更改为 Fast CGI,同样不起作用
  • 确保我们拥有最新的 Windows 更新(对于 IIS6,我们发现知识库文章指出需要针对 IIS6 进行修补的错误,但对于 IIS7 没有发现类似的错误)。

现在我们唯一能想到的可能性就是以下 Microsoft 知识库文章:http://support.microsoft.com/kb/145661- 内容如下:

CGI 错误:指定的 CGI 应用程序行为不当,未返回完整的 HTTP 标头集。它返回的标头如下:

文章提出了以下解决方案:

修改 CGI 应用程序标头输出的源代码。以下是正确标头的示例:

 print "HTTP/1.0 200 OK\n";  
 print "Content-Type: text/html\n\n\n";

不幸的是我们没有资源来尝试这一点,我也不确定我们是不是遇到了这个问题

您能帮我解决这个问题吗?有没有办法让应用程序在不需要 POST 请求的情况下工作?请注意,在旧的 IIS6 服务器上,该应用程序运行良好,我找不到任何特殊的 IIS 配置,我可能想在 IIS7 上尝试其等效配置。

答案1

简而言之:它可能是使用 D2007 最新更新(11.0.2902.10471)之前的 Delphi 版本编译的 Delphi CGI 应用程序。如果是这种情况,您需要源代码和 Delphi 安装并重新编译该应用程序。或者,您应该要求他们使用最新的 Delphi 版本重新编译该应用程序。

(从http://forums.iis.net/t/1100323.aspx?PageIndex=2

我们找到了导致我们的 CGI 在 IIS 7 上不响应的问题。实际上,我们将原因缩小到所有用 Delphi 编写的 CGI 应用程序(至少到 2005 版)基类中的一行代码。此行代码位于 TCGIApplication 的 Run 方法中,只是重置标准输入。在 IIS 6 及更早版本上,此行执行没有问题,但在 IIS 7 上会引发异常,导致 CGI 应用程序崩溃,因此无法响应请求。我们仍在调查注释掉此行的副作用,但这是我们目前的解决方案。通过删除此行,我们的 CGI 应用程序现在可以在 IIS 7 上正确执行。

原作者:史蒂文

答案2

我们有一个 Delphi 5 CGI 应用程序在 IIS 7 上遇到了同样的问题。我们的解决方案与 Steven 上面发布的解决方案类似,但是,我们并没有完全注释掉 marius 上面提到的行。当我这样做时,我发现任何 Request.ContentString 语句都会在应用程序中返回一个空字符串。我们的解决方案是实施建议的代码修复本文靠近底部。供您参考,以下是我们对 CGIApp.pas 副本进行更改后的代码片段。

procedure TCGIApplication.Run;
var
  HTTPRequest: TCGIRequest;
  HTTPResponse: TCGIResponse;
begin
  inherited Run;
  if IsConsole then
  begin
    Rewrite(Output);
    //Win 7/2008 IIS7
    //Reset(Input);
    {$i-} {!!IIS7}
    Reset(Input);
    if IOResult <>0 then ;
    {$i+}
  end;
  try
    HTTPRequest := NewRequest;
    try
      HTTPResponse := NewResponse(HTTPRequest);
      try
        HandleRequest(HTTPRequest, HTTPResponse);
      finally
        HTTPResponse.Free;
      end;
    finally
      HTTPRequest.Free;
    end;
  except
    HandleServerException(Exception(ExceptObject), FOutputFileName);
  end;
end;

答案3

CGI 供应商确认该应用程序与 IIS 7.0 不兼容,他们将在未来的版本中支持它。

我认为这表明唯一的解决方法是 Microsoft 知识库文章中提到的代码更改。

答案4

我遇到了这个问题(CGI GET 无法与 Delphi 生成的 CGI 一起使用),而且我还想将 CGI 的扩展名保留为 .cgi 而不是 .exe(这会让用户感到害怕!)。IIS 7.5 似乎不允许 CGI 使用除 .exe 或 .dll 之外的扩展名。

这里有一个涉及 PHP(!) 的超级巧妙的解决方案:

基本上,您将让 PHP 调用您的 CGI 并回显结果。

在您的 IIS 配置中,将 *.cgi 映射到 php,就像将 *.php 映射到 php 一样。不要直接调用 CGI,而是使用以下 PHP 代码调用 .cgi 文件:

<?php

putenv('QUERY_STRING=' . $_SERVER['QUERY_STRING']);
echo system('C:... path your cgi...//...delphicgi.exe');

?>

用您原来的 Delphi CGI 替换“C:... path your cgi...//...delphicgi.exe”。

就是这样!您的用户不会注意到任何差异。显然,通过 PHP 进行操作会对性能造成影响。但至少您不需要重建 CGI,而且可以使用 .cgi 扩展名!

相关内容