Python 3 - Программирование CGI

Общий интерфейс шлюза или CGI - это набор стандартов, которые определяют, как происходит обмен информацией между веб-сервером и настраиваемым сценарием. Спецификации CGI в настоящее время поддерживаются NCSA.

Что такое CGI?

  • Общий интерфейс шлюза, или CGI, является стандартом для программ внешнего шлюза для взаимодействия с информационными серверами, такими как серверы HTTP.

  • Текущая версия - CGI / 1.1, а CGI / 1.2 находится в стадии разработки.

Просмотр веб-страниц

Чтобы понять концепцию CGI, давайте посмотрим, что происходит, когда мы щелкаем гиперссылку для просмотра определенной веб-страницы или URL-адреса.

  • Ваш браузер связывается с веб-сервером HTTP и запрашивает URL-адрес, то есть имя файла.

  • Веб-сервер анализирует URL-адрес и ищет имя файла. Если он находит этот файл, он отправляет его обратно в браузер, в противном случае отправляет сообщение об ошибке, указывающее, что вы запросили не тот файл.

  • Веб-браузер принимает ответ от веб-сервера и отображает полученный файл или сообщение об ошибке.

Однако можно настроить HTTP-сервер так, чтобы всякий раз, когда запрашивается файл в определенном каталоге, этот файл не отправлялся обратно; вместо этого он выполняется как программа, и все, что выводит эта программа, отправляется обратно в ваш браузер для отображения. Эта функция называется Common Gateway Interface или CGI, а программы называются сценариями CGI. Эти программы CGI могут быть скриптом Python, скриптом PERL, скриптом оболочки, программой C или C ++ и т. Д.

Схема архитектуры CGI

Поддержка и настройка веб-сервера

Прежде чем приступить к программированию CGI, убедитесь, что ваш веб-сервер поддерживает CGI и настроен для обработки программ CGI. Все программы CGI, выполняемые HTTP-сервером, хранятся в предварительно настроенном каталоге. Этот каталог называется CGI Directory и по соглашению называется / var / www / cgi-bin. По соглашению файлы CGI имеют расширение.cgi, но вы можете хранить свои файлы с расширением python .py также.

По умолчанию сервер Linux настроен на запуск только сценариев в каталоге cgi-bin в / var / www. Если вы хотите указать любой другой каталог для запуска ваших сценариев CGI, прокомментируйте следующие строки в файле httpd.conf -

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from all
</Directory>

<Directory "/var/www/cgi-bin">
Options All
</Directory>

Здесь мы предполагаем, что у вас есть запущенный и успешно работающий веб-сервер, и вы можете запускать любую другую программу CGI, такую ​​как Perl или Shell и т. Д.

Первая программа CGI

Вот простая ссылка, которая связана со сценарием CGI с именем hello.py . Этот файл хранится в каталоге / var / www / cgi-bin и имеет следующее содержимое. Перед запуском вашей программы CGI убедитесь, что у вас есть режим изменения файла, используяchmod 755 hello.py Команда UNIX для создания исполняемого файла.

#!/usr/bin/python

print ("Content-type:text/html\r\n\r\n")
print ('<html>')
print ('<head>')
print ('<title>Hello Word - First CGI Program</title>')
print ('</head>')
print ('<body>')
print ('<h2>Hello Word! This is my first CGI program</h2>')
print ('</body>')
print ('</html>')

Note- В первой строке скрипта должен быть указан путь к исполняемому файлу Python. В Linux это должно быть #! / Usr / bin / python3

Введите следующий URL в вашем браузере

http://localhost:8080/cgi-bin/hello.py

Hello Word! This is my first CGI program

Этот сценарий hello.py представляет собой простой сценарий Python, который записывает свой вывод в файл STDOUT, то есть на экран. Доступна одна важная и дополнительная функция - первая строка для печати.Content-type:text/html\r\n\r\n. Эта строка отправляется обратно в браузер, и в ней указывается тип содержимого, отображаемого на экране браузера.

