CGI(通用网关接口)是一种让Web服务器与外部程序交互的标准方法。通过CGI,我们可以用Python编写动态网页程序,让网站能够处理表单、生成个性化内容等。
CGI就像网站和程序之间的桥梁。当你在网页上填写表单并点击提交时,CGI程序就会开始工作。它接收你输入的数据,进行处理,然后返回结果页面。
简单的工作流程:
你在浏览器中访问网站或提交表单
Web服务器收到请求
服务器调用CGI程序处理请求
CGI程序执行并生成结果
服务器将结果返回给浏览器显示
CGI程序可以用多种语言编写,包括Python、Perl、php等。
在使用CGI前,需要确保Web服务器支持CGI。以Apache服务器为例:
在Apache配置文件中设置CGI目录:
ScriptAlias /cgi-bin/ /var/www/cgi-bin/这样,所有CGI程序都放在/var/www/cgi-bin/目录中。
在配置中添加:
AddHandler cgi-script .cgi .pl .py这样服务器就能执行.py结尾的Python脚本了。
创建一个简单的"Hello World"程序:
#!/usr/bin/python3
print("Content-type: text/html; charset=utf-8")
print() # 空行,分隔头部和内容
print("<html>")
print("<head>")
print("<title>我的第一个CGI程序</title>")
print("</head>")
print("<body>")
print("<h1>Hello World!</h1>")
print("<p>这是我的第一个CGI程序</p>")
print("</body>")
print("</html>")将文件保存为hello.py,放到CGI目录中,然后设置权限:
chmod 755 hello.py在浏览器中访问http://你的网站/cgi-bin/hello.py就能看到结果。
CGI程序输出的第一部分是HTTP头部,告诉浏览器如何处理内容。
常用的头部信息:
Content-type: text/html - 内容是HTML格式
Content-type: text/plain - 纯文本内容
Location: URL - 重定向到其他页面
头部结束后必须有一个空行,然后才是实际内容。
CGI程序最重要的功能就是处理用户提交的数据。
GET方法将数据附加在URL后面:
http://example.com/cgi-bin/hello.py?name=张三&age=20处理GET请求的Python程序:
#!/usr/bin/python3
import cgi
# 获取表单数据
form = cgi.FieldStorage()
name = form.getvalue('name', '未知用户')
age = form.getvalue('age', '未知年龄')
print("Content-type: text/html; charset=utf-8")
print()
print("<html>")
print("<body>")
print(f"<h1>欢迎,{name}!</h1>")
print(f"<p>你的年龄是:{age}岁</p>")
print("</body>")
print("</html>")POST方法更安全,适合传输敏感信息。处理方式与GET类似:
#!/usr/bin/python3
import cgi
form = cgi.FieldStorage()
username = form.getvalue('username')
password = form.getvalue('password')
print("Content-type: text/html; charset=utf-8")
print()
print("<html>")
print("<body>")
if username and password:
# 这里应该验证用户名和密码
print(f"<h1>登录成功!</h1>")
print(f"<p>欢迎回来,{username}!</p>")
else:
print("<h1>请输入用户名和密码</h1>")
print("</body>")
print("</html>")HTML表单:
<form action="/cgi-bin/login.py" method="post">
用户名: <input type="text" name="username"><br>
密码: <input type="password" name="password"><br>
<input type="submit" value="登录">
</form>HTML:
<form action="/cgi-bin/survey.py" method="post">
<p>你喜欢的编程语言:</p>
<input type="radio" name="language" value="python"> Python<br>
<input type="radio" name="language" value="java"> Java<br>
<input type="radio" name="language" value="javascript"> JavaScript<br>
<input type="submit" value="提交">
</form>Python处理:
#!/usr/bin/python3
import cgi
form = cgi.FieldStorage()
language = form.getvalue('language', '未选择')
print("Content-type: text/html; charset=utf-8")
print()
print("<html>")
print("<body>")
print(f"<p>你选择的编程语言是:{language}</p>")
print("</body>")
print("</html>")HTML:
<form action="/cgi-bin/hobbies.py" method="post">
<p>你的爱好:</p>
<input type="checkbox" name="hobby" value="reading"> 阅读<br>
<input type="checkbox" name="hobby" value="sports"> 运动<br>
<input type="checkbox" name="hobby" value="music"> 音乐<br>
<input type="submit" value="提交">
</form>Python处理(注意:复选框可能有多个值):
#!/usr/bin/python3
import cgi
form = cgi.FieldStorage()
# 获取所有选中的爱好
hobbies = form.getlist('hobby')
print("Content-type: text/html; charset=utf-8")
print()
print("<html>")
print("<body>")
if hobbies:
print("<p>你的爱好:</p>")
print("<ul>")
for hobby in hobbies:
print(f"<li>{hobby}</li>")
print("</ul>")
else:
print("<p>你没有选择任何爱好</p>")
print("</body>")
print("</html>")HTML:
<form action="/cgi-bin/city.py" method="post">
<p>选择你所在的城市:</p>
<select name="city">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
<option value="shenzhen">深圳</option>
</select>
<input type="submit" value="提交">
</form>CGI程序可以访问服务器的环境变量,这些信息很有用:
#!/usr/bin/python3
import os
print("Content-type: text/html; charset=utf-8")
print()
print("<html>")
print("<body>")
print("<h1>服务器环境信息</h1>")
print("<table border='1'>")
print("<tr><th>变量名</th><th>值</th></tr>")
# 显示有用的环境变量
env_vars = {
'REMOTE_ADDR': '客户端IP地址',
'HTTP_USER_AGENT': '浏览器信息',
'REQUEST_METHOD': '请求方法',
'QUERY_STRING': '查询字符串',
'SCRIPT_NAME': '脚本名称'
}
for var, description in env_vars.items():
value = os.environ.get(var, '未设置')
print(f"<tr><td>{description}</td><td>{value}</td></tr>")
print("</table>")
print("</body>")
print("</html>")在开发CGI程序时,可能会遇到各种错误。使用cgitb模块可以显示详细的错误信息:
#!/usr/bin/python3
import cgi
import cgitb
cgitb.enable() # 启用错误显示
# 你的CGI代码在这里
form = cgi.FieldStorage()
# ...注意:在生产环境中应该关闭cgitb.enable(),避免向用户显示敏感信息。
HTML表单:
<form action="/cgi-bin/guestbook.py" method="post">
<p>姓名: <input type="text" name="name"></p>
<p>留言: <textarea name="message" rows="4" cols="50"></textarea></p>
<input type="submit" value="提交留言">
</form>Python处理程序:
#!/usr/bin/python3
import cgi
import os
from datetime import datetime
def save_message(name, message):
"""保存留言到文件"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open("/var/www/guestbook/messages.txt", "a", encoding="utf-8") as f:
f.write(f"{timestamp} - {name}: {message}\n")
def read_messages():
"""读取所有留言"""
try:
with open("/var/www/guestbook/messages.txt", "r", encoding="utf-8") as f:
return f.readlines()
except FileNotFoundError:
return []
form = cgi.FieldStorage()
name = form.getvalue('name', '').strip()
message = form.getvalue('message', '').strip()
print("Content-type: text/html; charset=utf-8")
print()
print("<html>")
print("<body>")
if name and message:
save_message(name, message)
print("<h1>留言成功!</h1>")
print("<p><a href='/cgi-bin/guestbook.py'>查看所有留言</a></p>")
else:
# 显示留言列表
messages = read_messages()
print("<h1>留言板</h1>")
if messages:
print("<h2>所有留言:</h2>")
print("<ul>")
for msg in messages[-10:]: # 显示最近10条
print(f"<li>{msg}</li>")
print("</ul>")
else:
print("<p>还没有留言</p>")
# 显示留言表单
print("""
<h2>发表留言</h2>
<form method="post">
<p>姓名: <input type="text" name="name"></p>
<p>留言: <textarea name="message" rows="4" cols="50"></textarea></p>
<input type="submit" value="提交留言">
</form>
""")
print("</body>")
print("</html>")HTML:
<form action="/cgi-bin/calculator.py" method="post">
<input type="number" name="num1" step="any" required>
<select name="operator">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">×</option>
<option value="/">÷</option>
</select>
<input type="number" name="num2" step="any" required>
<input type="submit" value="计算">
</form>Python程序:
#!/usr/bin/python3
import cgi
form = cgi.FieldStorage()
try:
num1 = float(form.getvalue('num1', 0))
num2 = float(form.getvalue('num2', 0))
operator = form.getvalue('operator', '+')
if operator == '+':
result = num1 + num2
elif operator == '-':
result = num1 - num2
elif operator == '*':
result = num1 * num2
elif operator == '/':
if num2 == 0:
result = "错误:除数不能为零"
else:
result = num1 / num2
else:
result = "未知运算符"
except ValueError:
result = "错误:请输入有效的数字"
print("Content-type: text/html; charset=utf-8")
print()
print("<html>")
print("<body>")
print(f"<h1>计算结果:{result}</h1>")
print("<p><a href='/calculator.html'>返回计算器</a></p>")
print("</body>")
print("</html>")验证输入:永远不要信任用户输入,要验证所有数据
错误处理:生产环境不要显示详细错误信息
文件权限:确保CGI脚本有正确的执行权限
路径安全:避免使用用户输入直接构造文件路径
如果CGI程序不工作,可以检查:
脚本是否有执行权限(755)
脚本第一行的Python路径是否正确
是否输出了正确的Content-type头部
头部和内容之间是否有空行
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!