Perl的CGI模块可以用于生成HTTP头部和HTML页面。本页内容采集自Perl的CGI文档。
CGI的同时支持命名参数和非命名参数,所有命名参数均为散列,并且必须为第一参数,非命名参数只对一些内建的常用操作符所识别,统一使用命名参数规则可以便于维护。像这样:
CGI的第二参数用于创建内容,内容分为两种,一种是串联,一种是并联,串联的内容中间插入分隔符($"),比如:
a({-href=>"localhost"}, "v1", "v2");
生成的tag是:
并联的内容则会将tag拷贝若干次,比如:
td({-align=>"center"}, ['t1', 't2'])
这个代码将产生如下的tag:
<td align="center">t2</td>
另外,有一些与Perl冲突的名字需要特殊对待:
- Select
- Tr
- Link
- Delete
- Accept
- Sub
接下来是一些功能部件,分述如下:
header:用于生成HTTP头部,有4个参数是被识别的,它们是:-type,-status,-expires,-cookie,其余的还有-nph,-charset,-attachment和-p3p:
- type用于控制文档MIME类型,浏览器通过它来决定如何处理跟在HTTP头部之后的数据
- status包含服务器返回的消息,1开头表示有后继,2开头表示成功,3开头表示重定向,4开头表示客户端错误,5表示服务器错误
- expires包含页面的时效时间,以now为点,+为前缀表示往后推的时间数,末尾带单位,y,M,d,h,m,s分别代表年月日时分秒,如+10h表示10小时后时效,now表示立刻失效
- cookie参数接受一个cookie
- nph会生成一个与NPH一起工作的脚本,没用过
- charset通知浏览器有关文档的字符集信息,这个选项会影响到HTML的-Content-Type中的字符集信息,它们应该保持一致
- attachment表示头部后面跟了一个附件,其值为建议保存的文件名。ScriptAlias下的文件不会被上传,附件应该直接写到输出流,type也应该设置为application/octet-stream
- p3p不清楚什么东西
其余的参数也可以传递给header,但仅仅是将参数首字母大写,写入字符参数而已。如果将引用传递进去,则会直接打印类型和地址。
redirect:重定向,-url指定重定向的URL,其余选项与header一致。
param:用于控制传递的参数,参数有关键字类型和key-value类型两种,关键字类型的参数像这样:k1+k2+k3,key-value类型则像这样:k1=v1&k2=v2,调试脚本时可以直接将键值当做参数传递给脚本,按照CGI文档的说法,调试阶段可以接受任意的看起来像表格的参数格式。也可以通过CGI->new直接初始化参数列表,而且还可以将文件句柄传递给CGI->save和CGI->restore将参数保存和提取,面向过程的风格就只能用restore_parameters读取文件句柄了。
参数的获取又有N种做法,最起码的,关键字类型的参数全部都被存放在keywords里面,可以通过$q->keywords或者param('keywords')获取,参数以字符串的形式保存,通过+连接;键-值类型则幸运许多,如果打算用param获取,则可以通过键获取值:param('key'),key只有单个值则用$v保存值,如果有多个值则用@v保存值。
还可以对参数执行多种操作,如修改,删除,添加,分别对应到param(-name=>"k", -value=>"v"),$q->delete/Delete或$q->delete_all/Delete_all,$q->append(-name=>"k",-value=>"v")
如果POST进来的参数类型既非application/x-www-form-urlencoded又非multipart/form-data,他们就不被解析而直接保存在'POSTDATA'名下,像PUTDATA也类似
param还提供了专门直接处理参数以便免去临时变量的方法:param_fetch返回一个数组的引用,引用意味着访问的是原始对象,加入,删除都会影响到内部参数。
最终提供的最强大的手段就是直接返回整个参数哈希表的引用,通过$q->Var或Var可以做到这点,scalar上下文中调用返回的就是哈希引用,对引用的修改影响到原始数据,但是list上下文则返回所有副本,k和v的副本,没有任何引用,{k=>v}返回的是(k, v),对于{k=>[v1, v2]}则返回(k, "v1\0v2")。
错误处理是通过$q->cgi_error来获取的,获取的就是HTTP的status码。
对于面向过程的风格代码,必须注意的是符号导入问题,Perl有多层的符号可以导入,但是通常只需要导入:standard即可。还有一些不常用的直接写上名字即可。
start_html:负责生成<head>.*</head><body>,解析的参数有-title,-author,-base,-xbase,-dtd,-lang和-target,所有参数详述如下:
- title生成标题,即<title>value</title>
- author生成作者邮件<link rev="made" href="mailto:url" />
- xbase生成<base href="url"/>标签,规定相对url的前缀
- dtd生成XML验证字串
- lang生成语言标记,默认是en_US
- target不被官方支持,它是base的属性之一,据说用来支持框架
- style会生成样式表链接
- encoding说明字符集,这个在未指定的情况下与header的charset给定的值一致,重复指定时应该避免混乱
- declare_xml给出<?xml?>声明
- head参数用于直接控制head的属性,它的值可以是数组引用或字符串,数组引用表明有若干个并联的tag,主要用于生成link和meta
- 专门用于脚本的选项有-script,-noscript,-onLoad,-onUnLoad,-onMouseOver,-onMouseOut,描述如下:
- script用于加入脚本,对于Javascript脚本,必须专门存放在$JSCRIPT中,否则都应该传递散列{-type=>"text/javascript", -src=>"js/jsc.js"},多个脚本则需要将它们括在一起传递:
start_html(-script=>[{-type=>"t1", -src=>"s1"}, {-type=>"t2", -src=>"s2"}]);
<head>
<title>Untitled Document</title>
<script src="s1" type="text/t"></script>
<script src="s2" type="text/t"></script>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head><body> - noscript用于在浏览器不支持脚本的情况下传递字符串
- 剩下的几个是动作
- script用于加入脚本,对于Javascript脚本,必须专门存放在$JSCRIPT中,否则都应该传递散列{-type=>"text/javascript", -src=>"js/jsc.js"},多个脚本则需要将它们括在一起传递:
- 其余不能处理的参数全部寄存到<body>名下,作为属性出现
解析URL:Perl提供了两个函数用于解析URL,self_url子过程返回文档当前的URL,url子过程则提供若干个选项来解析URL,参数皆为破折号打头,1或0为值,参数如下:
- absolute提供的是绝对路径,/path/script.cgi
- relative提供的是文件名,script.cgi
- full提供完整的URL,http://host:port/path/script.cgi
- query_string提供查询字串,k1=v1&k2=v2
- base提供地址前缀,http://host:port
- rewrite是为Apache的mod_rewrite提供的,提供rewrite之前的url
先写到这,考完再写表单。