К настоящему времени вы, должно быть, поняли базовую концепцию CGI и можете писать много сложных программ CGI, используя Python. Этот сценарий может взаимодействовать с любой другой внешней системой, а также для обмена информацией, такой как СУБД.

Заголовок HTTP

Линия Content-type:text/html\r\n\r\nявляется частью HTTP-заголовка, который отправляется браузеру для понимания содержимого. Весь HTTP-заголовок будет в следующей форме -

HTTP Field Name: Field Content

For Example
Content-type: text/html\r\n\r\n

Есть несколько других важных заголовков HTTP, которые вы часто будете использовать в программировании CGI.

Sr.No. Заголовок и описание
1

Content-type:

Строка MIME, определяющая формат возвращаемого файла. Пример: Content-type: text / html

2

Expires: Date

Дата, когда информация становится недействительной. Он используется браузером, чтобы решить, когда необходимо обновить страницу. Допустимая строка даты имеет формат 01 января 1998 12:00:00 GMT.

3

Location: URL

URL-адрес, который возвращается вместо запрашиваемого URL-адреса. Вы можете использовать это поле для перенаправления запроса в любой файл.

4

Last-modified: Date

Дата последней модификации ресурса.

5

Content-length: N

Длина возвращаемых данных в байтах. Браузер использует это значение, чтобы сообщить приблизительное время загрузки файла.

6

Set-Cookie: String

Установите cookie, передаваемый через строку

Переменные среды CGI

Все программы CGI имеют доступ к следующим переменным среды. Эти переменные играют важную роль при написании любой программы CGI.

Sr.No. Имя и описание переменной
1

CONTENT_TYPE

Тип данных содержимого. Используется, когда клиент отправляет прикрепленный контент на сервер. Например, загрузка файла.

2

CONTENT_LENGTH

Длина информации запроса. Доступно только для запросов POST.

3

HTTP_COOKIE

Возвращает установленные файлы cookie в виде пары ключ и значение.

4

HTTP_USER_AGENT

Поле заголовка запроса User-Agent содержит информацию о пользовательском агенте, создавшем запрос. Это имя веб-браузера.

5

PATH_INFO

Путь к сценарию CGI.

6

QUERY_STRING

Информация в кодировке URL, отправляемая с запросом метода GET.

7

REMOTE_ADDR

IP-адрес удаленного хоста, отправляющего запрос. Это полезно для ведения журнала или для аутентификации.

8

REMOTE_HOST

Полное имя хоста, выполняющего запрос. Если эта информация недоступна, то для получения IR-адреса можно использовать REMOTE_ADDR.

9

REQUEST_METHOD

Метод, использованный для отправки запроса. Наиболее распространены методы GET и POST.

10

SCRIPT_FILENAME

Полный путь к сценарию CGI.

11

SCRIPT_NAME

Имя сценария CGI.

12

SERVER_NAME

Имя хоста или IP-адрес сервера

13

SERVER_SOFTWARE

Название и версия программного обеспечения, на котором работает сервер.

Вот небольшая программа CGI для вывода всех переменных CGI. Щелкните эту ссылку, чтобы увидеть результат Получить среду

#!/usr/bin/python

import os

print ("Content-type: text/html\r\n\r\n");
print ("<font size=+1>Environment</font><\br>");
for param in os.environ.keys():
   print ("<b>%20s</b>: %s<\br>" % (param, os.environ[param]))

Методы GET и POST

Вы, должно быть, сталкивались со многими ситуациями, когда вам нужно было передать некоторую информацию из вашего браузера на веб-сервер и, в конечном итоге, в вашу программу CGI. Чаще всего браузер использует два метода, два из которых передают эту информацию веб-серверу. Это методы GET и POST.

Передача информации с использованием метода GET

