0

我已经在 html 的 cgi 文件中编写了这段代码,但它在 xampp 服务器中显示内部服务器错误。当我在命令行中编译它时,它只是显示“无调试”作为结果。我做错了什么?该代码在没有包含 css 部分的情况下工作正常,但是一旦我添加了链接部分,它就会停止工作。

 #!"c:\xampp\perl\bin\perl.exe"
use strict;
use warnings;
use CGI qw(:all); 
use CGI::Carp qw(fatalsToBrowser);
#use CGI ('div');
use CGI qw/Link/;

my $q = new CGI;

print $q->header,

$q->start_html
({
  -title=>'Input Request',
  -head=>Link({-rel => 'stylesheet', 
                        -media  => 'print',
                        -type   => 'text/css',
                        -href   => 'style.css'}), 

}),

print $q->div(
              {-id=>"divtop"},
              $q->p("Here's a paragraph")
             );
$q->start_form
(
    -method=>'post',
    ), "\n",

    "Operating System",

    $q->radio_group
    (
    -name=>'ostype',
    -values=>['Windows','Linux'],
    ),
    $q->br, "\n",
$q->end_html;
4

3 回答 3

3

运行代码后,问题非常明显。这是它输出的第一行......

<div id="divtop"><p>Here's a paragraph</p></div>Content-Type: text/html; charset=ISO-8859-1

“Content-Type:”标头绝对应该是您的 CGI 脚本中最先出现的内容。其他任何东西,您的网络服务器将不知道如何处理输出。

看起来您对代码中的分号和逗号感到困惑

print $q->header,

$q->start_html
({
  -title=>'Input Request',
  -head=>Link({-rel => 'stylesheet', 
                        -media  => 'print',
                        -type   => 'text/css',
                        -href   => 'style.css'}), 

}),

print $q->div(
              {-id=>"divtop"},
              $q->p("Here's a paragraph")
             );

用逗号链接这 3 个语句意味着代码会发生并且返回值被添加到第一个打印的事物列表print中。<div>print

整理一下,你的代码应该是这样的。标题行首先出现,它本身只是一个语句。

print $q->header;

我真的不知道那乱七八糟的 CGI HTML 代码是什么样子的,所以我不打算尝试修复它,尽管我认为它应该只是一个长的逗号分隔语句。你真的应该看看像模板工具包这样更好的东西。相比之下,即使只是打印出原始 HTML 也会更容易阅读 IMO。

此外,只是为了涵盖所有基础,脚本的第一行似乎在前面有一个空格 - 如果它确实存在并且不仅仅是复制粘贴错误,也会导致问题。

 #!"c:\xampp\perl\bin\perl.exe"
于 2018-02-07T17:50:49.580 回答
1

您应该了解print(或任何其他功能的工作方式):

1)这是一个例子:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;
use DBI;

sub do_stuff {
    print "xxx\n";
}

print "goodbye\n", do_stuff, "\n";

你认为 perl 会首先输出什么?字符串“goodbye\n”还是字符串“xxx”?换句话说,该 print 语句是否等同于:

print "goodbye\n";
print dostuff;
print "\n";

???

2)这是另一个例子:

print "hello", die("Too tired too print anything else...");

你认为输出会是什么?die()使您的程序立即终止并在退出前输出指定的消息。

The ruleis:函数的参数必须在函数本身执行之前完全确定。因此,在您编写的 perl 脚本中:

print $q->header,

...这是正确的,因为您必须先输出响应标头。但是还有那个尾随的逗号。你继续你的印刷声明:

print $q->header, $q->start_html(), print $q->div() 

该声明相当于:

print(
    $q->header,
    $q->start_html(),
    print($q->div)
)

好的,应用规则:在print()确定三个参数中的每一个之前,外部不会执行。因此,perl 执行$q->header,它返回一个字符串。规则 #2 是:代码中的所有函数调用都替换为函数的返回值。这给了你:

print(
    "some http response info,
    $q->start_html()
    print($q->div)
)

接下来,perl 执行$q->html,它也返回一个字符串,给你:

print(
    "some http response info",
    "<html> blah blah",
    print($q->div)
)

最后,评估第三个参数,print($q->div)。第三个参数等价于print("<div>..."),给你:

print(
    "some html response stuff",
    "<html> blah blah",
    print("<div...")
)

