Ruby_08_CGI编程



Ruby CGI 编程

Ruby 是一门通用的语言,不仅仅是一门应用于WEB开发的语言,

但有一说一哈,不吹不黑, 咱Ruby 在WEB应用及WEB工具中的开发那可是最常见的哈。

使用Ruby您不仅可以编写自己的SMTP服务器,FTP程序,或Ruby Web服务器,而且还可以使用Ruby进行CGI编程喔~

来来来,接下来,让我们花点时间来会一会Ruby的CGI编程吧。


网页浏览

为了更好的了解CGI是如何工作的,我们可以从在网页上点击一个链接或URL的流程:

  • 1、使用你的浏览器访问URL并连接到HTTP web 服务器。
  • 2、Web服务器接收到请求信息后会解析URL,并查找访问的文件在服务器上是否存在,如果存在返回文件的内容,否则返回错误信息。
  • 3、浏览器从服务器上接收信息,并显示接收的文件或者错误信息。

CGI程序可以是 Ruby 脚本,Python 脚本,PERL 脚本,SHELL 脚本,C 或者 C++ 程序等。


CGI架构图



Web服务器支持及配置

在你进行CGI编程前,确保您的Web服务器支持CGI及已经配置了CGI的处理程序。

Apache 支持CGI 配置:

在终端使用httpd -V命令可以查看httpd.conf所在的目录,

 其中HTTPD_ROOT和SERVER_CONFIG_FILE 就可以确定httpd.conf的路径了



本机的所在目录是:

SERVER_CONFIG_FILE="/private/etc/apache2/httpd.conf"


设置好CGI目录,如图所示(由于之前学Python的CGI编程已经设置过了)



#这是在学习Python的CGI编程时,已经设置了的CGI目录ScriptAlias /cgi-bin/ "/Users/beyond/sg_python/cgi-bin/"

所有的HTTP服务器执行CGI程序都保存在一个预先配置的目录。这个目录被称为CGI目录,

并按照国际惯例,它应该被命名为/var/www/cgi-bin目录。(我就不设置了,直接使用以前的Python的CGI目录了)

CGI文件的扩展名为.cgi,Ruby 也可以使用 .rb 扩展名。

默认情况下,Linux服务器配置运行的cgi-bin目录中为/var/www。

如果你想指定其他运行CGI脚本的目录,可以修改httpd.conf配置文件,

如下所示:


#在学习Python的CGI编程时,已经设置过了<Directory "/Users/beyond/sg_python/cgi-bin/">
   AllowOverride None
   Options +ExecCGI
   Order allow,deny
   Allow from all
</Directory>

在 AddHandler 中添加 .rb 后缀,这样我们就可以访问 .rb 结尾的 Ruby 脚本文件:


AddHandler cgi-script .cgi .pl .py .rb

编写 CGI 脚本

最简单的脚本用 Ruby CGI 代码表示如下所示:

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

puts "Content-type: text/html;charset=utf-8\n\n"
puts "  <html>
		<body>
		妳好,二次元!
		This is a website by ruby cgi
		</body>
	</html>"

然后保存名称为: cgi_1.rb (或者ruby_1.cgi)文件中,并把该代码保持到CGI目录下

然后上传(即保存)到服务器CGI目录(即前面设置的/Users/beyond/sg_python/cgi-bin)并赋予足够权限(如chmod 755  cgi_1.rb) 即可作为 CGI 脚本执行。

文件所在的位置如图所示:


然后更改权限,否则会报服务器内部500错误:


在浏览器中运行结果如下:



浏览器访问该网址后,Web 服务器会在站点CGI目录下找到 cgi_1.rb文件,然后通过Ruby解析器来解析脚本代码并访问HTML文档。


使用 cgi.rb

Ruby 可以调用 CGI 库来编写更复杂的CGI脚本。

以下代码调用了 CGI 库来创建一个脚本的CGI脚本。

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

require 'cgi'

cgi = CGI.new("html4")
puts cgi.header
puts "   <html>
		<body>
		hello beyond~
		This is a website by ruby cgi
		</body>
	  </html>"

以下代码中,创建了CGI 对象并打印头部信息。???Excuse Me???为啥什么也没看到输出???



在终端可以正常输出,如图所示



打印一下cgi = CGI.new("html4")对象,如图所示:



也可以使用快速输出,代码如下:

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

require "cgi"

cgi = CGI.new("html4")
cgi.out { 
        cgi.html { 
                cgi.body { 
                        cgi.h3 { "hello beyond " } 
                } 
        } 
}

效果如下:




表单处理