Метод GET отправляет закодированную информацию о пользователе, добавленную к запросу страницы. Страница и закодированная информация разделяются знаком? характер следующим образом -

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
  • Метод GET - это метод по умолчанию для передачи информации из браузера на веб-сервер, и он создает длинную строку, которая появляется в поле Location: вашего браузера.

  • Никогда не используйте метод GET, если у вас есть пароль или другая конфиденциальная информация для передачи на сервер.

  • Метод GET имеет ограничение по размеру: в строке запроса можно отправить только 1024 символа.

  • Метод GET отправляет информацию с помощью заголовка QUERY_STRING и будет доступен в вашей программе CGI через переменную среды QUERY_STRING.

Вы можете передать информацию, просто объединив пары ключ и значение вместе с любым URL-адресом, или вы можете использовать теги HTML <FORM> для передачи информации с помощью метода GET.

Пример простого URL: метод получения

Вот простой URL-адрес, который передает два значения программе hello_get.py с помощью метода GET.

/cgi-bin/hello_get.py?first_name=ZARA&last_name=ALI

Ниже hello_get.pyсценарий для обработки ввода данных веб-браузером. Мы собираемся использоватьcgi модуль, который позволяет очень легко получить доступ к переданной информации -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print ("Content-type:text/html\r\n\r\n")
print ("<html>")
print ("<head>")
print ("<title>Hello - Second CGI Program</title>")
print ("</head>")
print ("<body>")
print ("<h2>Hello %s %s</h2>" % (first_name, last_name))
print ("</body>")
print ("</html>")

Это даст следующий результат -

Hello ZARA ALI

Простой пример FORM: метод GET

В этом примере передаются два значения с использованием HTML FORM и кнопки отправки. Мы используем тот же CGI-скрипт hello_get.py для обработки этого ввода.

<form action = "/cgi-bin/hello_get.py" method = "get">
   First Name: <input type = "text" name = "first_name">  <br />

   Last Name: <input type = "text" name = "last_name" />
   <input type = "submit" value = "Submit" />
</form>

Вот фактический результат вышеприведенной формы, вы вводите имя и фамилию, а затем нажимаете кнопку отправки, чтобы увидеть результат.

Передача информации с использованием метода POST

Обычно более надежным методом передачи информации программе CGI является метод POST. Это упаковывает информацию точно так же, как методы GET, но вместо того, чтобы отправлять ее в виде текстовой строки после символа? в URL-адресе он отправляет его как отдельное сообщение. Это сообщение поступает в сценарий CGI в виде стандартного ввода.

Ниже приведен тот же скрипт hello_get.py, который обрабатывает GET, а также метод POST.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Hello - Second CGI Program</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"

Давайте снова возьмем тот же пример, что и выше, который передает два значения с помощью HTML FORM и кнопки отправки. Мы используем тот же CGI-скрипт hello_get.py для обработки этого ввода.

<form action = "/cgi-bin/hello_get.py" method = "post">
First Name: <input type = "text" name = "first_name"><br />
Last Name: <input type = "text" name = "last_name" />

<input type = "submit" value = "Submit" />
</form>

Вот фактический результат вышеуказанной формы. Вы вводите имя и фамилию, а затем нажимаете кнопку отправки, чтобы увидеть результат.

Передача данных флажка в программу CGI

Флажки используются, когда требуется выбрать более одного параметра.

Вот пример HTML-кода для формы с двумя флажками -

<form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank">
   <input type = "checkbox" name = "maths" value = "on" /> Maths
   <input type = "checkbox" name = "physics" value = "on" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

Результатом этого кода является следующая форма -

Ниже приведен сценарий checkbox.cgi для обработки ввода, предоставленного веб-браузером для кнопки флажка.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('maths'):
   math_flag = "ON"
else:
   math_flag = "OFF"

if form.getvalue('physics'):
   physics_flag = "ON"
else:
   physics_flag = "OFF"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Checkbox - Third CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> CheckBox Maths is : %s</h2>" % math_flag
print "<h2> CheckBox Physics is : %s</h2>" % physics_flag
print "</body>"
print "</html>"

