Python - CGI Programming: Руководство для начинающих

Привет, будущие маги Python! Я рад быть вашим проводником в этом захватывающем путешествии по миру CGI-программирования на Python. Как человек, который многие годы преподает информатику, я могу вам сказать, что CGI - это как секретный соус, который делает ваши веб-приложения живыми. Так что принимайтеся за работу!

Python - CGI Programming

Что такое CGI?

CGI означает Common Gateway Interface. Это звучит сложно, но представьте, что это переводчик между вашим веб-сервером и скриптами на Python. Это как доброжелательный интерпретатор, который помогает вашему серверу и коду общаться без сбоев.

CGI позволяет нам создавать динамические веб-страницы, которые могут реагировать на ввод пользователя. Представьте себе веб-сайт, который приветствует вас по имени или показывает вам персонализированный контент - это и есть магия CGI!

Веб-браузинг

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

  1. Ваш браузер отправляет запрос на веб-сервер.
  2. Веб-сервер обрабатывает запрос.
  3. Сервер отправляет ответ, обычно в виде HTML-страницы.
  4. Ваш браузер отображает эту HTML, показывая веб-страницу, которую вы видите.

CGI вступает в игру, когда мы хотим генерировать динамический контент на шаге 3.

Диаграмма архитектуры CGI

Вот простая диаграмма для визуализации того, как CGI вписывается в веб-архитектуру:

+-------------+    HTTP Request    +-------------+
|   Браузер   | -----------------> |  Веб-сервер |
|             | <----------------- |             |
+-------------+    HTTP Response   +-------------+
|
| CGI
v
+-------------+
| CGI Скрипт  |
| (Python)    |
+-------------+

Поддержка и конфигурация веб-сервера

Большинство веб-серверов поддерживают CGI, включая Apache и Nginx. Чтобы использовать CGI с Python, вам нужно настроить свой сервер, чтобы он выполнял Python-скрипты. Это обычно включает создание специального каталога для CGI-скриптов и указание серверу, что файлы в этом каталоге являются исполняемыми.

Например, в Apache вы можете добавить что-то вроде этого в вашу конфигурацию:

<Directory /var/www/cgi-bin>
Options ExecCGI
AddHandler cgi-script .py
</Directory>

Это указывает Apache выполнять .py файлы в каталоге /var/www/cgi-bin как CGI-скрипты.

Первый CGI-программ

Давайте напишем нашу первую CGI-программу! Начнем с классического примера "Hello, World!". Создайте файл с именем hello.py в вашем каталоге CGI:

#!/usr/bin/env python3
print("Content-Type: text/html")
print()
print("<html>")
print("<head>")
print("<title>Hello World - Первая CGI программа</title>")
print("</head>")
print("<body>")
print("<h2>Hello World! Это моя первая CGI программа</h2>")
print("</body>")
print("</html>")

Разберем это:

  1. Первая строка указывает сервер использовать Python для выполнения этого скрипта.
  2. Content-Type: text/html - это HTTP-заголовок, который сообщает браузеру, что мы отправляем HTML.
  3. Пустая print() отделяет заголовки от тела ответа.
  4. Остальное просто HTML, который мы генерируем динамически.

Когда вы откроете этот скрипт через веб-браузер, вы увидите страницу с текстом "Hello World! Это моя первая CGI программа".

HTTP-заголовок

В программировании CGI важно отправлять правильные HTTP-заголовки перед вашим контентом. Самый распространенный заголовок - это Content-Type, который сообщает браузеру, какой тип данных вы отправляете. Вот несколько примеров:

Тип контента Описание
text/html HTML-контент
text/plain Простой текст
image/jpeg JPEG-изображение
application/json JSON-данные

Не забывайте всегда отправлять соответствующий Content-Type заголовок перед вашим контентом!

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

CGI-скрипты имеют доступ к различным переменным среды, которые предоставляют информацию о запросе. Вот скрипт, который отображает некоторые из этих переменных:

#!/usr/bin/env python3
import os

print("Content-Type: text/html")
print()
print("<html><body>")
print("<h2>Переменные среды:</h2>")
for param in os.environ.keys():
print(f"<b>{param:20}</b>: {os.environ[param]}<br>")
print("</body></html>")

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

Методы GET и POST

Есть два основных метода для отправки данных в CGI-скрипт: GET и POST. Рассмотрим оба:

Метод GET

