为 cgi.pm 文件添加 css



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

#!"c:xamppperlbinperl.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;

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

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

"内容类型:"标头应该是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 个语句意味着<div>print的代码发生,并且返回值被添加到第一个print打印的内容列表中。

整理一下,你的代码应该看起来像这样。标题行排在第一位,本身只是一个语句。

print $q->header;

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

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

#!"c:xamppperlbinperl.exe"

你应该了解print(或任何其他函数)是如何工作的:

1)这里有一个例子:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;
use DBI;
sub do_stuff {
print "xxxn";
}
print "goodbyen", do_stuff, "n";

你认为perl会首先输出什么? 字符串"再见"还是字符串"xxx"? 换句话说,该打印语句是否等效于:

print "goodbyen";
print dostuff;
print "n";

???

2)这是另一个例子:

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

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

The rule是:在函数本身执行之前,必须完全确定函数的参数。因此,在你的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("<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>

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

而且,这里它使用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 => 'print添加到Link()哈希中,这会将属性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>

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

将静态文件移到cgi-bin之外,并更改用于引用它们的 URL,以指向其新 URL。