Programmation CGI Python3
Qu'est-ce que CGI
CGI est actuellement maintenu par NCSA. NCSA définit CGI comme suit :
CGI (Common Gateway Interface), interface de passerelle commune, c'est un programme, s'exécute sur le serveur tel que : Serveur HTTP, fournissant une interface avec la page HTML du client.
Navigation Web
Afin de mieux comprendre le fonctionnement de CGI, nous pouvons commencer par le processus consistant à cliquer sur un lien ou une URL sur une page Web :
1. Utilisez votre navigateur pour accéder à l'URL et vous connecter au serveur Web HTTP.
2. Après avoir reçu les informations de la demande, le serveur Web analysera l'URL et vérifiera si le fichier consulté existe sur le serveur. Si le fichier existe, renverra le contenu du fichier. sinon un message d'erreur sera renvoyé.
3. Le navigateur reçoit des informations du serveur et affiche le fichier ou le message d'erreur reçu.
Le programme CGI peut être un script Python, un script PERL, un script SHELL, un programme C ou C++, etc.
Schéma d'architecture CGI
Prise en charge et configuration du serveur Web
Avant de faire de la programmation CGI, assurez-vous de Le serveur Web prend en charge CGI et dispose de gestionnaires CGI configurés.
Apache prend en charge la configuration CGI :
Configurez le répertoire CGI :
ScriptAlias /cgi-bin/ /var/www/cgi-bin/
Tous les programmes CGI d'exécution du serveur HTTP sont enregistrés dans un répertoire préconfiguré. Ce répertoire est appelé répertoire CGI, et par convention, il est nommé /var/www/cgi-bin.
L'extension des fichiers CGI est .cgi, et python peut également utiliser l'extension .py.
Par défaut, le répertoire cgi-bin dans lequel le serveur Linux est configuré pour s'exécuter est /var/www.
Si vous souhaitez spécifier d'autres répertoires pour exécuter les scripts CGI, vous pouvez modifier le fichier de configuration httpd.conf comme suit :
<Directory "/var/www/cgi-bin"> AllowOverride None Options +ExecCGI Order allow,deny Allow from all </Directory>
Ajoutez le suffixe .py dans AddHandler pour que nous puissions y accéder .fichier de script python se terminant par py :
AddHandler cgi-script .cgi .pl .py
Le premier programme CGI
Nous utilisons Python pour créer le premier programme CGI, le nom du fichier est hello.py et le fichier est situé dans /var/ Dans le répertoire www/cgi-bin, le contenu est le suivant :
#!/usr/bin/python3 print ("Content-type:text/html") print () # 空行,告诉服务器结束头部 print ('<html>') print ('<head>') print ('<meta charset="utf-8">') print ('<title>Hello Word - 我的第一个 CGI 程序!</title>') print ('</head>') print ('<body>') print ('<h2>Hello Word! 我是来自php中文网的第一CGI程序</h2>') print ('</body>') print ('</html>')
Après avoir enregistré le fichier, modifiez hello.py et modifiez les permissions du fichier à 755 :
chmod 755 hello.py
Le programme ci-dessus affichera les résultats suivants lorsqu'il sera accédé par le navigateur :
Le script hello.py est un simple script Python. Le contenu de sortie de la première ligne du. Le script "Content-type: text/html" est envoyé au navigateur et notifié au navigateur. Le type de contenu affiché par le navigateur est "text/html".
Utilisez print pour afficher une ligne vierge pour indiquer au serveur de terminer les informations d'en-tête.
En-tête HTTP
Le "Content-type: text/html" dans le contenu du fichier hello.py fait partie de l'en-tête HTTP, qui sera envoyé au navigateur pour l'indiquer le navigateur Le type de contenu du fichier serveur.
Le format de l'en-tête HTTP est le suivant :
HTTP 字段名: 字段内容
Par exemple :
Content-type: text/html
Le tableau suivant présente les informations couramment utilisées dans les en-têtes HTTP des programmes CGI :
头 | 描述 |
---|---|
Content-type: | 请求的与实体对应的MIME信息。例如: Content-type:text/html |
Expires: Date | 响应过期的日期和时间 |
Location: URL | 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 |
Last-modified: Date | 请求资源的最后修改时间 |
Content-length: N | 请求的内容长度 |
Set-Cookie: String | 设置Http Cookie |
Variables d'environnement CGI
Tous les programmes CGI reçoivent les variables d'environnement suivantes, qui jouent un rôle important dans les programmes CGI :
变量名 | 描述 |
---|---|
CONTENT_TYPE | 这个环境变量的值指示所传递来的信息的MIME类型。目前,环境变量CONTENT_TYPE一般都是:application/x-www-form-urlencoded,他表示数据来自于HTML表单。 |
CONTENT_LENGTH | 如果服务器与CGI程序信息的传递方式是POST,这个环境变量即使从标准输入STDIN中可以读到的有效数据的字节数。这个环境变量在读取所输入的数据时必须使用。 |
HTTP_COOKIE | 客户机内的 COOKIE 内容。 |
HTTP_USER_AGENT | 提供包含了版本数或其他专有数据的客户浏览器信息。 |
PATH_INFO | 这个环境变量的值表示紧接在CGI程序名之后的其他路径信息。它常常作为CGI程序的参数出现。 |
QUERY_STRING | 如果服务器与CGI程序信息的传递方式是GET,这个环境变量的值即使所传递的信息。这个信息经跟在CGI程序名的后面,两者中间用一个问号'?'分隔。 |
REMOTE_ADDR | 这个环境变量的值是发送请求的客户机的IP地址,例如上面的192.168.1.67。这个值总是存在的。而且它是Web客户机需要提供给Web服务器的唯一标识,可以在CGI程序中用它来区分不同的Web客户机。 |
REMOTE_HOST | 这个环境变量的值包含发送CGI请求的客户机的主机名。如果不支持你想查询,则无需定义此环境变量。 |
REQUEST_METHOD | 提供脚本被调用的方法。对于使用 HTTP/1.0 协议的脚本,仅 GET 和 POST 有意义。 |
SCRIPT_FILENAME | CGI脚本的完整路径 |
SCRIPT_NAME | CGI脚本的的名称 |
SERVER_NAME | 这是你的 WEB 服务器的主机名、别名或IP地址。 |
SERVER_SOFTWARE | 这个环境变量的值包含了调用CGI程序的HTTP服务器的名称和版本号。例如,上面的值为Apache/2.2.14(Unix) |
Ce qui suit est un simple script CGI qui génère des variables d'environnement CGI :
#!/usr/bin/python3 import os print ("Content-type: text/html") print () print ("<meta charset=\"utf-8\">") print ("<b>环境变量</b><br>") print ("<ul>") for key in os.environ.keys(): print ("<li><span style='color:green'>%30s </span> : %s </li>" % (key,os.environ[key])) print ("</ul>")
Enregistrez les points ci-dessus sous test.py et modifiez les autorisations du fichier à 755. Les résultats de l'exécution sont les suivants :
Méthodes GET et POST
Le client du navigateur transmet les informations au serveur via deux méthodes, les deux méthodes sont la méthode GET et la méthode POST.
Utilisez la méthode GET pour transmettre des données
La méthode GET envoie les informations utilisateur codées au serveur. Les informations sur les données sont incluses dans l'URL de la page demandée, séparées par "?", comme indiqué ci-dessous :
http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2Quelques autres remarques sur les requêtes GET :
Les requêtes GET peuvent être mises en cache
Les requêtes GET restent dans l'historique du navigateur
Les requêtes GET peuvent être mises en favoris
Les requêtes GET ne doivent pas être utilisées lors du traitement de données sensibles
Demandes GET avoir des restrictions de longueur
Les requêtes GET ne doivent être utilisées que pour récupérer des données
Exemple d'URL simple : méthode GET
Ce qui suit est une URL simple qui utilise la méthode GET pour envoyer deux paramètres au programme hello_get.py :
/cgi-bin/test.py?name=php中文网&url=http://www.php.cn
Voici le code du fichier hello_get.py :
#!/usr/bin/python3 # CGI处理模块 import cgi, cgitb # 创建 FieldStorage 的实例化 form = cgi.FieldStorage() # 获取数据 site_name = form.getvalue('name') site_url = form.getvalue('url') print ("Content-type:text/html") print () print ("<html>") print ("<head>") print ("<meta charset=\"utf-8\">") print ("<title>php中文网 CGI 测试实例</title>") print ("</head>") print ("<body>") print ("<h2>%s官网:%s</h2>" % (site_name, site_url)) print ("</body>") print ("</html>")
Modifier hello_get après avoir enregistré le fichier.py, modifiez l'autorisation du fichier à 755 :
chmod 755 hello_get.py
Résultat de sortie de la requête du navigateur :
Exemple de formulaire simple : méthode GET
ci-dessous Il s'agit d'un formulaire HTML qui utilise la méthode GET pour envoyer deux données au serveur. Le script du serveur soumis est également le fichier hello_get.py Le code hello_get.html est le suivant :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/hello_get.py" method="get"> 站点名称: <input type="text" name="name"> <br /> 站点 URL: <input type="text" name="url" /> <input type="submit" value="提交" /> </form> </body> </html>
Par défaut. , le répertoire cgi-bin ne peut être stocké que pour le fichier script, nous stockons hello_get.html dans le répertoire test et modifions la permission du fichier à 755 :
chmod 755 hello_get.html
La démo Gif est la suivante :
Utiliser la méthode POST pour transférer des données
L'utilisation de la méthode POST pour transférer des données vers le serveur est plus sécurisée et fiable. Certaines informations sensibles telles que les mots de passe des utilisateurs doivent utiliser POST pour. transférer des données.
Ce qui suit est hello_get.py, qui peut également traiter les données du formulaire POST soumises par le navigateur :
#!/usr/bin/python3 # CGI处理模块 import cgi, cgitb # 创建 FieldStorage 的实例化 form = cgi.FieldStorage() # 获取数据 site_name = form.getvalue('name') site_url = form.getvalue('url') print ("Content-type:text/html") print () print ("<html>") print ("<head>") print ("<meta charset=\"utf-8\">") print ("<title>php中文网 CGI 测试实例</title>") print ("</head>") print ("<body>") print ("<h2>%s官网:%s</h2>" % (site_name, site_url)) print ("</body>") print ("</html>")
Ce qui suit est le formulaire via la méthode POST (method="post" ) Soumettez les données au script du serveur hello_get.py :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/hello_get.py" method="post"> 站点名称: <input type="text" name="name"> <br /> 站点 URL: <input type="text" name="url" /> <input type="submit" value="提交" /> </form> </body> </html> </form>
La démonstration Gif est la suivante :
Transmettre les données de la case à cocher via le programme CGI
La case à cocher est utilisée pour soumettre une ou plusieurs données d'option. Le code HTML est le suivant :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/checkbox.py" method="POST" target="_blank"> <input type="checkbox" name="php" value="on" /> php中文网 <input type="checkbox" name="google" value="on" /> Google <input type="submit" value="选择站点" /> </form> </body> </html>
Voici le code du fichier checkbox.py :
#!/usr/bin/python3 # 引入 CGI 处理模块 import cgi, cgitb # 创建 FieldStorage的实例 form = cgi.FieldStorage() # 接收字段数据 if form.getvalue('google'): google_flag = "是" else: google_flag = "否" if form.getvalue('php'): php_flag = "是" else: php_flag = "否" print ("Content-type:text/html") print () print ("<html>") print ("<head>") print ("<meta charset=\"utf-8\">") print ("<title>php中文网 CGI 测试实例</title>") print ("</head>") print ("<body>") print ("<h2> php中文网是否选择了 : %s</h2>" % php_flag) print ("<h2> Google 是否选择了 : %s</h2>" % google_flag) print ("</body>") print ("</html>")
Modifier la case à cocher. Autorisations .py :
chmod 755 checkbox.py
Démo Gif d'accès au navigateur :
Transférer les données Radio via le programme CGI
Radio ne transmet qu'une seule donnée au serveur, le code HTML est le suivant :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/radiobutton.py" method="post" target="_blank"> <input type="radio" name="site" value="php" /> php中文网 <input type="radio" name="site" value="google" /> Google <input type="submit" value="提交" /> </form> </body> </html>
radiobutton.py Le code du script est le suivant :
#!/usr/bin/python3 # 引入 CGI 处理模块 import cgi, cgitb # 创建 FieldStorage的实例 form = cgi.FieldStorage() # 接收字段数据 if form.getvalue('site'): site = form.getvalue('site') else: site = "提交数据为空" print ("Content-type:text/html") print () print ("<html>") print ("<head>") print ("<meta charset=\"utf-8\">") print ("<title>php中文网 CGI 测试实例</title>") print ("</head>") print ("<body>") print ("<h2> 选中的网站是 %s</h2>" % site) print ("</body>") print ("</html>")
Modifier les autorisations du bouton radio .py :
chmod 755 radiobutton.py
Accès au navigateur Image de démonstration Gif :
Transférer les données Textarea via le programme CGI
Textarea transfère plusieurs messages vers le serveur Données de ligne, le code HTML est le suivant :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/textarea.py" method="post" target="_blank"> <textarea name="textcontent" cols="40" rows="4"> 在这里输入内容... </textarea> <input type="submit" value="提交" /> </form> </body> </html>
textarea.py Le code du script est le suivant :
#!/usr/bin/python3 # 引入 CGI 处理模块 import cgi, cgitb # 创建 FieldStorage的实例 form = cgi.FieldStorage() # 接收字段数据 if form.getvalue('textcontent'): text_content = form.getvalue('textcontent') else: text_content = "没有内容" print ("Content-type:text/html") print () print ("<html>") print ("<head>") print ("<meta charset=\"utf-8\">") print ("<title>php中文网 CGI 测试实例</title>") print ("</head>") print ("<body>") print ("<h2> 输入的内容是:%s</h2>" % text_content) print ("</body>") print ("</html>")
Modifier textarea.py Autorisations :
chmod 755 textarea.py
Image de démonstration Gif d'accès au navigateur :
Transmettez les données déroulantes via le programme CGI.
Le code de la liste déroulante HTML est le suivant :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form action="/cgi-bin/dropdown.py" method="post" target="_blank"> <select name="dropdown"> <option value="php" selected>php中文网</option> <option value="google">Google</option> </select> <input type="submit" value="提交"/> </form> </body> </html>
Le code du script dropdown.py est le suivant :
#!/usr/bin/python3 # 引入 CGI 处理模块 import cgi, cgitb # 创建 FieldStorage的实例 form = cgi.FieldStorage() # 接收字段数据 if form.getvalue('dropdown'): dropdown_value = form.getvalue('dropdown') else: dropdown_value = "没有内容" print ("Content-type:text/html") print () print ("<html>") print ("<head>") print ("<meta charset=\"utf-8\">") print ("<title>php中文网 CGI 测试实例</title>") print ("</head>") print ("<body>") print ("<h2> 选中的选项是:%s</h2>" % dropdown_value) print ("</body>") print ("</html>")
Modifier les autorisations dropdown.py :
chmod 755 dropdown.py
Navigateur Visitez l'image de démonstration Gif :
Utilisation des cookies en CGI
Un gros inconvénient du protocole http est qu'il ne juge pas l'identité de l'utilisateur. Cela apporte de grands inconvénients aux programmeurs. L’émergence de la fonction cookie pallie cette lacune.
Le cookie consiste à écrire des données d'enregistrement sur le disque dur du client via le navigateur du client lorsque le client accède au script. , les informations sur les données seront récupérées la prochaine fois que le client accédera au script, afin d'atteindre la fonction de discrimination d'identité. Les cookies sont souvent utilisés dans la vérification de l'identité.
Syntaxe du cookie
Le cookie http est envoyé via l'en-tête http, qui est antérieur au transfert de fichier. La syntaxe de set-cookie dans l'en-tête est la suivante :
Set-cookie:name=name;expires=date;path=path;domain=domain;secure<🎜. >
name=name : Vous devez définir la valeur du cookie (le nom ne peut pas utiliser ";" et ","), comment many Utilisez ";" pour séparer les valeurs de nom, par exemple : name1=name1;name2=name2;name3=name3.
expires=date : Durée de validité des cookies, format : expires="Wdy,DD-Mon-YYYY HH:MM:SS"
path=path : Définissez le chemin pris en charge par les cookies. Si le chemin est un chemin, le cookie sera dedans. répertoire. Valable pour tous les fichiers et sous-répertoires, par exemple : path="/cgi-bin/". Si le chemin est un fichier, le cookie sera valide pour ce fichier, par exemple : path="/cgi-bin/cookie. cgi".
domain=domain : Nom de domaine valide pour les cookies, par exemple : domain="www.php.cn"
sécurisé : Si ce flag est donné, cela signifie que le cookie ne peut être délivré que via le serveur https du protocole SSL.
- La réception des cookies est obtenue en définissant la variable d'environnement HTTP_COOKIE. Les programmes CGI peuvent obtenir des informations sur les cookies en récupérant cette variable.
Paramètres des cookies
Le paramétrage des cookies est très simple et le cookie sera envoyé séparément dans l'en-tête http. L'exemple suivant définit le nom et expire dans le cookie :
#!/usr/bin/python3 # print ('Content-Type: text/html') print ('Set-Cookie: name="php中文网";expires=Wed, 28 Aug 2016 18:30:00 GMT') print () print (""" <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <h1>Cookie set OK!</h1> </body> </html> """)
Enregistrez le code ci-dessus dans cookie_set.py et modifiez les autorisations cookie_set.py :
chmod 755 cookie_set.py
L'exemple ci-dessus utilise le Set- Informations d'en-tête du cookie Pour définir les informations du cookie, d'autres attributs du cookie sont définis dans les options facultatives, tels que le délai d'expiration Expire, le nom de domaine et le chemin. Cette information est définie avant « Content-type:text/html ».
Récupérer les informations sur les cookies
La page de récupération des informations sur les cookies est très simple. Les informations sur les cookies sont stockées dans la variable d'environnement CGI HTTP_COOKIE. Le format de stockage est le suivant :
key1=value1;key2=value2;key3=value3....<. 🎜>Ce qui suit est un programme CGI simple pour récupérer les informations sur les cookies :
#!/usr/bin/python3 # 导入模块 import os import Cookie print ("Content-type: text/html") print () print (""" <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <h1>读取cookie信息</h1> """) if 'HTTP_COOKIE' in os.environ: cookie_string=os.environ.get('HTTP_COOKIE') c=Cookie.SimpleCookie() c.load(cookie_string) try: data=c['name'].value print ("cookie data: "+data+"<br>") except KeyError: print ("cookie 没有设置或者已过去<br>") print (""" </body> </html> """)Enregistrez le code ci-dessus dans cookie_get.py et modifiez les autorisations cookie_get.py :
chmod 755 cookie_get.pyLa couleur des paramètres de cookie ci-dessus est Gif est le suivant : Exemple de téléchargement de fichiersLe formulaire de configuration HTML pour le téléchargement de fichiers doit définir l'attribut
enctype sur multipart/form-data , le code est le suivant :
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <form enctype="multipart/form-data" action="/cgi-bin/save_file.py" method="post"> <p>选中文件: <input type="file" name="filename" /></p> <p><input type="submit" value="上传" /></p> </form> </body> </html>save_file.py Le code du fichier script est le suivant :
#!/usr/bin/python3 import cgi, os import cgitb; cgitb.enable() form = cgi.FieldStorage() # 获取文件名 fileitem = form['filename'] # 检测文件是否上传 if fileitem.filename: # 设置文件路径 fn = os.path.basename(fileitem.filename) open('/tmp/' + fn, 'wb').write(fileitem.file.read()) message = '文件 "' + fn + '" 上传成功' else: message = '文件没有上传' print ("""\ Content-Type: text/html\n <html> <head> <meta charset="utf-8"> <title>php中文网(php.cn)</title> </head> <body> <p>%s</p> </body> </html> """ % (message,))Enregistrez le code ci-dessus dans save_file.py et modifiez Autorisations save_file.py :
chmod 755 save_file.pyLe Gif de couleur du paramètre de cookie ci-dessus est le suivant : Si le système que vous utilisez est Unix/Linux, vous devez remplacez le séparateur de fichiers. Sous la fenêtre, il vous suffit d'utiliser l'instruction open() :
fn = os.path.basename(fileitem.filename.replace("\", "/" ))
Boîte de dialogue de téléchargement de fichierNous créons d'abord le fichier foo.txt dans le répertoire courant. pour télécharger le programme. Le téléchargement de fichiers est réalisé en définissant les informations d'en-tête HTTP. Le code de fonction est le suivant :
#!/usr/bin/python3 # HTTP 头部 print ("Content-Disposition: attachment; filename=\"foo.txt\"") print () # 打开文件 fo = open("foo.txt", "rb") str = fo.read(); print (str) # 关闭文件 fo.close().