Дана стаття містить короткий переклад документу RFC-3875 “CGI/1.1”, який описує Загальний Інтерфейс Шлюзу (Common Geteway Interface — CGI) версії 1.1. Для повної і оригінальної версії зверніться за сторінкою http://www.rfc-editor.org/rfc.html. Реалізація являється не сумісною, якщо вона не задовільняє хоча б одну необхідну вимогу MUST requirement) для призначеного протоколу. Реалізація, яка задовільняє усі необхідні (MUST) і усі з бажаних (should requirement), вважається безумовно сумісною. Реалізація, яка задовільняє усі необхідні умови, але не усі бажані вимоги, вважається умовно сумісною.

Позначення

Розширена BNF

Усі механізми вказані у цьому документі (у rfc-документі) описані у прозовій формі або у розширеній формі Бакуса-Наура (BNF - БНФ). Якщо конкретно не вказано, елементи являються чутливими до регістру. Дана нарощена БНФ містить наступні конструкції:
ім'я = визначення
Ім'я правила і його визначення відокремлюються знаком рівності ('=').
“буквенний”
Подвійні лапки (“) відокремлюють літерний текст, за винятком обмежувачів літери, яку оточують кутовими дужками ('>' і '<').
правило1 | правило2
Альтернативні правила відокремлюються вертикальною лінією ('|').
(правило1 правило2 правило3)
Елементи, розміщені у дужках, трактуються як один елемент.
*правило
Правило, якому передує знак множення (або зірка - '*'), можуть мати нуль або більше випадків. Повна форма виглядає як 'n*m правило', що показує хоча б n і максимум m випадків правила. N і m являються необов'язковими десятковими значеннями з стандартними значеннями 0 і безкінечності відповідно.
[правило]
Елемент, який розміщений у квадратних дужках ('[' і ']') являється необов'язковим, і є еквівалентом запису [*1 правило].
N правило
Правило, якому передує десяткове число, відображає точно N випадків (входжень) правила. Еквівалентний запис виглядає наступним чином 'N*N правило'.

Базові правила

Ця специфікація використовує БНФ-подібну граматику у термінах букв. На відміну від більшості специфікацій, які визначають дозволені байти у протоколі, тут кожна буква в граматиці, відповідає букві, яку вона представляє. Як ці букви представляються в системі у термінах бітів і байтів системи являється визначеним системою або вказане у відповідному контексті. Одним винятком, являється правило ОКТЕТ (OCTET rule), яке визначається нижче. Наступні правила використовуються цією специфікацією для опису базових конструкцій для інтерпретування.
alpha         = lowalpha | hialpha 

lowalpha      = "a" | "b" | "c" | "d" | "e" | "f" | 
                "g" | "h" | "i" | "j" | "k" | "l" | 
                "m" | "n" | "o" | "p" | "q" | "r" | 
                "s" | "t" | "u" | "v" | "w" | "x" | 
                "y" | "z" 

hialpha       = "A" | "B" | "C" | "D" | "E" | "F" | 
                "G" | "H" | "I" | "J" | "K" | "L" | 
                "M" | "N" | "O" | "P" | "Q" | "R" | 
                "S" | "T" | "U" | "V" | "W" | "X" | 
                "Y" | "Z"

digit         = "0" | "1" | "2" | "3" | "4" | "5" | 
                "6" | "7" | "8" | "9" 

alphanum      = alpha | digit 

OCTET         = <будь-який 8-ми бітний байт> 

CHAR          = alpha | digit | separator | "!" | 
                "#" | "$" | "%" | "&" | "'" | "*" | 
                "+" | "-" | "." | "`" | "^" | "_" | 
                "{" | "|" | "}" | "~" | CTL 

CTL           = <будь-який контрольний символ> 

SP            = <символ пробілу> 

HT            = <символ горизонтального відступу> 

NL            = <новий рядок> 

LWSP          = SP | HT | NL 

separator     = "(" | ")" | "<" | ">" | "@" | "," | 
                ";" | ":" | "\" | <"> | "/" | "[" | 
                "]" | "?" | "=" | "{" | "}" | SP | HT 

token         = 1*<any CHAR except CTLs or separators> 

quoted-string = <"> *qdtext <"> 

qdtext        = <будь-який символ CHAR за винятком <"> 
                символів CTL, але включно з LWSP> 

TEXT          = <будь-які друковані букви>
Зверніть увагу, що новий рядок (NL) не обов'язково повинен бути одним контрольним символом, але може бути послідовністю контрольних символів. Система МОЖЕ визначити TEXT, як більшу множину символів, ніж <будь-який символ CHAR, за виключенням символів CTL, але включаючи LWSP> Для того, щоб кодувати рядки символів, усі запасні і заборонені символи заміняються відповідними “%” послідовностями. Після цього, рядок символів може бути використаний у URI (unique recource identification — унікальний ідентифікатор ресурсу). Запасні символи можуть варіюватися від контексту до контексту, але завжди будуть міститися у наступній множині:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | 
           "=" | "+" | "$" | "," | "[" | "]"
Інші базові правила, які використовуються для опису синтаксису URI, наступні:
hex        = digit | "A" | "B" | "C" | "D" | "E" |
             "F" | "a" | "b" | "c" | "d" | "e" | "f" 