使用CGI库可以通过两种方式获取表单提交(或URL中的参数)的数据, 

例如URL:localhost/cgi-bin/cgi_3.rb?id=1&name=beyond

你可以使用 CGI#[] 来直接获取参数id和name:

#!/usr/bin/ruby

require 'cgi'
cgi = CGI.new('html4')
cgi['id']      # "id" =>  ["1"]
cgi['name']    # "name" =>  ["beyond"]

 

另外一种获取表单数据的方法:

#!/usr/bin/ruby

require 'cgi'
cgi = CGI.new
dict = cgi.params  # =>  {"id"=>["1"],"name"=>["beyond"]}
dict['id']  # =>  ["1"]
dict['name']   # =>  ["beyond"]

 

以下代码用于检索所有的键值:

#!/usr/bin/ruby

require 'cgi'
cgi = CGI.new
cgi.keys         # =>  ["id", "name"]

 

如果表单包含了多个相同名称的字段,则该相同字段的值将保存在数组中。

以下实例中,指定表单中三个相同的字段"name",值分别为 "beyond", "keke" 和 "面码":

#!/usr/bin/ruby

require 'cgi'
cgi = CGI.new
cgi['name']        # => "beyond"
cgi.params['name'] # => ["beyond", "keke", "面码"]
cgi.keys           # => ["name"]
cgi.params         # => {"name"=>["beyond", "keke", "面码"]}

注意:Ruby 会自动判断 GET 和 POST 方法,所以无需对两种方法区别对待。


以下是相关的HML代码:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0" />
</head>
<body>
<form method="POST" action="/cgi-bin/cgi_4.rb">
id :<input type="text" name="id" value="" />
<br />
name :<input type="text" name="name" value="" /> 
<input type="submit" value="submit" />
</form>
</body>
</html>



创建 Form 表单和 HTML

CGI 包含了大量的方法来创建 HTML,每个HTML标签都有相对应的方法。 

在使用这些方法前,比必须通过 CGI.new 来创建 CGI 对象。

为了使标签的嵌套更加的简单,这些方法将内容作为了代码块,代码块将返回字符串作为标签的内容。

代码如下所示:

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

require "cgi"
cgi = CGI.new("html4")
cgi.out{
	cgi.html{
		cgi.head{ "\n" +'<meta http-equiv=Content-Type content="text/html;charset=utf-8">' + cgi.title{"hello beyond"}}+
		cgi.body{ "\n" +
			cgi.form{"\n"+
				cgi.hr +
				cgi.h1{"未闻花名"} + "\n" +
				cgi.textarea("content") + "\n" +
				cgi.br +
				cgi.submit
			}
		}
	}
}


浏览器中的效果如图所示:





字符串转义