正如我在回答开头的前两个示例所展示的那样,内部 print() 将在外部 print 能够打印前两个参数之前执行。因此,您最终不会首先输出标题,因此您的错误。 print("<div...")实际上在输出字符串后返回 1,所以你最终得到:

print(
    "some html response stuff",
    "<html> blah blah",
    1
)

现在外部打印终于可以执行了。

我正在为我的服务器使用 Apache,您的 perl 脚本位于此处:

apache2/cgi-bin/perl2.pl 

用于检索脚本输出的 url:

http://localhost:8080/cgi-bin/perl2.pl

我在这里放了一个css文件:

apache2/cgi-bin/htdocs/css/my.css

通常,我可以在不指定 htdocs 目录的情况下检索 htdocs 中的 html 页面,因此:

http://localhost:8080/page.html

因此,从 cgi-bin 目录到 htdocs 目录中文件的路径很简单:

../css/my.css  (rather than ../htdocs/css/my.css)

这是您的代码,其中包含访问 css 文件所需的所有更改:

use strict;
use warnings;
use CGI qw(:all); 
use CGI::Carp qw(fatalsToBrowser);

my $q = new CGI;

print(

    $q->header,

    $q->start_html(
        -title => 'Input Request',
        -style=>{-src=>"../css/my.css"}    #<==THIS CREATES A LINK TAG           
    ),

    $q->div(
        {-id=>"divtop"},
        $q->p("Here's a paragraph")
    ),

    $q->start_form(
        -method=>'post'
    ),

    $q->div("OperatingSystem"),
    $q->div(
        $q->radio_group(
            -name=>'ostype',
            -values=>['Windows','Linux']
        )
    ),

    $q->end_form,
    $q->end_html
);

这是 perl 脚本创建的 html(间距由我调整):

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">

<head>
  <title>Input Request</title>
  <link rel="stylesheet" type="text/css" href="../css/my.css" />
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>

<body>

<div id="divtop"><p>Here's a paragraph</p></div>

<form method="post" action="/cgi-bin/perl2.pl" enctype="multipart/form-data">
  <div>OperatingSystem</div>
  <div>
    <label><input type="radio" name="ostype" value="Windows" checked="checked" />Windows</label> 
    <label><input type="radio" name="ostype" value="Linux" />Linux</label>
  </div>

<div><input type="hidden" name=".cgifields" value="ostype"  /></div>
</form>

</body>
</html>

请注意,您可以免费获得 head 标签。我认为这是因为标题和链接标签应该在格式良好的 html 中的 head 标签内。

而且,这里使用的是Link()

print(

    $q->header,

    $q->start_html(
        -title => 'Input Request',
        -head  => Link({
                   -rel    => 'stylesheet',
                   -type   => 'text/css',
                   -href   => '../css/my.css'
                  })    
    ),

    $q->div(
        {-id=>"divtop"},
        $q->p("Here's a paragraph")
    ),

    $q->start_form(
        -method=>'post'
    ),

    $q->div("OperatingSystem"),
    $q->div(
        $q->radio_group(
            -name=>'ostype',
            -values=>['Windows','Linux']
        )
    ),

    $q->end_form(),

    $q->br(),
    $q->end_html()

);

如果我添加media => 'printLink()将属性添加到链接标记的哈希中media="print",则 css 在我的浏览器中被禁用。另一方面,当我在浏览器中对页面进行打印预览时,我确实看到了 css 样式。我认为这是预期的行为。这是html:

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">

<head>
<title>Input Request</title>
<link type="text/css" rel="stylesheet" href="../css/my.css" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>

<body>
<div id="divtop"><p>Here's a paragraph</p></div><form method="post" action="/cgi-bin/perl2.pl" enctype="multipart/form-data"><div>OperatingSystem</div><div><label><input type="radio" name="ostype" value="Windows" checked="checked" />Windows</label> <label><input type="radio" name="ostype" value="Linux" />Linux</label></div><div><input type="hidden" name=".cgifields" value="ostype"  /></div></form><br />
</body>
</html>
于 2018-02-07T17:24:56.263 回答
0

CGI 程序通常放置在经过cgi-bin配置的目录中,因此 Web 服务器将其中的所有内容视为 CGI 兼容的可执行文件。您的 CSS 文件不是可执行的 CGI 程序!

将您的静态文件移到外面 cgi-bin并更改您用来引用它们的 URL 以指向它们的新 URL。

于 2018-02-07T16:08:58.393 回答