escaped    = "%" hex hex 

unreserved = alpha | digit | mark 

mark       = "-" | "_" | "." | "!" | "~" | "*" | "'" | 
             "(" | ")"

Сервер, програма, запити і змінні

Сервер поводить себе, як програмний шлюз. Він отримує запити від клієнтів, обирає CGI-програму для обробки запиту, перетворює запит клієнта на запит CGI, запускає програму і перетворює CGI відповідь у відповідь до клієнта. Сервер також може функціонувати не прозоро — модифікуючи запити чи відповіді. Сервер самостійно обирає, яку CGI-програму виконувати. В основному вибір залежить від URI-запиту клієнта. URI визначається наступним чином:
script-URI = <scheme> "://" <server-name> ":" <server-port> 
             <script-path> <extra-path> "?" <query-string>
Де <scheme> знаходиться у SERVER_PROTOCOL, <server-name>, <server-port> і <query-string> являються значеннями відповідних мета-змінних. CGI-програма викликається у визначений системою спосіб. Якщо конкретно не вказано, файл, який містить програму, буде викликаний як виконуваний файл. При виникненні помилки, сервер може перервати чи завершити виконання програми у будь-який час, без попередження; отож необов'язкова умова для CGI-програми полягає у готовності до ненормальних завершень. Інформація про запит походить від двох різних джерел: мета-змінні запиту і будь-яке асоційоване тіло запиту. Мета-змінні містять дані про запит, переданий від серверу до CGI-програми. Програма отримує доступ до цих змінних у системно визначений спосіб. Мета змінні визначаються за допомогою регістрово незалежних імен — не можуть існувати дві різні змінні, імена яких відрізняються тільки регістром. Далі вони представлені, використовуючи канонічні представлення букв з символом підкреслення (“_”). Конкретні системи можуть визначати інші представлення.
meta-variable-name = "AUTH_TYPE" | "CONTENT_LENGTH" | 
                     "CONTENT_TYPE" | "GATEWAY_INTERFACE" | 
                     "PATH_INFO" | "PATH_TRANSLATED" | 
                     "QUERY_STRING" | "REMOTE_ADDR" | 
                     "REMOTE_HOST" | "REMOTE_IDENT" | 
                     "REMOTE_USER" | "REQUEST_METHOD" | 
                     "SCRIPT_NAME" | "SERVER_NAME" | 
                     "SERVER_PORT" | "SERVER_PROTOCOL" | 
                     "SERVER_SOFTWARE" | scheme | 
                     protocol-var-name | extension-var-name 

protocol-var-name  = ( protocol | scheme ) "_" var-name 

scheme             = alpha *( alpha | digit | "+" | "-" | "." ) 

var-name           = token 

extension-var-name = token
Мета-змінні з таким самим ім'ям, як у схеми (scheme — в основному протокол), і іменами, які починаються з назви протоколу, також дозволені (на подобі “HTTP_ACCEPT”). Кількість і значення цих змінних може змінюватися незалежно від цієї специфікації. Сервер також МОЖЕ встановлювати додаткові мета-змінні, імена яких, не обов'язково, повинні мати префікс “X_”. Ця специфікація не розділяє значення пустого (NULL) значення і не існуючого значення. Наприклад, CGI-програма не повинна відрізняти два запити “http://host/program” і “http://host/program?” - в обох випадках мета-змінна QUERY_STRING буде мати нульове значення.
meta-variable-value = "" | 1*<TEXT, CHAR or tokens of value>
Значення мета-змінних ПОВИННО (MUST-requirement) вважатися чутливим до регістру, якщо не вказано інше. Представлення букв у мета-змінних являється системно визначеним; сервер ПОВИНЕН (MUST) перетворювати значення змінних до цього представлення.

AUTH_TYPE

Мета-змінна AUTH_TYPE ідентифікує будь-який механізм, який використовувався для ідентифікування користувача. Вона містить не чутливе до регістру значення, визначене протоколом клієнта чи реалізацією сервера. Для HTTP, якщо запит клієнта вимагає аутентифікації для зовнішнього доступу, тоді сервер ПОВИНЕН встановити значення цієї змінної з знаку 'auth-scheme' запиту у заголовковому полі Authorization.
AUTH_TYPE      = "" | auth-scheme 
auth-scheme    = "Basic" | "Digest" | extension-auth 
extension-auth = token
Схеми аутентифікацій HTTP описані у RFC 2517.

CONTENT_LENGTH

Змінна CONTENT_LENGTH містить розмір тіла повідомлення, прикріпленого до запиту, якщо таке є, у десятковому значенні кількості октетів. Якщо не прикріплено ніяких даних, тоді змінна набуває значення NULL (або не встановлена). CONTENT_LENGTH = "" | 1*digit Сервер ПОВИНЕН встановлювати цю мета-змінну, якщо тільки запит супроводжується тілом повідомлення. Значення CONTENT_VALUE повинне відображати довжину тіла повідомлення після того, як сервер видалиться будь-які коди передачі або коди контенту.

CONTENT_TYPE