Передача данных радиокнопки в программу CGI

Радиокнопки используются, когда требуется выбрать только один вариант.

Вот пример HTML-кода для формы с двумя переключателями -

<form action = "/cgi-bin/radiobutton.py" method = "post" target = "_blank">
   <input type = "radio" name = "subject" value = "maths" /> Maths
   <input type = "radio" name = "subject" value = "physics" /> Physics
   <input type = "submit" value = "Select Subject" />
</form>

Результатом этого кода является следующая форма -

Ниже приведен скрипт radiobutton.py для обработки ввода, предоставленного веб-браузером для переключателя -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('subject'):
   subject = form.getvalue('subject')
else:
   subject = "Not set"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Radio - Fourth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Передача данных текстовой области в программу CGI

Элемент TEXTAREA используется, когда многострочный текст должен быть передан программе CGI.

Вот пример HTML-кода для формы с полем TEXTAREA -

<form action = "/cgi-bin/textarea.py" method = "post" target = "_blank">
   <textarea name = "textcontent" cols = "40" rows = "4">
      Type your text here...
   </textarea>
   <input type = "submit" value = "Submit" />
</form>

Результатом этого кода является следующая форма -

Ниже приведен сценарий textarea.cgi для обработки ввода, предоставленного веб-браузером -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Entered Text Content is %s</h2>" % text_content
print "</body>"

Передача данных раскрывающегося списка в программу CGI

Выпадающий список используется, когда у нас много доступных вариантов, но будут выбраны только один или два.

Вот пример HTML-кода для формы с одним раскрывающимся списком -

<form action = "/cgi-bin/dropdown.py" method = "post" target = "_blank">
   <select name = "dropdown">
      <option value = "Maths" selected>Maths</option>
      <option value = "Physics">Physics</option>
   </select>
   <input type = "submit" value = "Submit"/>
</form>

Результатом этого кода является следующая форма -

Ниже приведен сценарий dropdown.py для обработки ввода данных веб-браузером.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('dropdown'):
   subject = form.getvalue('dropdown')
else:
   subject = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Dropdown Box - Sixth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Использование файлов cookie в CGI

Протокол HTTP - это протокол без сохранения состояния. Для коммерческого веб-сайта требуется поддерживать информацию о сеансе между разными страницами. Например, регистрация одного пользователя заканчивается после заполнения множества страниц. Как сохранить информацию о сеансе пользователя на всех веб-страницах?

Во многих ситуациях использование файлов cookie является наиболее эффективным методом запоминания и отслеживания предпочтений, покупок, комиссионных и другой информации, необходимой для лучшего взаимодействия с посетителями или статистики сайта.

Как это устроено?

Ваш сервер отправляет некоторые данные в браузер посетителя в виде файла cookie. Браузер может принять файл cookie. Если это так, он сохраняется в виде простой текстовой записи на жестком диске посетителя. Теперь, когда посетитель переходит на другую страницу вашего сайта, cookie доступен для поиска. После получения ваш сервер знает / запоминает, что было сохранено.

Файлы cookie представляют собой запись данных в виде простого текста из 5 полей переменной длины:

  • Expires- Дата истечения срока действия cookie. Если это поле пусто, срок действия cookie истечет, когда посетитель закроет браузер.

  • Domain - Доменное имя вашего сайта.

  • Path- Путь к каталогу или веб-странице, которая устанавливает cookie. Это может быть пустое поле, если вы хотите получить cookie из любого каталога или страницы.

  • Secure- Если это поле содержит слово «безопасный», то файл cookie может быть получен только с помощью безопасного сервера. Если это поле пустое, такое ограничение отсутствует.

  • Name = Value - Файлы cookie устанавливаются и извлекаются в виде пар ключ-значение.

Настройка файлов cookie

