什么是CGI
CGI是通用网关接口(Common Gateway Interface)的缩写,它是一种标准协议,用于Web服务器执行外部程序或脚本与Web浏览器进行交互。通过CGI,Web服务器能够动态生成网页内容,处理用户提交的表单数据,并与数据库或其他外部资源进行交互。
基本上,当用户在网页上与Web表单进行交互时,表单数据将被发送到服务器并由CGI程序进行处理。CGI程序可以是任何编程语言编写的脚本(如Perl、Python、PHP、C++等),它接收来自Web服务器的数据,进行逻辑处理,生成新的页面内容,然后将其发送回给用户的浏览器展示。
在简单的例子中,CGI程序可以处理用户输入的数据,比如搜索关键词,然后从数据库中检索相应的结果,最后将结果呈现给用户。这使得网站可以根据用户的请求动态地生成内容,实现高度个性化和互动性。
需要注意的是,虽然CGI在过去广泛使用,但由于性能和安全性方面的考虑,现代的Web开发倾向于使用更先进的技术,如服务器端脚本语言(例如Node.js、Ruby on Rails)、API和框架(如Django、Flask)来取代传统的CGI程序。
Web服务器支持及配置
在你进行CGI编程前,确保您的Web服务器支持CGI及已经配置了CGI的处理程序。
Apache 支持CGI 配置:
设置好CGI目录:
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
所有的HTTP服务器执行CGI程序都保存在一个预先配置的目录。这个目录被称为CGI目录,并按照惯例,它被命名为/var/www/cgi-bin目录。
CGI文件的扩展名为.cgi,python也可以使用.py扩展名。
默认情况下,Linux服务器配置运行的cgi-bin目录中为/var/www。
如果你想指定其他运行CGI脚本的目录,可以修改httpd.conf配置文件,如下所示:
<Directory "/var/www/cgi-bin">AllowOverride NoneOptions +ExecCGIOrder allow,denyAllow from all
</Directory>
在 AddHandler 中添加 .py 后缀,这样我们就可以访问 .py 结尾的 python 脚本文件:
AddHandler cgi-script .cgi .pl .py
第一个CGI程序
以下是一个简单的 Python CGI 程序的例子,它将接收用户输入,并返回一个包含输入内容的网页。在这个例子中,我们假设用户通过表单提交了一个名为 “name” 的字段。
#!/usr/bin/python
print("Content-type: text/html\n") # 输出 HTTP 头部print("<html><head><title>CGI Example</title></head><body>")
print("<h1>CGI Example</h1>")
print("<p>Hello, ")import cgi
form = cgi.FieldStorage() # 获取提交的表单数据
if "name" in form:print(form["name"].value) # 打印用户输入的名字
else: print("Anonymous") # 如果没有输入名字,默认为匿名用户
print("</p>")
print("</body></html>")
在这个例子中,我们首先输出 HTTP 头部,然后打印一个简单的 HTML 页面。接着,我们使用 Python 的 cgi
模块来获取用户提交的表单数据,并根据用户输入的名字进行相应的处理。
要让这个 Python CGI 程序生效,需要确保 Web 服务器已经启用了对 Python CGI 程序的支持。在 Apache 服务器中,你需要将这个 Python 文件放置在适当的 CGI 目录(一般为 /usr/lib/cgi-bin/
目录),并且需要配置 Web 服务器以便它能够执行 Python 脚本。
请注意,上面的示例代码比较简单,并且忽略了安全性和错误处理方面的考虑。在实际开发中,你需要对用户输入进行验证和过滤,以确保安全性。
HTTP头部
HTTP头部(HTTP header)是在发送 HTTP 请求或响应时,用于传输额外信息的部分。它由若干行组成,每行包含一个字段和它的值,字段与值之间用冒号分隔。HTTP 头部通常包含以下几种类型的信息:
-
通用头部(General Headers):这些头部可以出现在请求和响应两种消息中,但与消息内容无关,通常包括 Cache-Control、Connection、Date 等。
-
请求头部(Request Headers):出现在客户端发送的 HTTP 请求中,用于描述客户端要求的资源或者客户端自身的信息,通常包括 Host、User-Agent、Accept 等。
-
响应头部(Response Headers):出现在服务器响应中,用于描述服务器返回的资源信息,通常包括 Server、Content-Type、Content-Length 等。
-
实体头部(Entity Headers):这些头部描述了实体主体部分内容,出现在请求或响应的消息体中,通常包括 Content-Length、Content-Type 等。
下面是一个 HTTP 头部的范例,展示了一些常见的字段:
HTTP/1.1 200 OK
Date: Tue, 24 Aug 2021 06:00:00 GMT
Server: Apache/2.4.6 (CentOS)
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
在这个例子中,第一行是响应状态行;其后的几行是响应头部,包括 Date、Server、Content-Type 和 Content-Length 字段。
HTTP 头部在客户端和服务器之间传递额外的信息,它们对于确定如何处理请求或响应非常重要,并在 Web 通讯过程中发挥着关键的作用。
CGI环境变量
以下是一个简单的CGI脚本输出CGI的环境变量:
实例
#!/usr/bin/python3
import os
print (“Content-type: text/html”)
print ()
print (“<meta charset=“utf-8”>”)
print (“环境变量
”)
print (“
- ”)
for key in os.environ.keys():
print (“ - %30s : %s
- ” % (key,os.environ[key]))
print (“
GET和POST方法
GET 和 POST 方法是 HTTP 协议中用于客户端与服务器进行信息交换的两种基本请求方法。
-
GET 方法:GET 方法用于向服务器请求特定资源,通常用于获取数据。当客户端使用 GET 方法发送请求时,请求中的数据会被附在 URL 后面,以查询字符串的形式发送,例如:
http://www.example.com/path/to/resource?param1=value1¶m2=value2
。由于数据附在 URL 后面,因此 GET 请求的数据长度有限制,并且会被保存在浏览器的历史记录和 Web 服务器的日志文件中。 -
POST 方法:POST 方法通常用于向服务器提交数据,尤其是那些可能包含敏感信息的数据。与 GET 方法不同,POST 请求中的数据不会附在 URL 后面,而是作为请求的正文发送到服务器。因此,POST 请求对发送的数据长度没有限制,并且 POST 请求的数据不会被保存在浏览器历史记录或 Web 服务器日志文件中。
总的来说,GET 方法适合用于从服务器获取资源或数据,而 POST 方法适合用于向服务器提交数据。在实际应用中,需要根据具体的情况选择合适的请求方法。GET 请求通常用于读取数据,而 POST 请求通常用于修改数据或执行涉及状态改变的操作。
需要注意的是,不应该将敏感信息放在 GET 请求的 URL 中,因为这些信息可能会被保存在浏览器历史记录或 Web 服务器日志文件中,并且容易被第三方获取,而 POST 请求的数据传输相对更安全一些。
简单的表单实例:GET方法
下面是一个使用 GET 方法的简单 HTML 表单示例,它将用户输入的数据作为查询字符串附加在 URL 后面,并通过 GET 请求发送给服务器。假设用户输入的数据将用于搜索:
<!DOCTYPE html>
<html>
<head><title>GET 方法表单示例</title>
</head>
<body><h2>使用 GET 方法提交表单</h2><form action="search.php" method="get"><label for="searchQuery">搜索内容:</label><input type="text" id="searchQuery" name="q"><input type="submit" value="搜索"></form>
</body>
</html>
在这个例子中,用户可以在文本框中输入搜索内容,然后点击提交按钮。当用户提交表单时,浏览器会将用户输入的内容作为查询字符串附加在 URL 后面,类似于这样:
http://www.example.com/search.php?q=user_input
其中 search.php
是表单的提交目标页面,?q=user_input
是使用 GET 方法提交的查询字符串,其中 q
是表单字段的名称,user_input
是用户输入的内容。
在服务器端,可以通过对查询字符串进行解析来获取用户输入的数据,从而执行相关操作。例如,使用 PHP 可以通过 $_GET['q']
来获取用户提交的搜索内容。
使用POST方法传递数据
下面是一个使用POST方法传递数据的表单示例。假设这个表单用于用户注册:
<!DOCTYPE html>
<html>
<head><title>使用POST方法提交表单</title>
</head>
<body><h2>用户注册</h2><form action="register.php" method="post"><label for="username">用户名:</label><input type="text" id="username" name="username"><br><br><label for="password">密码:</label><input type="password" id="password" name="password"><br><br><label for="email">邮箱:</label><input type="email" id="email" name="email"><br><br><input type="submit" value="注册"></form>
</body>
</html>
在这个例子中,用户可以填写用户名、密码和邮箱地址,然后点击“注册”按钮。当用户提交表单时,表单数据将作为请求的正文以POST方法发送到服务器端的register.php
页面。
在服务器端的register.php
页面,您可以通过解析POST请求来获取用户输入的用户名、密码和邮箱,并进行相应的处理。例如,使用PHP可以通过$_POST['username']
、$_POST['password']
和$_POST['email']
来获取这些数据。
通过POST方法提交数据可以保护用户输入的隐私信息,因为表单数据不会直接显示在URL中,而是作为请求的一部分发送到服务器端。POST方法通常用于向服务器提交敏感信息或执行对服务器状态产生影响的操作。
通过CGI程序传递checkbox数据
通过 CGI 程序传递复选框(checkbox)数据的基本步骤如下:
- 创建包含复选框的 HTML 表单,让用户进行选择。
- 使用 CGI 程序处理用户提交的表单数据,并从中提取复选框的数值。
- 对于选中的复选框,CGI 程序可以将其值收集起来并进行处理。
以下是一个简单的例子:
HTML 表单代码 form.html
:
<!DOCTYPE html>
<html>
<head><title>通过CGI程序传递checkbox数据</title>
</head>
<body><h2>复选框示例</h2><form action="process_form.cgi" method="post"><input type="checkbox" name="fruit" value="apple"> 苹果<br><input type="checkbox" name="fruit" value="banana"> 香蕉<br><input type="checkbox" name="fruit" value="orange"> 橙子<br><input type="submit" value="提交"></form>
</body>
</html>
CGI 程序 process_form.cgi
(使用 Python 作为示例):
#!/usr/bin/env python
import cgiform = cgi.FieldStorage()print("Content-Type: text/html\n")print("<html><body>")
print("<h2>已选择的水果:</h2>")
if "fruit" in form:if isinstance(form["fruit"], list): # 如果有多个勾选项for value in form.getlist("fruit"):print("<p>{}</p>".format(value))else: # 只有一个勾选项print("<p>{}</p>".format(form["fruit"].value))
else:print("<p>未选择任何水果</p>")
print("</body></html>")
在这个例子中,用户可以勾选苹果、香蕉和橙子,并提交表单。process_form.cgi
CGI 程序将从表单中提取勾选的水果,然后生成一个简单的 HTML 页面来显示用户选择的水果。
通过CGI程序传递 Textarea 数据
通过 CGI 程序传递 Textarea 数据的基本步骤如下:
- 创建包含 Textarea 元素的 HTML 表单,让用户输入文本信息。
- 使用 CGI 程序处理用户提交的表单数据,并提取 Textarea 中的文本内容。
- 对于提取的文本内容,CGI 程序可以对其进行处理或显示。
以下是一个简单的例子:
HTML 表单代码 form.html
:
<!DOCTYPE html>
<html>
<head><title>通过CGI程序传递Textarea数据</title>
</head>
<body><h2>Textarea示例</h2><form action="process_form.cgi" method="post"><label for="message">请输入您的留言:</label><br><textarea id="message" name="message" rows="4" cols="50"></textarea><br><br><input type="submit" value="提交"></form>
</body>
</html>
CGI 程序 process_form.cgi
(使用 Python 作为示例):
#!/usr/bin/env python
import cgiform = cgi.FieldStorage()print("Content-Type: text/html\n")print("<html><body>")
if "message" in form:message = form["message"].valueprint("<h2>您输入的留言是:</h2>")print("<p>{}</p>".format(message))
else:print("<h2>您未输入任何留言</h2>")
print("</body></html>")
在这个例子中,用户可以在 Textarea 中输入留言内容,然后提交表单。process_form.cgi
CGI 程序将提取用户输入的留言内容,并生成一个简单的 HTML 页面来显示用户输入的留言。
通过CGI程序传递下拉数据
通过 CGI 程序传递下拉框(select)数据的基本步骤如下:
- 创建包含下拉框的 HTML 表单,让用户进行选择。
- 使用 CGI 程序处理用户提交的表单数据,并提取下拉框中选定的值。
- 对于选定的值,CGI 程序可以收集并处理它们。
以下是一个简单的例子:
HTML 表单代码 form.html
:
<!DOCTYPE html>
<html>
<head><title>通过CGI程序传递下拉数据</title>
</head>
<body><h2>下拉框示例</h2><form action="process_form.cgi" method="post"><label for="color">请选择您喜欢的颜色:</label><select id="color" name="color"><option value="red">红色</option><option value="blue">蓝色</option><option value="green">绿色</option></select><br><br><input type="submit" value="提交"></form>
</body>
</html>
CGI 程序 process_form.cgi
(使用 Python 作为示例):
#!/usr/bin/env python
import cgiform = cgi.FieldStorage()print("Content-Type: text/html\n")print("<html><body>")
if "color" in form:selected_color = form["color"].valueprint("<h2>您选定的颜色是:</h2>")print("<p>{}</p>".format(selected_color))
else:print("<h2>您未选定任何颜色</h2>")
print("</body></html>")
在这个例子中,用户可以在下拉框中选择喜欢的颜色,然后提交表单。process_form.cgi
CGI 程序将提取用户选择的颜色,并生成一个简单的 HTML 页面来显示用户选择的颜色。
CGI中使用Cookie
在 CGI 中使用 Cookie 可以通过设置响应头来创建和发送 Cookie 给客户端,同时也可以通过请求头从客户端接收和读取 Cookie 的值。下面是一个简单的示例来说明如何在 CGI 中使用 Cookie:
- 创建包含设置 Cookie 的 CGI 程序
set_cookie.cgi
:
#!/usr/bin/env python
print("Set-Cookie: user_id=12345; Expires=Wed, 09 Jun 2023 10:18:14 GMT")
print("Content-Type: text/html\n")print("<html><body>")
print("<h2>Cookie 已设置</h2>")
print("</body></html>")
在这里,Set-Cookie
头部用于设置名为 user_id
的 Cookie,并将其值设置为 12345
,并且设置了过期时间。
- 创建包含读取 Cookie 的 CGI 程序
read_cookie.cgi
:
#!/usr/bin/env python
import osprint("Content-Type: text/html")
print()print("<html><body>")
if "HTTP_COOKIE" in os.environ:cookie_string = os.environ.get("HTTP_COOKIE")cookies = cookie_string.split('; ')for cookie in cookies:name, value = cookie.split('=')print("<p>Cookie 名称:{},值:{}</p>".format(name, value))print("</body></html>")
这个 CGI 程序可以从请求头中读取客户端传递的 Cookie,将其解析并显示出来。
请确保将以上两个 CGI 程序保存为 .cgi
文件,并在支持 CGI 的服务器上运行。第一个程序用于设置 Cookie,第二个程序用于读取和显示 Cookie 的值。根据实际需求和场景,你可以相应地设置和读取更多的 Cookie。
Cookie设置
在 CGI 中使用 Cookie 可以通过设置响应头来创建和发送 Cookie 给客户端,同时也可以通过请求头从客户端接收和读取 Cookie 的值。下面是一个简单的示例来说明如何在 CGI 中使用 Cookie:
- 创建包含设置 Cookie 的 CGI 程序
set_cookie.cgi
:
#!/usr/bin/env python
print("Set-Cookie: user_id=12345; Expires=Wed, 09 Jun 2023 10:18:14 GMT")
print("Content-Type: text/html\n")print("<html><body>")
print("<h2>Cookie 已设置</h2>")
print("</body></html>")
在这里,Set-Cookie
头部用于设置名为 user_id
的 Cookie,并将其值设置为 12345
,并且设置了过期时间。
- 创建包含读取 Cookie 的 CGI 程序
read_cookie.cgi
:
#!/usr/bin/env python
import osprint("Content-Type: text/html")
print()print("<html><body>")
if "HTTP_COOKIE" in os.environ:cookie_string = os.environ.get("HTTP_COOKIE")cookies = cookie_string.split('; ')for cookie in cookies:name, value = cookie.split('=')print("<p>Cookie 名称:{},值:{}</p>".format(name, value))print("</body></html>")
这个 CGI 程序可以从请求头中读取客户端传递的 Cookie,将其解析并显示出来。
请确保将以上两个 CGI 程序保存为 .cgi
文件,并在支持 CGI 的服务器上运行。第一个程序用于设置 Cookie,第二个程序用于读取和显示 Cookie 的值。根据实际需求和场景,你可以相应地设置和读取更多的 Cookie。
检索Cookie信息
在 CGI 中,你可以通过读取客户端请求中的请求头来获取 Cookie 信息。以下是一个用 Python 编写的示例程序,演示了如何在 CGI 中检索和解析客户端传递的 Cookie 信息:
#!/usr/bin/env python
import osprint("Content-Type: text/html")
print()print("<html><body>")
if "HTTP_COOKIE" in os.environ:cookie_string = os.environ.get("HTTP_COOKIE")cookies = cookie_string.split('; ')print("<h2>检索到的Cookie信息:</h2>")for cookie in cookies:name, value = cookie.strip().split('=')print("<p>{}: {}</p>".format(name, value))else:print("<h2>没有找到Cookie信息</h2>")print("</body></html>")
在这个示例中,我们从 os.environ
中获取了名为 HTTP_COOKIE
的请求头部分,并使用它来提取传递的 Cookie 信息。然后将其解析并显示在 HTML 页面上。
请确保将以上代码保存为 .cgi
文件,并在支持 CGI 的服务器上运行。当客户端向该 CGI 程序发出请求时,它会解析并显示客户端发送的所有 Cookie 信息。
文件上传实例
在 Web 开发中,文件上传是一个常见的需求。你可以使用 HTML 表单和后端 CGI 来实现文件上传。以下是一个简单的示例,在这个示例中,我们将展示如何使用 HTML 表单和 Python CGI 来进行文件上传。
首先,让我们创建一个 HTML 表单来允许用户上传文件:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传示例</title>
</head>
<body><h2>文件上传示例</h2><form action="upload_file.cgi" method="post" enctype="multipart/form-data"><input type="file" name="file" /><input type="submit" value="上传" /></form>
</body>
</html>
接下来,创建名为 upload_file.cgi
的 CGI 脚本来处理文件上传:
#!/usr/bin/env python
import cgi
import osform = cgi.FieldStorage()if "file" in form:fileitem = form["file"]if fileitem.file:# 指定文件保存路径filepath = '/path/to/save/' + os.path.basename(fileitem.filename)# 保存文件with open(filepath, 'wb') as f:f.write(fileitem.file.read())print("Content-Type: text/html\n")print("<html><body>")print("<h2>文件上传成功!</h2>")print("<p>文件保存路径:{}</p>".format(filepath))print("</body></html>")else:print("Content-Type: text/html\n")print("<html><body>")print("<h2>没有选择要上传的文件!</h2>")print("</body></html>")
else:print("Content-Type: text/html\n")print("<html><body>")print("<h2>没有找到文件字段!</h2>")print("</body></html>")
确保将 upload_file.cgi
中的 /path/to/save/
替换为服务器上实际用于保存文件的目录路径。
以上代码将允许用户通过 HTML 表单上传文件,并将文件保存到服务器指定的路径中。请注意,对于文件上传功能,需要添加适当的安全措施来验证上传的文件类型、大小以及处理可能存在的安全风险。
文件下载对话框
要在Web页面上实现文件下载对话框,你可以通过HTML超链接和HTTP头部信息来实现。以下是一个简单的示例:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件下载示例</title>
</head>
<body><h2>文件下载示例</h2><a href="download_file.cgi?filename=file.txt">点击这里下载文件</a>
</body>
</html>
在上面的示例中,我们创建了一个包含超链接的HTML页面,当用户点击超链接时,它将调用名为 download_file.cgi
的CGI脚本,并传递了要下载的文件名作为参数。
下面是 download_file.cgi
的代码示例,它将发送HTTP头部信息告诉浏览器响应内容是一个文件,并指定该文件的名称:
#!/usr/bin/env pythonprint("Content-Type: application/octet-stream")
print("Content-Disposition: attachment; filename=file.txt")
print()
with open('/path/to/your/file/file.txt', 'rb') as f:print(f.read())
在上面的示例中,download_file.cgi
CGI脚本发送了HTTP头部信息告诉浏览器响应内容是一个文件(MIME类型为application/octet-stream),并且通过 Content-Disposition 头部指定了使用附件方式下载,并指定了文件名为 file.txt。接着,在空行后输出了文件的内容。
请注意,你需要将 /path/to/your/file/file.txt
替换为实际文件的路径。
这样,当用户点击链接时,浏览器会显示文件下载对话框,提示用户下载文件。
关注我,不迷路,共学习,同进步
关注我,不迷路,共学习,同进步