Якщо запит включає тіло повідомлення, змінна CONTENT_TYPE є встановленою у відповідності до Internet Media Type (RFC 2046) тіла повідомлення.
CONTENT_TYPE = "" | media-type 
media-type   = type "/" subtype *( ";" parameter ) 
type         = token 
subtype      = token 
parameter    = attribute "=" value 
attribute    = token 
value        = token | quoted-string
Тип, підтип і імена параметрів атрибутів не являються чутливими до регістру. Значення параметрів можуть бути чутливими до регістру. Типи медіа і їхнє використання у HTTP описані у секції 3.7 специфікації HTTP/1.1 (RFC-2068). Немає значення за умовчанням для цієї змінної. Тільки якщо вона не встановлена, CGI-програма МОЖЕ спробувати визначити тип медіа отриманих даних. Якщо тип невідомий, тоді CGI-програма МОЖЕ припустити тип application/octet-stream або може відхилити запит з поверненням помилки. Сервер ПОВИНЕН встановити цю мета-змінну, якщо поле Content-Type протоколу HTTP присутнє у заголовку запиту клієнта. Якщо сервер отримує запит з прикріпленням, але не визначеним заголовковим полем Content-Type, він МОЖЕ спробувати визначити коректний тип контенту, в іншому випадку повинен пропустити цю мета-змінну.

GATEWAY_INTERFACE

Змінна GATEWAY_INTERFACE ПОВИННА бути встановленою у значення типу діалекту CGI, який використовується сервером для зв'язку з CGI-програмою. Синтаксис:
GATEWAY_INTERFACE = "CGI" "/" 1*digit "." 1*digit
Зверніть увагу, що старше і молодше число інтерпретуються, як окремі цілочисельні значення і кожен з них може бути більшим від однозначного числа. Тобто CGI/2.4 являється старішою версією, ніж CGI/2.13, яка у свою чергу старіша від CGI/12.3. Передуючі нулі ПОВИННІ бути ігнорованими скриптом і НЕ ПОВИННІ генеруватися сервером. Ця специфікація (RFC-3875) визначає версію 1.1 CGI інтерфейсу.

PATH_INFO

Значення змінної PATH_INFO вказує шлях, який повинен бути інтерпретований CGI-програмою. Вона визначає ресурс або підресурс, який повинна повернути CGI-програма, і є похідною від порції ієрархії шляху URI, яка міститься після ідентифікатора самої програми CGI. На відміну від шляху URI, змінна PATH_INFO не є кодованою у URI-стилі, і не може містити параметри сегментів шляху. Змінна PATH_INFO, яка має значення “/”, представляє один пустий сегмент шляху.
PATH_INFO = "" | ( "/" path ) 
path      = lsegment *( "/" lsegment ) 
lsegment  = *lchar 
lchar     = <any TEXT or CTL except "/">
Значення розглядається як чутливе до регістру і сервер ПОВИНЕН зберегти такий ж регістр шляху, який міститься у запиті URI. Сервер МОЖЕ впроваджувати заборони і обмеження на значення, які він передає у змінній PATH_INFO, і МОЖЕ відхилити запит, який містить помилку. Інтерпретування символів шляху, які не містяться у US_ASCII кодуванні, є залежним від системи.

PATH_TRANSLATED

Значення змінної PATH_TRANSLATED походить від інтерпретованого значення PATH_INFO, перетвореного у будь-якій формі віртулане-до-фізичного, у відповідності до серверної фізичної структури. Набір символів, дозволений у значенні результату, являється системно-залежним.
PATH_TRANSLATED = *<будь-який символ>
Це є шлях розміщення файлу, до якого буде отримано доступ за запитом
<scheme> "://" <server-name> ":" <server-port> <extra-path>
де, <scheme> являється оригінальною схемою запиту користувача і <extra-path> являється URL-закодованою версією значення змінної PATH_INFO, з запасними символами “;”, “=” і “?”. Наприклад, наступний запит:
http://somehost.com/cgi-bin/somescript/this%2eis%2epath%3binfo
буде мати наступне представлення у значенні змінної PATH_INFO
/this.is.the.path;info
Внутрішній URI конструюється з схеми, розміщення серверу і URL-закодованої PATH_INFO
http://somehost.com/this.is.the.path%3binfo
Це буде перетворено у шлях розміщення сховища документів сервера. Можливо шлях у файловій системі буде виглядати, приблизно, наступним чином:
/usr/local/www/htdocs/this.is.the.path;info
Значення змінної PATH_TRANSLATED являється результатом перетворення. Сервер ПОВИНЕН зберігати регістр сегменту шляху, за винятком, якщо підпорядковане сховище підтримує не чутливі до регістру імена. Алгоритм перетворення, який сервер використовує для отримання PATH_TRANSLATED, являється реалізаційно-залежним; CGI-програми, які використовують цю змінну можуть мати деяку несумісність відносно інших реалізацій серверів. Якщо змінну PATH_INFO не встановлено, змінна PATH_TRANSLATED також повинна бути не встановленою.

QUERY_STRING