Отправить файлы cookie в браузер очень просто. Эти файлы cookie отправляются вместе с заголовком HTTP до поля Content-type. Предполагая, что вы хотите установить UserID и Password как файлы cookie. Настройка файлов cookie выполняется следующим образом -

#!/usr/bin/python
print "Set-Cookie:UserID = XYZ;\r\n"
print "Set-Cookie:Password = XYZ123;\r\n"
print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT;\r\n"
print "Set-Cookie:Domain = www.tutorialspoint.com;\r\n"
print "Set-Cookie:Path = /perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....

Из этого примера вы, должно быть, поняли, как устанавливать файлы cookie. Мы используемSet-Cookie Заголовок HTTP для установки файлов cookie.

Необязательно устанавливать такие атрибуты файлов cookie, как Expires, Domain и Path. Примечательно, что файлы cookie устанавливаются перед отправкой волшебной строки"Content-type:text/html\r\n\r\n.

Получение файлов cookie

Получить все установленные файлы cookie очень просто. Файлы cookie хранятся в переменной среды CGI HTTP_COOKIE, и они будут иметь следующую форму:

key1 = value1;key2 = value2;key3 = value3....

Вот пример того, как получить файлы cookie.

#!/usr/bin/python

# Import modules for CGI handling 
from os import environ
import cgi, cgitb

if environ.has_key('HTTP_COOKIE'):
   for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
      (key, value ) = split(cookie, '=');
      if key == "UserID":
         user_id = value

      if key == "Password":
         password = value

print "User ID  = %s" % user_id
print "Password = %s" % password

Это дает следующий результат для файлов cookie, установленных указанным выше сценарием:

User ID = XYZ
Password = XYZ123

Пример загрузки файла

Чтобы загрузить файл, HTML-форма должна иметь атрибут enctype, установленный на multipart/form-data. Тег ввода с типом файла создает кнопку «Обзор».

<html>
   <body>
      <form enctype = "multipart/form-data" action = "save_file.py" method = "post">
      <p>File: <input type = "file" name = "filename" /></p>
      <p><input type = "submit" value = "Upload" /></p>
      </form>
   </body>
</html>

Результатом этого кода является следующая форма -

Приведенный выше пример был намеренно отключен, чтобы сохранить людей, загружающих файл на наш сервер, но вы можете попробовать приведенный выше код со своим сервером.

Вот сценарий save_file.py для обработки загрузки файла -

#!/usr/bin/python

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# Get filename here.
fileitem = form['filename']

# Test if the file was uploaded
if fileitem.filename:
   # strip leading path from file name to avoid 
   # directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = 'The file "' + fn + '" was uploaded successfully'
   
else:
   message = 'No file was uploaded'
   
print """\
Content-Type: text/html\n
<html>
   <body>
      <p>%s</p>
   </body>
</html>
""" % (message,)

Если вы запустите приведенный выше сценарий в Unix / Linux, вам необходимо позаботиться о замене разделителя файлов следующим образом, в противном случае на вашем компьютере с Windows вышеупомянутый оператор open () должен работать нормально.

fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

Как открыть диалоговое окно "Загрузка файла"?

Иногда желательно предоставить вариант, при котором пользователь может щелкнуть ссылку, и пользователю будет выведено диалоговое окно «Загрузка файла» вместо отображения фактического содержимого. Это очень просто и может быть достигнуто через HTTP-заголовок. Этот заголовок HTTP отличается от заголовка, упомянутого в предыдущем разделе.

Например, если вы хотите сделать FileName файл, загружаемый по заданной ссылке, то его синтаксис следующий:

#!/usr/bin/python

# HTTP Header
print "Content-Type:application/octet-stream; name = \"FileName\"\r\n";
print "Content-Disposition: attachment; filename = \"FileName\"\r\n\n";

# Actual File Content will go here.
fo = open("foo.txt", "rb")

str = fo.read();
print str

# Close opend file
fo.close()

Надеюсь, вам понравился этот урок. Если да, отправьте мне свой отзыв по адресу: Свяжитесь с нами