当你在处理 URL 中的参数或者 HTML 表单数据时,需要对指定的特殊字符进行转义,如:引号("),反斜杠(/)。

Ruby CGI 对象提供了CGI.escape 和 CGI.unescape 方法来处理这些特殊字符的转义:

以上代码执行结果如下:


另一组实例,CGI.escapeHTML("<h1>hello beyond</h1>")

以下代码执行结果如下:



CGI 类中常用的方法

以下是Ruby中完整的CGI类的相关方法

  • Ruby CGI - 标准 CGI 库相关方法

Cookies 和 Sessions

  • Ruby CGI Cookies - 如何处理 CGI Cookies.
  • Ruby CGI Sessions - 如何处理 CGI sessions.

Ruby CGI方法

以下为CGI类的方法列表:

序号方法描述
1CGI::new([ level="query"])
创建 CGI 对象。query可以是以下值:
  • query: 没有 HTML 生成输出

  • html3: HTML3.2

  • html4: HTML4.0 Strict

  • html4Tr: HTML4.0 Transitional

  • html4Fr: HTML4.0 Frameset

2CGI::escape( str)
使用 URL 编码来转义字符串
3CGI::unescape( str)
对通过 escape() 编码的字符串进行解码。
4CGI::escapeHTML( str)
编码 HTML 特殊字符, 包括: & < >。
5CGI::unescapeHTML( str)
解码 HTML 特殊字符, 包括: & < >。
6CGI::escapeElement( str[, element...])
在指定的 HTML 元素中编码 HTML 特殊字符。
7CGI::unescapeElement( str, element[, element...])
在指定的 HTML 元素中解码 HTML 特殊字符。
8CGI::parse( queryString)
解析查询字符串,并返回包含哈希的 键=》值 对
9CGI::pretty( string[, leader=" "])
返回整齐的HTML格式。 如果指定了 leader ,它将写入到每一行的开头。 leader 默认值为两个空格。
10CGI::rfc1123_date( time)
根据 RFC-1123 来格式化时间 (例如, Tue, 2 Jun 2008 00:00:00 GMT)。

CGI 实例化方法

以下实例中我们将 CGI::new 的对象赋值给 cgi 变量,方法列表如下:

序号方法描述
1cgi[ name]
返回一个数组,包含了对应字段名为 name 的所有的值(具体可参照上面的示例图)。
2cgi.checkbox( name[, value[, check=false]])
cgi.checkbox( options)

返回 HTML 字符串用于定义 checkbox 字段。

标签的属性可以以一个哈希函数作为参数传递。

3cgi.checkbox_group( name, value...)
cgi.checkbox_group( options)

>返回 HTML 字符串用于定义 checkbox 组。

同样有,标签的属性可以以一个哈希函数作为参数传递。

4cgi.file_field( name[, size=20[, max]])
cgi.file_field( options)

返回定义 file 字段的HTML字符串。
5cgi.form([ method="post"[, url]]) { ...}
cgi.form( options)

返回定义 form 表单的HTML字符串。 

如果指定了代码块,将作为表单内容输出。

类似的,标签的属性可以以一个哈希函数作为参数传递。

6cgi.cookies
返回 CGI::Cookie 对象,包含了cookie 中的键值对
7cgi.header([ header])

返回 CGI 头部的信息。

如果 header 参数是哈希值,其键 => 值对,用于创建头部信息。

8cgi.hidden( name[, value])
cgi.hidden( options)

返回定义一个隐藏字段的HTML字符串。

跟上面一样,标签的属性可以以一个哈希函数作为参数传递。

9cgi.image_button( url[, name[, alt]])
cgi.image_button( options)

返回定义一个图像按钮的HTML字符串。

同样的,标签的属性可以以一个哈希函数作为参数传递。

10cgi.keys
返回一个数组,包含了表单的字段名。
11cgi.key?( name)
cgi.has_key?( name)
cgi.include?( name)

如果表单包含了指定的字段名返回 true。
12cgi.multipart_form([ url[, encode]]) { ...}
cgi.multipart_form( options) { ...}

返回定义一个多媒体表单(multipart)的HTML字符串。

类似的,标签的属性可以以一个哈希函数作为参数传递。

13cgi.out([ header]) { ...}
生成 HTML 并输出。使用 由块的输出 来创建页面的主体生成的字符串。
14cgi.params
返回包含表单字段名称的哈希值 key => value。
15cgi.params= hash
设置使用字段名和值。
16cgi.password_field( name[, value[, size=40[, max]]])
cgi.password_field( options)

返回定义一个password字段的HTML字符串。

同样的,标签的属性可以以一个哈希函数作为参数传递。

17cgi.popup_menu( name, value...)
cgi.popup_menu( options)
cgi.scrolling_list( name, value...)
cgi.scrolling_list( options)

返回定义一个弹出式菜单的HTML字符串。

类似的,标签的属性可以以一个哈希函数作为参数传递。

18cgi.radio_button( name[, value[, checked=false]])
cgi.radio_button( options)

返回定义一个radio字段的HTML字符串。

同样的,标签的属性可以以一个哈希函数作为参数传递。

19cgi.radio_group( name, value...)
cgi.radio_group( options)

返回定义一个radio按钮组的HTML字符串。

类似的,标签的属性可以以一个哈希函数作为参数传递。

20cgi.reset( name[, value])
cgi.reset( options)

返回定义一个reset按钮的HTML字符串。 

同样的,标签的属性可以以一个哈希函数作为参数传递

21cgi.text_field( name[, value[, size=40[, max]]])
cgi.text_field( options)

返回定义一个text字段的HTML字符串。

类似的,标签的属性可以以一个哈希函数作为参数传递。

22cgi.textarea( name[, cols=70[, rows=10]]) { ...}
cgi.textarea( options) { ...}

返回定义一个textarea字段的HTML字符串。 

如果指定了块,代码块输出的字符串将作为 textarea 的内容。 

同样的,标签的属性可以以一个哈希函数作为参数传递。


HTML 生成方法

你可以再 CGI 实例中使用相应的 HTML 标签名来创建 HTML 标签,实例如下:

代码如下:(与cgi_4.rb源码一样)

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

require "cgi"
cgi = CGI.new("html4")
cgi.out{
	cgi.html{
		cgi.head{ "\n" +'<meta http-equiv=Content-Type content="text/html;charset=utf-8">' + cgi.title{"hello beyond"}}+
		cgi.body{ "\n" +
			cgi.form{"\n"+
				cgi.hr +
				cgi.h1{"未闻花名"} + "\n" +
				cgi.textarea("content") + "\n" +
				cgi.br +
				cgi.submit
			}
		}
	}
}


运行效果如下



CGI 对象属性

你可以再 CGI 实例中使用以下属性:

属性返回值
accept可接受的 MIME 类型
accept_charset可接受的字符集
accept_encoding可接受的编码
accept_language可接受的语言
auth_type可接受的类型
raw_cookieCookie 数据 (原字符串)
content_length内容长度(Content length)
content_type内容类型(Content type)
FromClient e-mail 地址
gateway_interfaceCGI 版本
path_info路径
path_translated转换后的路径
Query_string查询字符串
referer之前访问网址
remote_addr客户端主机地址(IP)
remote_host客户端主机名
remote_ident客户端名
remote_user经过身份验证的用户
request_method请求方法(GET, POST, 等。)
script_name参数名
server_name服务器名
server_port服务器端口
server_protocol服务器协议
server_software服务器软件
user_agent用户代理(User agent)


Ruby CGI Cookies

HTTP协议是无状态协议。

但对于一个商业网站,它需要保持不同的页面间的会话信息。

如用户在网站注册过程中需要跳转页面,但又要保证之前填写的信息不会丢失。

那么,在这种情况下 Cookie 就很好的帮我们解决了问题的啦啦啦~~


Cookie 是如何工作的?

几乎所有的网站设计者在进行网站设计时都使用了Cookie,

因为他们都想给浏览网站的用户提供一个更友好的、人文化的浏览环境,

同时也能更加准确地收集访问者的信息(嘿嘿,妳懂的~)。


写入和读取

Cookies集合是附属于Response对象及Request对象的数据集合,使用时需要在前面加上Response或Request。


用于给客户机发送Cookies的语法通常为:

当给  不存在的Cookies集合  设置时,就会在客户机创建,

如果该Cookies己存在,则会被代替。

由于Cookies是作为HTTP传输的头信息的一部分发给客户机的,所以向客户机发送Cookies的代码一般来说,

是放在发送给浏览器的HTML文件的标记之前。


如果用户要读取Cookies,则必须使用Request对象的Cookies集合,

其使用方法是: 需要注意的是:

只有在服务器未被下载任何数据给浏览器之前,浏览器才能与Server进行Cookies集合的数据交换,

一旦浏览器开始接收Server所下载的数据,Cookies的数据交换则停止,

为了避免错误,要在程序和前面请加上response.Buffer=True ???Excuse Me???

集合的属性

  • 1.Expires属性:此属性用来给Cookies设置一个期限,在期限内只要打开网页就可以调用被保存的Cookies,如果过了此期限Cookies就自动被删除。如: 设定Cookies的有效期到2018年6月7日,到时将自动删除。如果一个Cookies没有设定有效期,则其生命周期从打开浏览器开始,到关闭浏览器结束,每次运行后生命周期将结束,下次运行将重新开始。
  • 2.Domain属性:这个属性定义了Cookies传送数据的唯一性。
  • 3.Path属性:定义了Cookies只发给指定的路径请求,如果Path属性没有被设置,则使用应用软件的缺省路径
  • 4.Secure属性指定Cookies能否被用户读取。
  • 5、Name=Value : Cookies是以键值对的形式进行 设置和检索的。

Ruby 中处理Cookies

你可以创建一个名为 cookie 的对象并存储文本信息,将该信息发送至浏览器,

调用 CGI.out 设置cookie的头部的示例代码如下:

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

require "cgi"
cgi = CGI.new("html4")
cookie = CGI::Cookie.new('name' => 'sex',
						 'value' => 'loli',
						 'expires' => Time.now + 3600)   #有效时间 1小时
#在输入html代码之前,先输出cookie
cgi.out('cookie' => cookie) do 
	cgi.head + cgi.body{"Cookie has been stored"}
end

运行结果如下:


两种方法查看刚才CGI脚本向客户端输出的cookie

1.在地址栏左边可以看到一下 小的提示图标,点击提示图标即可查看




 2.第2种查看方式,使用chrome 自带的调试工具(这里的时区是零时区,要加8个小时)



接下来我们新建一个cgi页面,并查找cookie中名字是sex所对应的值loli,如下所示:

 

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

require "cgi"
cgi = CGI.new("html4")
#读取cookie,这个sex是cgi_6设置的cookie的name(也就是key)
cookie  = cgi.cookies['sex']
cgi.out('cookie' => cookie) do
	cgi.head + cgi.body{cookie[0]}
end

运行结果:



CGI::Cookie对象实例化时包含以下参数:

参数描述
name规定 cookie 的名称。
value规定 cookie 的值。
expire规定 cookie 的有效期。
path规定 cookie 的服务器路径。
domain规定 cookie 的域名。
secure规定是否通过安全的 HTTPS 连接来传输 cookie。


Ruby CGI Sessions

CGI::Session 可以为用户和CGI环境保存持久的会话状态,会话使用后需要关闭,

这样可以保证数据写入到存储当中,当会话完成后,你需要删除该数据。

先看一个宝贝:


关于上面图片的一点点说明:

session_key: 键名保存会话 默认为 _session_id
session_id: 唯一的会话 ID。自动生成

new_session: 如果为true,为当前会话创建一个新的Session id。 如果为 false, 通过 session_id 使用已存在的 session 标识。 如果省略该参数,如果可以用的话就使用现有的会话,否则创建一个新的。

prefix: 对于 FileStore, 为 session 在磁盘的文件的前缀名。

磁盘的路径如下:


cgi_8.rb的代码如下:

#!/usr/bin/ruby 
# -*- coding: UTF-8 -*-
#coding=utf-8

require "cgi"
require "cgi/session"
cgi = CGI.new("html4")
#创建session会话
# 会话数据存在在服务器的临时文件目录中,
# prefix 参数指定了会话的前缀,将作为临时文件的前缀。这样你在服务器上可以轻松的识别不同的会话临时文件。
session = CGI::Session.new(cgi,"session_key" => "session_id_number","prefix" => "tmpFileConversation_prefix")
#从session中取出上次存入的值
lastAccessTime = session['lastAccessTime'].to_s
#将最新的当前访问的时间,存入session里面
session['lastAccessTime'] = Time.now

#http://localhost/cgi-bin/cgi_8.rb?bgcolor=red
#如果请求的参数bgcolor所对应的字符串的首字母是a-z的字母
if cgi['bgcolor'][0] =~ /[a-z]/
	#那么就把请求参数bgcolor的值red存入到session中保存
	session['bgcolor'] = cgi['bgcolor']
end
#输出html页面
cgi.out{
	cgi.html{
		#head
		cgi.head{ "\n" +'<meta http-equiv=Content-Type content="text/html;charset=utf-8">' + cgi.title{"hello beyond"}}+
		#body的bgcolor颜色值 为 session中取出来的,也就是请求路径cgi_8.rb?bgcolor=red传递进来的颜色值
		cgi.body("bgcolor" => session["bgcolor"]){
			"页面的背景颜色由用户的请求参数bgcolor的值决定<br/>"+
			"当前时间是:#{Time.now}<br/>"+
			"您上次访问本站的时间是:#{lastAccessTime}"
		}
	}
}

运行效果如下:


注意:访问 "localhost/cgi-bin/cgi_08.rb?bgcolor=pink" 将会给页面设置指定的背景颜色。

会话数据存在在服务器的临时文件目录中,prefix 参数指定了会话的前缀,将作为临时文件的前缀。

这样你在服务器上可以轻松的识别不同的会话临时文件。


CGI::Session 类

CGI::Session 保持了用户与 CGI 环境的持久状态。 

会话可以在内存中,也可以在硬盘上。

类方法

Ruby 类 Class CGI::Session 提供了简单的方法来创建 session:

CGI::Session::new( cgi[, option])

启用一个新的 CGI 会话并返回相应的 CGI::Session 对象。

选项可以是可选的哈希(key => value),可以是以下值:

  • session_key: 键名保存会话 默认为 _session_id。
  • session_id: 唯一的会话 ID。自动生成
  • new_session: 如果为true,为当前会话创建一个新的Session id。 如果为 false, 通过 session_id 使用已存在的 session 标识。 如果省略该参数,如果可用则使用现有的会话,否则创建一个新的。
  • database_manager: 用于保存 sessions 的类,可以是 CGI::Session::FileStore or CGI::Session::MemoryStore。默认为 FileStore
  • tmpdir: 对于 FileStore, 为 session 的存储目录
  • prefix: 对于 FileStore, 为 session 文件的前缀。

实例化方法

序号方法描述
1[ ]
返回给定 key 的值
2[ ]=
设置给定 key 的值
3delete

调用底层数据库管理的删除方法。

对于 FileStore, 删除包含 session 的物理文件。 

对于 MemoryStore, 从内存中移除 session 数据。

4update

调用底层数据库管理的更新方法。 

对于 FileStore, 将 session 写入到磁盘中。 

对于 MemoryStore则无效果。



未完待续,下一章节,つづく



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值