Змінна QUERY_STRING містить URL-закодований рядок-параметр. Він забезпечує інформацію для CGI-програми, для отримання ефекту або перебудування документу, який буде поверненим CGI-програмою. Синтаксис URL для рядка пошуку оголошений у секції 3 документу RFC-2396. Значення змінної QUERY_STRING являється чутливим до регістру.
QUERY_STRING = query-string 
query-string = *uric 
uric         = reserved | unreserved | escaped
Під час декодування і інтерпретування рядка запиту, деталі інтерпретування, запасні символи і підтримка не US-ASCII символів залежить від контексту. Наприклад, у підпорядкованому від HTML документу, який використовує кодування application/x-www-form-urlencoded, у якому символи “+”, “&”, “=” являються запасними (тобто системними — мають спеціальне семантичне значення), кодування символів ISO 8859-1 може бути використаною для не US-ASCII символів. Значення QUERY_STRING забезпечує частину рядка запиту Script-URI. Сервер ПОВИНЕН встановлювати цю змінну. Якщо Script-URI не містить компонент-запит, змінна QUERY_STRING ПОВИННА бути встановлена в пусте значення (“”).

REMOTE_ADDR

Значення змінної REMOTE_ADDR ПОВИННЕ бути встановленим у мережеву адресу клієнта, який надіслав запит до серверу.
REMOTE_ADDR  = hostnumber 
hostnumber   = ipv4-address | ipv6-address 
ipv4-address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit 
ipv6-address = hexpart [ ":" ipv4-address ] 
hexpart      = hexseq | ( [ hexseq ] "::" [ hexseq ] ) 
hexseq       = 1*4hex *( ":" 1*4hex )
Формат адреси IPv6 описаний у документі RFC 3513.

REMOTE_HOST

Змінна REMOTE_HOST містить повне доменне ім'я клієнта, який надіслав запит до серверу, якщо такий існує, у іншому випадку — NULL. Повне доменне ім'я отримує форму, описану у секції 3.5 документу RFC-1034 і секції 2.1 RFC-1123. Доменні імена не чутливі до регістру.
REMOTE_HOST   = "" | hostname | hostnumber 
hostname      = *( domainlabel "." ) toplabel [ "." ] 
domainlabel   = alphanum [ *alphahypdigit alphanum ] 
toplabel      = alpha [ *alphahypdigit alphanum ] 
alphahypdigit = alphanum | "-"
Сервер необов'язково встановлює дану змінну. Якщо ім'я хосту недоступне з огляду на ефективність чи іншої причини. Сервер МОЖЕ замінювати значення змінної REMOTE_ADDR.

REMOTE_IDENT

Змінна REMOTE_INDENT МОЖЕ бути використаною для передачі інформації, яку сервер отримав від з'єднання, у формі запиту, описаній документом RFC-1413, до віддаленого агенту, якщо така доступна. Сервер може не підтримувати цю можливість, або не запитувати дані з огляду на ефективність, або не повертати доступні дані ідентифікації. REMOTE_IDENT = *TEXT Отримані дані можуть використовуватися для автентифікації, але рівень довіри до неї, повинен бути мінімальний.

REMOTE_USER

Змінна REMOTE_USER забезпечує рядок ідентифікування користувача, яка постачається клієнтом у вигляді частини автентифікації користувача. REMOTE_USER = *TEXT Якщо запит клієнта вимагає автентифікацію HTTP (тобто мета-змінна AUTH_TYPE встановлена у значення “Basic” або “Digest”), тоді значення мета-змінної REMOTE_USER ПОВИННЕ бути встановленим у значення ідентифікатора користувача.

REQUEST_METHOD

Значення мета-змінної REQUEST_METHOD ПОВИННО бути встановлено у значення методу, який повинен бути використаним скриптом, щоб обробити запит.
REQUEST_METHOD   = method 
method           = "GET" | "POST" | "HEAD" | extension-method 
extension-method = "PUT" | "DELETE" | token
Значення методу є чутливим до регістру. Методи HTTP описані у секції 5.1.1 специфікації протоколу HTTP/1.0 (RFC-1945) і секції 5.1.1 специфікації протоколу HTTP/1.1 (RFC-2068).

SCRIPT_NAME

Змінна SCRIPT_NAME ПОВИННА бути встановленою у значення шляху URI (не кодованої у URL-стилі), яка повинна ідентифікувати CGI-програму (а не її вивід). Синтаксис такий ж, як для змінної META_INFO
SCRIPT_NAME = "" | ( "/" path )
Знак “/” у першій позиції рядка не є частиною шляху. Він є необов'язковим, коли шлях є пустим; однак, у такому випадку, змінна все-одно ПОВИННА бути встановленою. Рядок SCRIPT_NAME формує деяку лідируючу частину компоненту шляху Script-URI, отриману у деякий визначеній реалізацією манері. Ніякий сегмент змінної PATH_INFO не повинен бути включеним у значення змінної SCRIPT_NAME.

SERVER_NAME

