Общий интерфейс шлюза или CGI: это набор стандартов, которые определяют обмен информацией между веб-сервером и настраиваемым скриптом. Спецификации CGI в настоящее время поддерживаются NCSA.
Common Gateway Interface или CGI является стандартом для внешних шлюзовых программ для взаимодействия с информационными серверами, такими как HTTP-серверы.
Чтобы понять концепцию CGI, давайте посмотрим, что происходит, когда мы нажимаем на гипер ссылку для просмотра определенной веб-страницы или URL-адреса.
Тем не менее, можно настроить HTTP-сервер так, чтобы всякий раз, когда запрашивается файл в определенном каталоге, этот файл не отправляется обратно; вместо этого он выполняется как программа, и все эти выходы программы отправляются обратно для отображения вашего браузера. Эта функция называется интерфейсом общего шлюза или CGI, а программы называются скриптами CGI. Эти CGI-программы могут быть Python Script, PERL Script, Shell Script, C или C ++ программой и т. д.
Прежде чем приступать к программированию 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-скриптом 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>Привет, Мир!: Это моя первая программа CGI</title>' print '</head>' print '<body>' print '<h2>Привет, Мир! Это моя первая программа CGI</h2>' print '</body>' print '</html>'
Если вы нажмете hello.py, то это даст следующий результат:
Привет, Мир! Это моя первая программа CGI |
Этот скрипт hello.py: это простой скрипт Python, который записывает свой вывод в файл STDOUT, т. е. на экран. Существует одна важная и дополнительная функция, которая является первой строкой для печати. Content-type: text/html\r\n\r\n . Эта строка отправляется обратно в браузер и указывает тип содержимого, отображаемый на экране браузера.
К настоящему времени вы, должно быть, поняли базовую концепцию CGI, и вы можете написать много сложных программ CGI, используя Python. Этот скрипт может взаимодействовать с любой другой внешней системой также для обмена информацией, такой как РСУБД.
Строка 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.
№ | Заголовок и описание |
---|---|
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.
№ | Имя переменной и описание |
---|---|
1 | CONTENT_TYPE Тип данных содержимого. Используется, когда клиент отправляет прикрепленный контент на сервер. Например, загрузка файла. |
2 | CONTENT_LENGTH Длина информации запроса. Он доступен только для запросов POST. |
3 | HTTP_COOKIE Возвращает набор файлов cookie в виде пары ключ и значение. |
4 | HTTP_USER_AGENT Поле заголовка запроса пользователя-агента содержит информацию о пользовательском агенте, инициирующем запрос. Это имя веб-браузера. |
5 | PATH_INFO Путь к скрипту CGI. |
6 | QUERY_STRING URL-кодированная информация, которая отправляется с запросом метода GET. |
7 | REMOTE_ADDR IP-адрес удаленного хоста, делающего запрос. Это полезно для ведения журнала или для аутентификации. |
8 | REMOTE_HOST Полноценное имя хоста, делающего запрос. Если эта информация недоступна, REMOTE_ADDR можно использовать для получения IR-адреса. |
9 | REQUEST_METHOD Метод, используемый для выполнения запроса. Наиболее распространенными методами являются GET и POST. |
10 | SCRIPT_FILENAME Полный путь к скрипту CGI. |
11 | SCRIPT_NAME Имя скрипта CGI. |
12 | SERVER_NAME Имя хоста сервера или IP-адрес |
13 | SERVER_SOFTWARE Имя и версия программного обеспечения, на котором запущен сервер. |
Вот небольшая программа CGI для перечисления всех переменных CGI. Нажмите эту ссылку, чтобы увидеть результат Get Environment
#!/usr/bin/python import os print "Content-type: text/html\r\n\r\n"; print "<font size=+1>Окружающая среда</font><\br>"; for param in os.environ.keys(): print "<b>%20s</b>: %s<\br>" % (param, os.environ[param])
Вы должны столкнуться со многими ситуациями, когда вам нужно передать некоторую информацию из своего браузера на веб-сервер и, в конечном счете, в свою программу CGI. Чаще всего браузер использует два метода, которые передают эту информацию на веб-сервер. Этими методами являются метод GET и метод POST.
Метод 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-адрес, который передает два значения программе hello_get.py с использованием метода GET.
/cgi-bin/hello_get.py?first_name=ZARA&last_name=ALI
Ниже приведен скрипт hello_get.py для обработки ввода, заданного веб-браузером. Мы будем использовать cgi- модуль, который очень упрощает доступ к переданной информации:
#!/usr/bin/python # Импорт модулей для обработки CGI import cgi, cgitb # Создание экземпляра FieldStorage form = cgi.FieldStorage() # Получение данных из полей 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>Привет: вторая программа CGI</title>" print "</head>" print "<body>" print "<h2>Привет %s %s</h2>" % (first_name, last_name) print "</body>" print "</html>"
Это приведет к следующему результату:
Привет, AndreyEx |
Этот пример передает два значения с помощью кнопки HTML FORM и отправки. Для обработки этого ввода мы используем тот же скрипт CGI hello_get.py.
<form action = "/cgi-bin/hello_get.py" method = "get"> Имя: <input type = "text" name = "first_name"> <br /> Фамилия: <input type = "text" name = "last_name" /> <input type = "submit" value = "Submit" /> </form>
В фактическом выводе вышеуказанной формы, вы вводите Имя и Фамилию, а затем нажмите кнопку «Отправить», чтобы увидеть результат.
Обычно более надежным способом передачи информации в программу CGI является метод POST. Он упаковывает информацию точно так же, как метод GET, но вместо отправки ее в виде текстовой строки после ? в URL-адресе он отправляет его как отдельное сообщение. Это сообщение входит в CGI-скрипт в виде стандартного ввода.
Ниже приведен такой же скрипт hello_get.py, который обрабатывает GET, а также метод POST.
#!/usr/bin/python # Импорт модулей для обработки CGI import cgi, cgitb # Создание экземпляра FieldStorage form = cgi.FieldStorage() # Получение данных из полей 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>Привет: Вторая программа CGI</title>" print "</head>" print "<body>" print "<h2>Привет %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"> Имя: <input type = "text" name = "first_name"><br /> Фамилия: <input type = "text" name = "last_name" /> <input type = "submit" value = "Submit" /> </form>
Вот фактический вывод вышеуказанной формы. Введите первое и последнее имя и нажмите кнопку «Отправить», чтобы увидеть результат.
Флажки используются, когда требуется выбрать более одного параметра.
Вот пример кода HTML для формы с двумя флажками:
<form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank"> <input type = "checkbox" name = "maths" value = "on" /> Математика <input type = "checkbox" name = "physics" value = "on" /> Физика <input type = "submit" value = "Select Subject" /> </form>
Ниже приведен флажок checkbox.cgi для обработки ввода, заданного веб-браузером, для кнопки флажка.
#!/usr/bin/python # Импорт модулей для обработки CGI import cgi, cgitb # Создание экземпляра FieldStorage form = cgi.FieldStorage() # Получение данных из полей 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>Флажок: Третья программа CGI</title>" print "</head>" print "<body>" print "<h2> Флажок Математика : %s</h2>" % math_flag print "<h2> Флажок Физика : %s</h2>" % physics_flag print "</body>" print "</html>"
Кнопки «Радио» используются, когда требуется выбрать только один параметр.
Вот пример кода HTML для формы с двумя переключателями:
<form action = "/cgi-bin/radiobutton.py" method = "post" target = "_blank"> <input type = "radio" name = "subject" value = "maths" /> Математика <input type = "radio" name = "subject" value = "physics" /> Физика <input type = "submit" value = "Select Subject" /> </form>
Ниже приведен сценарий radioobutton.py для обработки ввода, заданного веб-браузером для переключателя:
#!/usr/bin/python # Импорт модулей для обработки CGI import cgi, cgitb # Создание экземпляра FieldStorage form = cgi.FieldStorage() # Получение данных из полей if form.getvalue('subject'): subject = form.getvalue('subject') else: subject = "Не ставить" print "Content-type:text/html\r\n\r\n" print "<html>" print "<head>" print "<title>Радио: Четвертая программа CGI</title>" print "</head>" print "<body>" print "<h2> Выбран предмет %s</h2>" % subject print "</body>" print "</html>"
Элемент TEXTAREA используется, когда многострочный текст должен быть передан в программу CGI.
Вот пример кода HTML для формы с полем TEXTAREA:
<form action = "/cgi-bin/textarea.py" method = "post" target = "_blank"> <textarea name = "textcontent" cols = "40" rows = "4"> Введите текст здесь... </textarea> <input type = "submit" value = "Submit" /> </form>
Ниже приведен скрипт textarea.cgi для обработки ввода, заданного веб-браузером:
#!/usr/bin/python # Импорт модулей для обработки 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\r\n\r\n" print "<html>" print "<head>"; print "<title>Текстовая область: Пятая программа CGI</title>" print "</head>" print "<body>" print "<h2> Введенный текстовый контент %s</h2>" % text_content print "</body>"
Drop Down Box используется, когда у нас есть много доступных опций, но будет выбран только один или два.
Вот пример кода HTML для формы с одним выпадающим списком:
<form action = "/cgi-bin/dropdown.py" method = "post" target = "_blank"> <select name = "dropdown"> <option value = "Maths" selected>математика</option> <option value = "Physics">физика</option> </select> <input type = "submit" value = "Submit"/> </form>
Ниже приведен сценарий dropdown.py для обработки ввода, заданного веб-браузером.
#!/usr/bin/python # Импорт модулей для обработки CGI import cgi, cgitb # Создание экземпляра FieldStorage form = cgi.FieldStorage() # Получение данных из полей if form.getvalue('dropdown'): subject = form.getvalue('dropdown') else: subject = "Не вводить" print "Content-type:text/html\r\n\r\n" print "<html>" print "<head>" print "<title>Выпадающий список: Шестая программа CGI</title>" print "</head>" print "<body>" print "<h2> Выбранный предмет %s</h2>" % subject print "</body>" print "</html>"
Протокол HTTP: это протокол без учета состояния. Для коммерческого веб-сайта необходимо поддерживать информацию о сеансе между различными страницами. Например, одна регистрация пользователя заканчивается после завершения многих страниц. Как сохранить информацию о сеансе пользователя на всех веб-страницах?
Во многих ситуациях использование файлов куки — является наиболее эффективным методом запоминания и отслеживания предпочтений, покупок, комиссий и другой информации, необходимой для лучшего опыта посетителей или статистики сайта.
Ваш сервер отправляет некоторые данные в браузер посетителя в виде файла cookie. Браузер может принять cookie. Если это так, оно хранится как простая текстовая запись на жестком диске посетителя. Теперь, когда посетитель прибывает на другую страницу вашего сайта, cookie доступен для извлечения. После получения ваш сервер знает/запоминает, что было сохранено.
Файлы cookie представляют собой запись текстовых данных из 5 полей переменной длины:
Очень легко отправлять файлы 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, 30-Sep-2018 00:37:12 GMT";\r\n" print "Set-Cookie:Domain = andreyex.ru;\r\n" print "Set-Cookie:Path = /perl;\n" print "Content-type:text/html\r\n\r\n" ...........Rest of the HTML Content....
В этом примере вы должны понимать, как устанавливать файлы cookie. Мы используем HTTP-заголовок Set-Cookie для установки файлов cookie.
Не обязательно устанавливать атрибуты cookie, такие как Expires, Domain и Path. Примечательно, что файлы cookie устанавливаются перед отправкой магической строки «Content-type: text/html\r\n\r\n.
Очень легко получить все установленные файлы cookie. Файлы cookie хранятся в переменной среды CGI HTTP_COOKIE, и они будут иметь следующую форму:
key1 = value1;key2 = value2;key3 = value3....
Ниже приведен пример извлечения файлов cookie.
#!/usr/bin/python # Импорт модулей для обработки CGI 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 "ID пользователя = %s" % user_id print "Пароль = %s" % password
Это дает следующий результат для файлов cookie, установленных вышеуказанным скриптом:
ID пользователя = XYZ Пароль = 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 = "Загрузить" /></p> </form> </body> </html>
Вышеприведенный пример был заблокирован намеренно для сохранения людей, загружающих файл на наш сервер, но вы можете попробовать код выше с вашим сервером.
Вот сценарий save_file.py для обработки загрузки файлов:
#!/usr/bin/python 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> <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"; # Фактическое содержимое файла будет идти сюда. fo = open("andrey.txt", "rb") str = fo.read(); print str # Закрыть открытый файл fo.close()
Спасибо за интересную статью. Но мне хотелось бы узнать больше. Например, как выключить сервер и как поменять файл(не index.html), который будет отсылать сервер.
как запустить web-сервер в этом каталоге? Куда это вставить $ python server.py
serving at port 8080
Судя по синтаксису это интерфейс командной строки windows. При правильной установке питона команда будет звучать вот так: python server.py
🙂 🙂
как воспользоваться сервером с другого пк
Самый простой вариант — набрать в адресной строке другого ПК ip-адрес нашего ПК. Однако это не сработает если: другой ПК — это любой ПК из интернета, а на вашем ПК «черный» (установленный за сетевым экраном провайдера интернета) адрес. У вас должен быть либо «белый» адрес, либо другой ПК должен находиться в одной локальной сети с сервером.
как добавить данные в файл на сервере?