Метод GET отправляет данные как часть URL. Вот простой пример:

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
name = form.getvalue('name', 'Мир')

print("<html><body>")
print(f"<h2>Привет, {name}!</h2>")
print("</body></html>")

Вы можете получить доступ к этому скрипту с URL, таким как http://вашсервер.com/cgi-bin/hello.py?name=Алиса, и он скажет "Привет, Алиса!".

Метод POST

Метод POST отправляет данные в теле HTTP-запроса. Обычно он используется для форм. Вот пример:

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
name = form.getvalue('name', 'Мир')
email = form.getvalue('email', 'Не указан')

print("<html><body>")
print(f"<h2>Привет, {name}!</h2>")
print(f"<p>Ваш email: {email}</p>")
print("</body></html>")

Этот скрипт можно использовать с HTML-формой, которая использует метод POST.

Обработка различных элементов формы

CGI может обрабатывать различные элементы формы. Рассмотрим несколько примеров:

Флажки (Checkbox)

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
hobbies = form.getlist('hobby')

print("<html><body>")
print("<h2>Ваши хобби:</h2>")
for hobby in hobbies:
print(f"<p>{hobby}</p>")
print("</body></html>")

Радио-кнопки (Radio Buttons)

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
gender = form.getvalue('gender', 'Не указан')

print("<html><body>")
print(f"<h2>Ваш пол: {gender}</h2>")
print("</body></html>")

Текстовая область (Text Area)

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
message = form.getvalue('message', 'Сообщение не указано')

print("<html><body>")
print("<h2>Ваше сообщение:</h2>")
print(f"<p>{message}</p>")
print("</body></html>")

Выпадающий список (Drop Down Box)

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
country = form.getvalue('country', 'Не выбрано')

print("<html><body>")
print(f"<h2>Ваша страна: {country}</h2>")
print("</body></html>")

Использование куки в CGI

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

Установка кук

#!/usr/bin/env python3
import cgi
from http import cookies
import datetime

# Создаем куку
c = cookies.SimpleCookie()
c['lastvisit'] = str(datetime.datetime.now())
c['lastvisit']['expires'] = 365 * 24 * 60 * 60  # истекает через год

print(c)  # Это выводит заголовок Set-Cookie
print("Content-Type: text/html")
print()

print("<html><body>")
print("<h2>Кука установлена!</h2>")
print("</body></html>")

Получение кук

#!/usr/bin/env python3
import os
from http import cookies

print("Content-Type: text/html")
print()

if 'HTTP_COOKIE' in os.environ:
cookie_string = os.environ.get('HTTP_COOKIE')
c = cookies.SimpleCookie()
c.load(cookie_string)
lastvisit = c.get('lastvisit')
if lastvisit:
print(f"<h2>Ваш последний визит был: {lastvisit.value}</h2>")
else:
print("<h2>Это ваш первый визит!</h2>")
else:
print("<h2>Это ваш первый визит!</h2>")

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

Обработка загрузки файлов немного сложнее, но вот простой пример:

#!/usr/bin/env python3
import cgi, os
import cgitb; cgitb.enable()

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()

# Получаем имя файла здесь.
fileitem = form['filename']

# Проверяем, был ли файл загружен
if fileitem.filename:
# Обрезаем ведущий путь от имени файла, чтобы избежать
# атак по переходу каталогов
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = f'Файл "{fn}" был успешно загружен'
else:
message = 'Файл не был загружен'

print(f"""\
<html>
<body>
<p>{message}</p>
</body>
</html>
""")

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

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

#!/usr/bin/env python3
import os

filename = "example.txt"  # Это будет ваше имя файла
filepath = "/path/to/your/file"  # Это будет путь к вашему файлу

print("Content-Type: application/octet-stream")
print(f"Content-Disposition: attachment; filename={filename}")
print()  # Пустая строка, конец заголовков

# Теперь отправляем содержимое файла
with open(os.path.join(filepath, filename), 'rb') as f:
print(f.read())

Этот скрипт устанавливает Content-Type на application/octet-stream, что указывает браузеру загружать файл, а не отображать его. Заголовок Content-Disposition предлагает имя файла для загрузки.

Итак, это базовые знания о CGI-программировании на Python. Помните, практика - это ключ к успеху, так что не стесняйтесь экспериментировать с этими примерами и создавать свои собственные. Счастливого кодинга, и愿 ваши CGI-скрипты всегда работали гладко!

Credits: Image by storyset