Змінна SERVER_NAME повинна бути встановленою у значення ім'я сервера хосту, до якого призначений запит клєнта. Значення являється не чутливим до регістру ім'я хосту (комп'ютера) або мережева адреса. Він формує частину “host” Script-URI.
SERVER_NAME = server-name

server-name = hostname | ipv4-address | 
              ( "[" ipv6-address "]" )
Сервер може мати одне або більше можливих значень цієї змінної, коли декілька віртуальних HTTP серверів розділяють одну IP-адресу. У такому випадку, сервер повинен використовувати значення заголовкового поля Host запиту для обирання коректного віртуально сервера.

SERVER_PORT

Значення змінної SERVER_PORT ПОВИННЕ бути встановлене у номер порту TCP/IP, через який даний запит отриманий від клієнта. Це значення використовується частині “port” значення Script-URI.
SERVER_PORT = server-port
server-port = 1*digit
Зверніть увагу, що дане значення повинне бути встановленим, навіть якщо значення порт є стандартне значення для використовуваної схеми і може бути знехтуваною з значення URI.

SERVER_PROTOCOL

Значення змінної SERVER_PROTOCOL повинне бути встановленим у значення ім'я і версії протоколу, який використовує програма для цього CGI-запиту. Це значення може відрізнятися від значення версії протоколу, яка використовується сервером для комунікаці з клієнтом.
SERVER_PROTOCOL   = HTTP-Version | "INCLUDED" | 
                    extension-version

HTTP-Version      = "HTTP" "/" 1*digit "." 1*digit

extension-version = protocol [ "/" 1*digit "." 1*digit ]

protocol          = token
Тут, “protocol” визначає синтаксис деякої інформації, яка передається між сервером і CGI-програмою (функції унікальні для протоколу). Він не є чутливим до регістру і зазвичай представлений у верхньому регістрі. Протокол не є таким ж як у частині “scheme” значення URI скрипту, який визначає загальний механізм доступу, який використовується клієнтами для зв'язку з сервером. Наприклад, запит, який отримала CGI-програма, з протоколом “HTTP” може використовувати схему “HTTPS”. Загальновідоме значення для змінної SERVER_PROTOCOL, яке сервер МОЖЕ використовувати “INCLUDED”, що сигналізує, що поточний документ скоріш являється включеним, як частина композитного документу, ніж є прямою ціллю запиту клієнта. Скрипт повинен трактувати це значення як запит HTTP/1.0.

SERVER_SOFTWARE

Значення мета-змінної SERVER_SOFTWARE ПОВИННЕ бути встановленим у ім'я і версію програмного забезпечення серверу, який згенерував CGI-запит. Вона повинна мати таке ж значення, як опис серверу, наданий клієнту, якщо мало місце надавання даної інформації.
SERVER_SOFTWARE = 1*( product | comment )

product         = token [ "/" product-version ]

product-version = token

comment         = "(" *( ctext | comment ) ")"

ctext           = <будь-який символ TEXT включаючи "(" і ")">
Сервер ПОВИНЕН встановлювати мета-змінні, які є характерними для відповідного протоколу і схеми запиту. Інтерпретування специфічних для протоколу змінних залежить від версії протоколу у змінній SERVER_PROTOCOL. Сервер МОЖЕ встановлювати мета-змінні у не нульове значення ім'я схеми, якщо схема не є тією ж, що і протокол. Присутність даної змінної надає для скрипту інформацію при використовувану схему запиту. Мета змінні з іменами, які починаються з “HTTP_” містять отримані значення з заголовкових полів запиту користувача, якщо використаний протокол є HTTP. Перетворені на верхній регістр імена заголовкових полів HTTP, мають усі входження знаку “-” заміненими на “_” і мають префікс “HTTP_” доданий до ім'я даної мета-змінної. Заголовкові дані можуть бути представленими у вигляді, який надіслав клієнт, або можуть бути зміненими у спосіб, який не змінює їхню семантику. Якщо отримані дубльовані заголовкові поля з однаковими іменами, тоді сервер ПОВИНЕН переписати їх як одинарне значення з такою ж семантикою. Так само, заголовкове поле, яке розділене на декілька рядків ПОВИННЕ бути з'єднане в один рядок. Сервер ПОВИНЕН, якщо необхідно, змінювати представлення даних (наприклад, кодування символів), щоб вони відповідали до мета-змінних протоколу CGI. Сервер не зобов'язаний створювати мета-змінні для усіх заголовкових полів, які він отримав. Особливо, він не обов'язково повинен видаляти будь-яке заголовкове поле, яке призначене для утримування інформації про аутентифікацію, на подобі 'Authorization'; або таку, яка доступна для CGI-програми у інших змінних, на подобі 'Content-Length' і 'Content-Type'. Сервер МОЖЕ видаляти заголовкові поля, які відносяться виключно до питань комунікації з клієнтської сторони, на подобі 'Connection'.

Тіло повідомлення запиту

CGI-програма отримує доступ до даних запиту, визначеним системою методом. Якщо тільки не сказано інше, це буде відбуватися за допомогою зчитування з файлового дескриптора чи файлового обробника “стандартного введення”.
Request-Data   = [ request-body ] [ extension-data ]
request-body   = <CONTENT_LENGTH>OCTET
extension-data = *OCTET
Тіло запиту постачається разом з запитом, якщо змінна CONTENT_LENGTH встановлена в не нульове значення. Сервер ПОВИНЕН зробити хоча б стільки байтів доступними для читання скриптом. Сервер може сигналізувати досягнення умови end-of-file (закінчення файлу) після того, як CONTENT_LENGTH байтів були зчитаними або він може передати додаткові дані. Тому, CGI-програма НЕ ПОВИННА намагатися зчитати більше ніж CONTENT_LENGTH байтів, навіть, якщо доступні ще дані. Однак, вона не зобов'язана читати будь-які дані. Для CGI-програм, які не інтерпретують заголовки, сервер не обов'язково повинен запевнити, що дані, надані CGI-програмі, такі ж як їх передав клієнт і не змінені сервером. Якщо кодування передачі не підтримуються тілом запиту, сервер ПОВИНЕН видалити будь-які входження таких кодувань з тіла повідомлення, і заново обчислити змінну CONTENT_LENGTH. Якщо це неможливо (наприклад, через занадто великі вимоги запиту до буферів), сервер не обов'язково повинен відхилити запит клієнта. Він також МОЖЕ видалити будь-які заголовки кодування контенту з тіла повідомлення.

Методи запиту

Метод запиту постачається за допомогою мета-змінної REQUEST_METHOD, яка ідентифікує метод обробки, який необхідно застосувати CGI-прогармою під час генерування запиту. Автор CGI-прогарми може вибрати реалізувати методи, які найбільш відповідають програмі. Якщо програма отримує запит з методом, який вона не підтримує, вона не обов'язково повинна відхилити його, і повернути помилку.

GET

Метод GET показує, що CGI-програма повинна згенерувати документ, контент якого залежить від значень мета-змінних. За загальною згодою, метод GET являється 'безпечним' і 'ідемпотентним' і не повинен мати значення інше, ніж генерування документу. Значення методу GET може бути модифікованим і удосконаленим за допомогою залежних від протоколу мета-змінних.

POST

Метод POST використовується запитами, які вимагають, щоб CGI-програма виконувала і генерувала документ, який повинен базуватися на даних тіла повідомлення запиту, в додаток до мета-змінних. Загальне використання являється у надсиланні формами HTML, яке призначене для ініціалізування обробки CGI-програмою, яка має постійний ефект, на подобі зміни у базі даних. CGI-програма ПОВИННА перевіряти значення змінної CONTENT_LENGTH, перед тим як читати прикріплені дані у тілі повідомлення, і не обов'язково повинна перевіряти значення змінної CONTENT_TYPE перед їх обробкою.

HEAD

Запит HEAD змушує CGI-програму виконати достатню обробку для повернення полів заголовків відповіді, без повернення тіла повідомлення відповіді. CGI-програма не обов'язково повинна забезпечувати тіло повідомлення для HEAD-запиту. Якщо ж вона все-таки забезпечує тіло повідомлення, сервер ПОВИНЕН відхилити тіло повідомлення під час читання відповіді від CGI-програми.

Методи залежні від протоколу

CGI-програма може реалізовувати будь-які методи, які є специфічні для протоколу, на подобі методів протоколу HTTP/1.1 PUT і DELETE; вона не обов'язково повинна перевіряти значення змінної SERVER_PROTOCOL під час виконання даних дій. Сервер МОЖЕ вирішити, що деякі методи не є відповідними чи дозволеним для CGI-програми, і може обробити дані методи самостійно або повернути помилку клієнту.

Командний рядок CGI-програми

Деякі системи підтримують метод для отримування масиву рядків до CGI-програми. Це використовується тільки у випадку індексованих запитів HTTP, які ідентифікуються за допомогою запитів 'GET' або 'HEAD' з рядком запиту URI, які не містять будь-яких не кодованих символів “=”. Для такого запиту, сервер не обов'язково повинен трактувати рядки запиту, як рядок пошуку і інтерпретувати його у слова, використовуючи наступні правила:
search-string = search-word *( "+" search-word )

search-word   = 1*schar

schar         = unreserved | escaped | xreserved

xreserved     = ";" | "/" | "?" | ":" | "@" | "&" | 
                "=" | "," | "$"
Після інтерпретування, кожне слово пошуку являється URL-декодованим, не обов'язково кодованим у визначеним системою способом і після цього додається до командної стрічки рядку аргументів. Якщо сервер не може створити будь-яку чистину списку аргументів, тоді сервер НЕ ПОВИНЕН генерувати будь-яку інформацію командного рядка. Наприклад, кількість аргументів може перевищувати обмеження системи або серверу, або один або декілька слів можуть не бути представленими як аргумент. CGI-програма повинна перевірити чи значення змінної QUERY_STRING містить декодовану змінну “=”, і не обов'язково не використовувати аргументи командного рядка.

CGI відповідь

Обробка відповіді

CGI-програма завжди ПОВИННА повертати не пусту відповідь, і отож, є системно визначений метод для неї, щоб відправити ці дані назад до серверу. Якщо не визначений інший спосіб, дані будуть відсилатися до сервера через 'стандартний вивід' файлового дескриптора. CGI-програма завжди ПОВИННА перевіряти змінну REQUEST_METHOD під час обробки запиту і підготовки відповіді. Сервер МОЖЕ реалізувати період закінчення часу запиту, після якого, дані повинні бути отриманими від CGI-програми. Якщо реалізація серверу визначає такі часові обмеження і не отримує дані від CGI-програми після такого часового періоду, сервер МОЖЕ зупинити процес CGI-програми.

Типи відповіді

Відповідь охоплює заголовки повідомлення і його тіло, відокремлені пустим рядком. Заголовки повідомлення містять одне або декілька полів. Тіло може мати нульову довжину.
generic-response = 1*header-field NL [ response-body ]
CGI-програма ПОВИННА повертати одне або відповідь документом, або локальне перенаправлення, або ж відповідь перенаправлення клієнта (з не обов'язковим документом). У визначенні відповідей, наведених нижче, порядок полів заголовку відповіді не має значення (незважаючи на виникнення такої у БНФ).
CGI-Response = document-response | local-redir-response |
               client-redir-response | 
               client-redirdoc-response

Відповідь документом

CGI-програма може повернути документ до користувача у відповіді документом, з не обов'язковим кодом помилки, яка ідентифікує успішний статус відповіді.
document-response = Content-Type [ Status ] *other-field NL
                    response-body
CGI-програма повинна повернути заголовкове поле Content-Type. Заголовкове поле статусу являється не обов'язковим, і статус 200 'OK' набувається, якщо дане поле відсутнє. Сервер ПОВИНЕН робити будь-які відповідні модифікації виводу CGI-програми, щоб запевнити, що відповідь до клієнта відповідає версії протоколу відповіді.

Локальна відповідь перенаправлення

CGI-програма може повертати шлях URI і рядок запиту ('local-pathquery') до локального ресурсу у заголовковому полі Location. Це показує серверу, що він повинен перетворити запит, використовуючи вказаний шлях.
local-redir-response = local-Location NL
CGI-програма НЕ ПОВИННА повертати будь-які інші заголовкові поля або тіло повідомлення, і сервер ПОВИНЕН генерувати відповідь, яка буде генерована у відповіді на запит, яка містить URL.
 
scheme "://" server-name ":" server-port local-pathquery

Відповідь перенаправлення клієнта

CGI-програма може повернути абсолютний шлях URI у заголовковому полі Location, для того щоб повідомити клієнта, що він повинен переробити запит, використовуючи вказане URI.
client-redir-response = client-Location *extension-field NL
CGI-програма НЕ ПОВИННА постачати будь-які інші заголовкові поля, за виключенням, визначених сервером, розширених полів CGI. Для запитів HTTP клієнта, сервер ПОВИНЕН генерувати відповідь повідомлення 302 'Found'.

Відповідь перенаправлення клієнта з Документом

CGI-скрипт може повертати абсолютний шлях URI у заголовковому полі Location разом з прикріпленим документом, для того щоб повідомити клієнта, що він повинен переробити запит, використовуючи вказаний URI.
client-redirdoc-response = client-Location Status Content-Type
                                 *other-field NL response-body
Заголовкове поле Status ПОВИННЕ бути наданим і ПОВИННЕ містити статус 302 'Found', або ж воно МОЖЕ містити розширений код, тобто, інший коректний коду статусу, який означає перенаправлення клієнта. Сервер ПОВИНЕН впевнитись, що відповідь до клієнта відповідає версії протоколу відповіді.

Заголовкові поля відповіді

Заголовкові поля відповіді являються або CGI, або додатковими заголовковими полями, які повинні бути інтерпретованими сервером, або залежні від протоколу заголовкові поля, які необхідно включити у відповідь, яка повертається клієнту. Наданим ПОВИННЕ бути хоча б одне поле CGI. Кожне поле CGI НЕ ПОВИННЕ з'являтися більше ніж один раз у відповіді. Заголовкові поля відповіді мають наступний синтаксис:
header-field    = CGI-field | other-field
CGI-field       = Content-Type | Location | Status
other-field     = protocol-field | extension-field
protocol-field  = generic-field
extension-field = generic-field
generic-field   = field-name ":" [ field-value ] NL
field-name      = token
field-value     = *( field-content | LWSP )
field-content   = *( token | separator | quoted-string )
Ім'я поля не являється чутливим до регістру. Поле нульової довжини, являється еквівалентом до поля, яке є не визначеним. Зверніть увагу, що кожне заголовкове поле у CGI-відповіді ПОВИННЕ бути вказаним у одинарному рядку; CGI/1.1 не підтримує розбиті рядки. Пробіли дозволені між “:” і значенням поля (але не між назвою поля і знаком “:”) і також між знаками у значенні поля.

Content-Type

Поле відповіді Content-type встановлює Interned Media Type (медіа тип інтернету) тіла відповіді.
Content-Type = "Content-Type:" media-type NL
Якщо повернено тіло відповіді, CGI-програма ПОВИННА постачати поле Content-Type у відповіді. Якщо вона не виконала дану умова, сервер не обов'язково не повинен спробувати визначити коректний тип контенту. Значення не обов'язково повинно бути надісланим не модифікованим до клієнта, окрім будь-якої зміни параметру кодування символів. Якщо тільки не визначено системою, клієнтом припускається, що стандартне кодування для текстового медіа-типу являється ISO-8859-1, якщо протокол являється HTTP і у іншому випадку US-ASCII. Отже скрипт не обов'язково повинен включати параметер кодування символів.

Location

Заголовкове поле Location використовується для вказування серверу, що CGI-програма повертає посилання на документ, а не сам документ. Це є або абсолютний URI, або ж локальний шлях URI.
Location        = local-Location | client-Location
client-Location = "Location:" fragment-URI NL
local-Location  = "Location:" local-pathquery NL
fragment-URI    = absoluteURI [ "#" fragment ]
fragment        = *uric
local-pathquery = abs-path [ "?" query-string ]
abs-path        = "/" path-segments
path-segments   = segment *( "/" segment )
segment         = *pchar
pchar           = unreserved | escaped | extra
extra           = ":" | "@" | "&" | "=" | "+" | "$" | ","
Синтаксис absoluteURI включений у цей документ з вказаного у документі RFC-2396 і RFC-2732. Коректний absoluteURI завжди починається з ім'я схеми, після якої міститься символ “:”; імена схем починаються з літер і продовжуються символами alphanumeric, “+”, “-” або “.”. Локальний шлях URI і запит повинні бути абсолютними шляхами і не мати відносний шлях або мати пусту довжину, і отже повинні починатись з символу “/”.

Статус

Заголовкове поле статусу містить 3-х розрядний цілочисельний код результату, який ідентифікує рівень успіху спроби CGI-програми обробити запит.
Status         = "Status:" status-code SP reason-phrase NL
status-code    = "200" | "302" | "400" | "501" | extension-code
extension-code = 3digit
reason-phrase  = *TEXT
Код статусу 200 'OK' ідентифікує успіх, і являється значенням за замовчуванням, яке припускається для відповіді документом. Код статусу 302 'Found' використовується разом з заголовковим полем Location і тіло повідомлення відповіді. Код статусу 400 'Bad request' може бути використаним для невідомого формату запиту, на подобі відсутнього CONTENT_TYPE. Код статусу 501 “Not Implemented” може бути повернуто CGI-програмою, якщо вона отримала не підтримуваний REQUEST_METHOD. Інші коректні коди статусів перелічені у секції 6.1.1 специфікації протоколу HTTP, і також у реєстрі кодів статусу IANA і МОЖУТЬ бути використаними в додатку до або замість тих, які перелічені вище. Програма ПОВИННА перевіряти значення змінної SERVER_PROTOCOL перед тим, як використовувати коди статусів HTTP/1.1. Скрипт МОЖЕ відхилити запит з поверненням помилки 405 'Method Not Allowed' HTTP/1.1, якщо він використовує метод, який CGI-програма не підтримує. Зверніть увагу на те, що повертаючи код статусу помилки не обов'язково повинно означати помилковий стан самої програми. Наприклад, скрипт, який викликаний сервером, як обробник помилок, повинен повернути код, відповідний до умови помилки серверу. Фраза причини являється текстовим описом помилки, яка повертається до клієнта, для розуміння людьми.

Тіло повідомлення відповіді

Тіло повідомлення відповіді являється прикріпленим документом, який необхідно повернути До клієнта сервером. Сервер ПОВИНЕН прочитати усі дані, які передаються CGI-програмою, аж поки скрипт не сигналізуватиме кінець тіла повідомлення, шляхом відправлення сигналу end-of-file (EOF). Тіло повідомлення не обов'язково повинне надсилатися не модифікованим до клієнта, окрім запитів HEAD або будь-яких необхідних кодувань передач, кодувань контенту чи перетворень кодувань символів.
response-body = *OCTET

Реалізація

Рекомендація для серверів

Хоча сервери і CGI-програми не потребують послідовності у їхній обробці шляхів URL (клієнтських URL і дані PATH_INFO, відповідно), автори серверів можуть забажати її введення. Отож реалізація серверу повинна вказувати її поведінку у наступних випадках:
  1. визначення будь-яких обмежень на дозволені сегменти шляху, в особливості чи дозволені сегменти без завершуючого нуля;
  2. визначення поведінки для сегментів шляху “.” або “..”;
  3. визначення будь-яких обмежень реалізації, включаючи обмеження на довжини шляхів чи рядків пошуку, і обмеження на значення заголовкових полів, які сервер буде інтерпретувати.

Рекомендації для CGI-програм

Якщо CGI-програма не наміряється обробляти дані змінної PATH_INFO, тоді вона повинна відхиляти запити з кодом 404 'Not Found', якщо PATH_INFO має не нульове значення. Якщо обробляється вивід форми, перевірте, чи CONTENT_TYPE рівне значенню "application/x-www-form-urlencoded" або "multipart/form-data". Якщо змінна CONTENT_TYPE являється пустою, CGI-програма може відхилити запит і повернути код помилки 415 'Unsupported Media Type', якщо це підтримується протоколом. Під час інтерпретування значень змінних PATH_INFO, PATH_TRANSLATED чи SCRIPT_NAME CGI-програма повинна бути обережною з пустими сегментами шляху (“//”) і спеціальними сегментами шляху (“.” або “..”). Вони повинні бути або видаленими з шляху перед використанням у викликах операційної системи, або запит повинен бути відхиленим з кодом 404 'Not Found'. При повернені заголовкових полів, CGI-програма повинна намагатися надіслати заголовкові поля CGI, як найшвидше, і повинна надіслати їх перед будь-якими заголовковими полями HTTP. Це може допомогти серверу зменшити об'єм використовуваної пам'яті. Автори CGI-програм повинні розуміти, що мета-змінні REMOTE_ADDR і REMOTE_HOST можуть точно не ідентифікувати джерело запиту. Вони ідентифікують клієнт для безпосереднього запиту до серверу; цей клієнт може являтися проксі-сервером, шлюзом або іншою посередницькою ланкою на шляху до самого клієнта.

Автор оригіналу

David Robinson The Apache Software Foundation EMail: drtr@apache.org Ken A. L. Coar The Apache Software Foundation EMail: coar@apache.org