Ruby CGI方法
在 Ruby 中,CGI(Common Gateway Interface) 编程通过内置的 cgi
库提供了一系列方法,用于处理 Web 请求、生成动态内容、管理 Cookies 和处理文件上传等。以下是对 Ruby cgi
库中常用方法的中文讲解,涵盖核心功能、用法及示例,力求简洁清晰,避免重复之前的内容(如 CGI 编程概述)。内容将聚焦于 CGI
类的方法及其实际应用。
1. CGI 类概述
Ruby 的 cgi
模块提供 CGI
类,用于处理 HTTP 请求(GET、POST)、生成 HTML 响应、管理 Cookies 和处理表单数据。所有 CGI 脚本需引入:
require 'cgi'
2. 创建 CGI 对象
CGI.new
:初始化 CGI 对象,解析 HTTP 请求。
cgi = CGI.new
参数:
html
:指定 HTML 版本(默认 HTML4),如"html5"
。
cgi = CGI.new("html5")
3. 常用 CGI 方法
以下是 CGI
类中常用的实例方法和类方法,分为请求处理、响应生成、Cookies 和工具方法。
3.1 请求处理方法
cgi.params
:获取请求参数(GET 或 POST),返回哈希,键为参数名,值为数组。
cgi = CGI.new
name = cgi.params['name'][0] # 获取 name 参数的第一个值
puts "Content-type: text/html\n\n"
puts "<p>Name: #{CGI.escapeHTML(name)}</p>"
示例 URL:http://localhost/cgi-bin/test.rb?name=Alice
输出:Name: Alice
cgi[key]
:快捷获取参数值(返回字符串,单值时更简洁)。
puts "<p>Name: #{CGI.escapeHTML(cgi['name'])}</p>"
cgi.multipart?
:检查请求是否为multipart/form-data
(常用于文件上传)。
puts cgi.multipart? # 输出:true(如果是文件上传表单)
cgi.cookies
:获取请求中的 Cookies,返回哈希。
user_id = cgi.cookies['user_id'][0] || 'Guest'
puts "<p>User ID: #{CGI.escapeHTML(user_id)}</p>"
3.2 响应生成方法
cgi.out(options = {})
:生成 HTTP 响应头和内容,自动添加Content-type
。
cgi = CGI.new
cgi.out do
"<html><body><h1>Hello, CGI!</h1></body></html>"
end
选项:
type
:Content-type(如"text/html"
)。status
:HTTP 状态码(如"404 Not Found"
)。cookie
:Cookies 数组。
cookie = CGI::Cookie.new('name' => 'user_id', 'value' => '12345')
cgi.out('cookie' => [cookie], 'type' => 'text/html') do
"<html><body><p>Cookie set!</p></body></html>"
end
cgi.header(options = {})
:仅生成 HTTP 响应头。
puts cgi.header('type' => 'text/plain')
puts "Plain text response"
3.3 HTML 生成方法
CGI
类提供方法生成 HTML 标签(基于 HTML 版本)。
cgi.element_name(attributes = {})
:生成指定 HTML 标签,如cgi.h1
,cgi.p
。
cgi = CGI.new("html5")
puts cgi.out do
cgi.html do
cgi.body do
cgi.h1 { "Welcome" } + cgi.p { "This is a paragraph." }
end
end
end
输出:
<html>
<body>
<h1>Welcome</h1>
<p>This is a paragraph.</p>
</body>
</html>
cgi.form(attributes = {}, &block)
:生成表单。
puts cgi.out do
cgi.form('action' => '/cgi-bin/submit.rb', 'method' => 'post') do
cgi.text_field('name') + cgi.submit('Submit')
end
end
输出:
<form action="/cgi-bin/submit.rb" method="post">
<input type="text" name="name"><input type="submit" value="Submit">
</form>
3.4 Cookies 管理
CGI::Cookie.new(name, value)
:创建 Cookie 对象。
cookie = CGI::Cookie.new(
'name' => 'user_id',
'value' => '12345',
'expires' => Time.now + 3600, # 1 小时后过期
'path' => '/',
'secure' => true
)
- 设置 Cookie:通过
cgi.out
或cgi.header
设置。
cgi.out('cookie' => [cookie]) { "<p>Cookie set!</p>" }
3.5 工具方法(类方法)
CGI.escape(string)
:对 URL 编码。
puts CGI.escape("name=Alice & Bob") # 输出:name%3DAlice+%26+Bob
CGI.unescape(string)
:解码 URL 编码。
puts CGI.unescape("name%3DAlice+%26+Bob") # 输出:name=Alice & Bob
CGI.escapeHTML(string)
:转义 HTML 特殊字符,防止 XSS。
puts CGI.escapeHTML("<script>alert('xss')</script>") # 输出:<script>alert('xss')</script>
CGI.unescapeHTML(string)
:解码 HTML 转义字符。
puts CGI.unescapeHTML("<p>Hello</p>") # 输出:<p>Hello</p>
4. 文件上传处理
处理 multipart/form-data
表单上传的文件。
表单示例
<form action="/cgi-bin/upload.rb" method="post" enctype="multipart/form-data">
File: <input type="file" name="file">
<input type="submit" value="Upload">
</form>
处理上传
#!/usr/bin/ruby
require 'cgi'
cgi = CGI.new
file = cgi.params['file'][0]
filename = CGI.escapeHTML(file.original_filename)
content = file.read
# 保存文件
File.open("uploads/#{filename}", "wb") { |f| f.write(content) }
cgi.out do
"<html><body><p>File #{filename} uploaded!</p></body></html>"
end
说明:
file.original_filename
:获取上传文件名。file.read
:读取文件内容。- 确保
uploads
目录存在且有写权限。
5. 异常处理
CGI 脚本需处理参数缺失或无效输入。
#!/usr/bin/ruby
require 'cgi'
cgi = CGI.new
begin
name = cgi['name'] || raise("Name 参数缺失")
cgi.out do
"<html><body><p>Hello, #{CGI.escapeHTML(name)}!</p></body></html>"
end
rescue => e
cgi.out('status' => '400') do
"<html><body><p>错误: #{CGI.escapeHTML(e.message)}</p></body></html>"
end
end
6. 注意事项
- 安全性:
- 使用
CGI.escapeHTML
转义用户输入,防止 XSS。 - 验证上传文件的类型和大小,防止恶意上传。
- 避免直接拼接 SQL 查询,结合数据库时使用参数绑定。
- 性能:CGI 每次请求启动新进程,适合小型应用,复杂项目推荐 Rails/Sinatra。
- 调试:检查 Web 服务器日志(如
/var/log/apache2/error.log
)。 - 环境变量:通过
ENV
访问REQUEST_METHOD
,QUERY_STRING
等。
puts ENV['REQUEST_METHOD'] # 输出:GET 或 POST
- HTML 版本:初始化
CGI.new
时指定 HTML 版本(如"html5"
),确保生成正确的标签。
7. 综合示例
#!/usr/bin/ruby
require 'cgi'
cgi = CGI.new("html5")
cookie = CGI::Cookie.new('name' => 'last_user', 'value' => cgi['name'] || 'Guest', 'expires' => Time.now + 3600)
begin
name = cgi['name'] || 'Guest'
cgi.out('cookie' => [cookie]) do
cgi.html do
cgi.body do
cgi.h1 { "Welcome, #{CGI.escapeHTML(name)}!" } +
cgi.form('action' => '/cgi-bin/form.rb', 'method' => 'post') do
cgi.p { "Name: " + cgi.text_field('name') } +
cgi.submit('Submit')
end +
cgi.p { "Last user: #{CGI.escapeHTML(cgi.cookies['last_user'][0] || 'None')}" }
end
end
end
rescue => e
cgi.out('status' => '400') do
"<html><body><p>错误: #{CGI.escapeHTML(e.message)}</p></body></html>"
end
end
保存:保存为 /usr/lib/cgi-bin/form.rb
,设置权限(chmod +x
)。
访问:http://localhost/cgi-bin/form.rb?name=Alice
。
功能:显示欢迎消息、表单,并通过 Cookie 记录上一个用户。
8. 总结
Ruby 的 CGI
类提供了丰富的实例方法(如 params
, out
, form
)和类方法(如 escapeHTML
, escape
),用于处理 HTTP 请求、生成动态 HTML、管理 Cookies 和文件上传。结合异常处理和转义方法,CGI 脚本可以安全处理用户输入。尽管 CGI 适合快速开发小型 Web 应用,但性能限制使其在现代开发中常被 Rails 或 Sinatra 替代。
如果你需要更具体的方法讲解(如特定 HTML 标签生成)或复杂示例,请告诉我!