G.8. utl_http — доступ к данным в Интернете по протоколу HTTP #
utl_http — это расширение Postgres Pro, которое позволяет получать доступ к данным в Интернете по протоколу HTTP (HTTP/1.0 и HTTP/1.1), выполняя HTTP-вызовы из SQL и PL/pgSQL. Функциональность, предоставляемая этим модулем, во многом пересекается с функциональностью пакета UTL_HTTP в Oracle. С помощью utl_http можно писать программы, взаимодействующие с HTTP-серверами. Кроме того, расширение utl_http содержит функции, которые можно использовать в запросах SQL, поддерживает протокол HTTP через SSL, также известный как HTTPS, и HTTP-методы GET, POST, PUT, UPLOAD, PATCH, HEAD, OPTIONS, DELETE, TRACE (см. https://datatracker.ietf.org/doc/html/rfc9110#name-methods), а также любые пользовательские HTTP-методы.
Расширение utl_http обычно используется следующим образом:
Запрос создаётся функцией
begin_request.Задаются параметры запроса, подробнее они описаны в Подразделе G.8.3.3.
Ответ обрабатывается функцией
get_response.Полученный ответ обрабатывается с использованием процедур из Подраздел G.8.3.4.
G.8.1. Установка #
Расширение utl_http поставляется вместе с Postgres Pro Enterprise в отдельном пакете pgpro-orautl-ent-17 (подробные инструкции по установке приведены в Главе 17). Чтобы включить utl_http, создайте расширение с помощью следующего запроса:
CREATE EXTENSION utl_http;
G.8.2. Типы данных #
Расширение utl_http предоставляет несколько типов данных:
Тип
reqпредставляет собой HTTP-запрос.CREATE TYPE req AS ( url varchar(32767), method varchar(64), http_version varchar(64) );
Таблица G.93. Параметры
reqПараметр Описание urlURL-адрес HTTP-запроса. Задаётся после создания запроса функцией begin_request.methodМетод, который будет применяться для ресурса, определяемого URL-адресом. Он задаётся после создания запроса функцией begin_requesthttp_versionВерсия HTTP-протокола, используемая для отправки запроса. Она задаётся после создания запроса функцией begin_request.Тип
respпредставляет собой HTTP-ответ.CREATE TYPE resp AS ( status_code integer, reason_phrase varchar(256), http_version varchar(64) );
Таблица G.94. Параметры
respПараметр Описание status_codeКод состояния, возвращаемый веб-сервером. Это трёхзначное целое число, показывающее результаты HTTP-запроса, обработанного веб-сервером. Этот код задаётся после обработки ответа функцией get_response.reason_phraseКороткое текстовое сообщение, возвращаемое веб-сервером и описывающее код состояния. Оно содержит краткое описание результатов HTTP-запроса, обработанного веб-сервером, и задаётся после обработки ответа функцией get_response.http_versionВерсия HTTP-протокола, используемая в HTTP-ответе. Она задаётся после обработки ответа функцией get_response.Тип
cookieпредставляет собой данные cookie HTTP. Типcookie_table— это набор cookie данных HTTP. По сути, это тип данных массива, создаваемого на основе автоматически созданного массива.CREATE TYPE cookie AS ( name varchar(256), value varchar(1024), domain varchar(256), expire timestamp with time zone, path varchar(1024), secure bool, version int, comment varchar(1024) ); CREATE DOMAIN cookie_table AS _cookie;
Таблица G.95. Поля типов
cookieиcookie_tableПараметр Описание nameИмя cookie HTTP. valueЗначение cookie. domainДомен, для которого действительны cookie. expireВремя истечения срока действия cookie. pathПодмножество URL-адресов, к которым относятся cookie. secureДолжны ли cookie возвращаться на веб-сервер только с использованием защищённых средств. versionВерсия спецификации cookie, которой соответствуют cookie. commentКомментарий, описывающий предполагаемое использование cookie. Тип
request_context_keyиспользуется для определения ключа контекста запроса. В Postgres Pro он представлен типомintegerи сохраняется из соображений совместимости для миграции из Oracle.
G.8.3. Функции и процедуры utl_http #
Обратите внимание, что параметр request_context в функциях и процедурах ниже сохраняется для совместимости при миграции из Oracle и не влияет на результат.
G.8.3.1. Простые HTTP-запросы #
Функции request_function и request_pieces_function берут URL-адрес в виде строки, подключаются к указанному в ней сайту и возвращают данные (обычно HTML), полученные с этого сайта.
-
request(#urltext,proxytextdefault null) returnstext Получает веб-страницу и возвращает не более первых 2000 байт этой страницы.
-
request_pieces(#urltext,max_piecesintdefault 32767,proxytextdefault null) returnstext Эта функция возвращает таблицу PL/pgSQL, состоящую из фрагментов данных по 2000 байт, полученных по заданному URL-адресу. Элементы таблицы, возвращаемые
request_pieces, представляют собой последовательные фрагменты данных, полученные в результате HTTP-запроса к этому URL-адресу.
G.8.3.2. Параметры сеанса #
Расширение utl_http предоставляет функции и процедуры для работы с конфигурацией и поведением по умолчанию при выполнении HTTP-запросов в сеансе пользователя базы данных. Когда запрос создаётся, он наследует параметры по умолчанию в отношении поддержки cookie, перенаправления, набора символов тела сообщения и тайм-аута передачи текущего сеанса. Когда создаётся ответ на запрос, он наследует эти параметры из запроса.
-
set_response_error_check(#enablebooldefault false) Эта процедура определяет, будет ли функция
get_responseвыдавать исключение, когда веб-сервер возвращает код состояния, указывающий на ошибку — код состояния в диапазоне 4xx или 5xx.-
get_response_error_check(#enablebool) Эта процедура проверяет, установлена ли проверка ошибок ответа.
-
set_transfer_timeout(#timeoutint4default 60) Эта процедура устанавливает значение тайм-аута по умолчанию для всех будущих HTTP-запросов, который должен соблюдаться расширением utl_http перед чтением HTTP-ответа с веб-сервера или прокси-сервера. Это значение тайм-аута можно использовать, чтобы избежать блокировки программ при загрузке веб-серверов или интенсивном сетевом трафике во время получения получении веб-страниц с веб-серверов. Значение тайм-аута по умолчанию — 60 секунд.
-
get_transfer_timeout(#timeoutint4) Эта процедура получает значение тайм-аута по умолчанию для всех будущих HTTP-запросов.
-
set_detailed_excp_support(#enablebooldefault false) Эта процедура определяет, выдаёт ли расширение utl_http подробное исключение. По умолчанию она выдаёт исключение
REQUEST_FAILEDпри сбое HTTP-запроса. Используйтеget_detailed_sqlcodeиget_detailed_sqlerrmдля получения более подробной информации об ошибке.Доступные исключения перечислены в Таблице G.96.
Таблица G.96. Исключения utl_http
Исключение Код ошибки Причина Где выдаётся исключение BAD_ARGUMENT29265 Передан некорректный аргумент Любой интерфейс HTTP-запроса или ответа, если включена выдача подробных исключений HEADER_NOT_FOUND29261 Заголовок не найден get_header,get_header_by_name, когда включена выдача подробных исключенийEND_OF_BODY29266 Достигнут конец тела HTTP-ответа read_raw,read_textиread_line, когда включена выдача подробных исключенийHTTP_CLIENT_ERROR29268 Код состояния ответа из get_responseуказывает на то, что произошла ошибка клиента (код состояния в диапазоне 4xx). Из функцииbegin_requestHTTP-прокси возвращает код состояния в диапазоне 4xx при выполнении HTTPS-запроса через прокси.get_response,begin_request, когда включена выдача подробных исключенийHTTP_SERVER_ERROR29269 Код состояния ответа из get_responseуказывает на то, что произошла ошибка сервера (код состояния в диапазоне 5xx). Из функцииbegin_requestHTTP-прокси возвращает код состояния в диапазоне 5xx при выполнении HTTPS-запроса через прокси.get_response,begin_request, когда включена выдача подробных исключенийREQUEST_FAILED29273 Ошибка выполнения запроса Любой интерфейс HTTP-запроса или ответа, если отключена выдача подробных исключений -
get_detailed_excp_support(#enablebool) Эта процедура проверяет, выдаст ли utl_http подробное исключение или нет.
G.8.3.3. HTTP-запросы #
Расширение utl_http предоставляет функции и процедуры для запуска HTTP-запроса, работы с атрибутами и отправки информации запроса на веб-сервер. Когда запрос создаётся, он наследует параметры по умолчанию в отношении поддержки cookie, перенаправления, набора символов тела сообщения и тайм-аута передачи текущего сеанса. Параметры можно изменить, вызвав интерфейс запроса.
-
begin_request(#urltext,methodtextdefault 'GET',http_versiontextdefault null,request_contextrequest_context_keydefault null) returnsreq Эта функция начинает новый HTTP-запрос.
-
set_header(#rreq,nametext,valuetext) Эта процедура устанавливает заголовок HTTP-запроса для будущего запроса.
-
set_authentication(#rreq,usernametext,passwordtext,schemetextdefault 'Basic',for_proxybooleandefault false) Эта процедура устанавливает информацию о HTTP-аутентификации в заголовке HTTP-запроса. Веб-серверу эта информация нужна для авторизации запроса.
-
set_body_charset(#rreq,charsetnamedefault null) Эта процедура устанавливает набор символов, когда тип носителя —
text, но набор символов не указан в заголовкеContent-Typeи может принимать одну из следующих форм:Устанавливает набор символов по умолчанию для тела всех будущих HTTP-запросов.
set_body_charset( charset IN name DEFAULT NULL)
Устанавливает набор символов тела запроса.
set_body_charset( r INOUT req, charset IN name DEFAULT NULL)
-
set_cookie_support(#rreq,enablebool) Эта процедура определяет поддержку cookie и может принимать одну из следующих форм:
Включает или отключает поддержку cookie HTTP в запросе.
set_cookie_support( r INOUT req, enable IN bool DEFAULT true)
Устанавливает, будут ли будущие HTTP-запросы поддерживать cookie HTTP, а также максимальное количество cookie, поддерживаемых в текущем сеансе пользователя базы данных.
set_cookie_support( enable IN bool, max_cookies IN int4 DEFAULT 300, max_cookies_per_site IN int4 DEFAULT 20)
-
set_follow_redirect(#rreq,max_redirectsint4default 3) Эта процедура устанавливает максимальное количество раз, когда utl_http должен следовать инструкции HTTP-перенаправления в HTTP-ответах на запросы в
get_response. По умолчанию — 3.-
set_proxy(#proxytext,no_proxy_domainstext) Эта процедура устанавливает прокси-сервер, который будет использоваться для HTTP-запросов или других протоколов.
-
write_raw(#rreq,databytea) Эта процедура записывает двоичные данные в тело HTTP-запроса для будущего запроса.
-
write_text(#rreq,datatext) Эта процедура записывает текстовые данные в тело HTTP-запроса для будущего запроса.
-
end_request(#rreq) Эта процедура завершает HTTP-запрос путём сброса параметров запроса.
G.8.3.4. HTTP-ответы #
Расширение utl_http предоставляет функции и процедуры для управления HTTP-ответом, полученным из get_response, и получения информации об ответе от веб-сервера. Когда создаётся ответ на запрос, он наследует параметры поддержки cookie, перенаправления, набора символов тела сообщения и тайм-аута передачи из запроса. Вызвав интерфейс ответа, можно изменить только набор символов тела.
-
end_response(#rresp) Эта процедура завершает HTTP-ответ путём сброса параметров запроса.
-
get_authentication(#rresp,schemetext,realmtext,for_proxybooldefault false) Эта процедура получает информацию о HTTP-аутентификации, необходимую для принятия запроса веб-сервером, как указано в заголовке HTTP-ответа.
-
get_header(#rresp,nint4,nametext,valuetext) Эта процедура возвращает n-е имя заголовка HTTP-ответа и значение, возвращаемое в ответе.
-
get_header_by_name(#rresp,nametext,valuetext,nint4default 1) Эта процедура возвращает значение заголовка HTTP-ответа, возвращаемое в ответе, по заданному имени заголовка.
-
get_header_count(#rresp) returnsint4 Эта функция возвращает количество заголовков HTTP-ответа, возвращаемых в ответе.
-
get_response(#rreq,return_info_responsebooldefault false) returnsresp Эта функция завершает HTTP-запрос и ответ: читает HTTP-ответ и обрабатывает строку состояния и заголовки ответа. Код состояния, описание причины и версия HTTP-протокола сохраняются в записи ответа.
-
read_raw(#rresp,databytea,lenint4default null) Эта процедура считывает тело HTTP-ответа в двоичной форме и возвращает выходные данные в буфер со стороны вызывающего.
-
read_line(#rresp,datatext,remove_crlfbooldefault false) Эта процедура считывает тело HTTP-ответа в текстовой форме до конца строки, и возвращает выходные данные в буфер со стороны вызывающего.
-
read_text(#rresp,datatext,lenint4default null) Эта процедура считывает тело HTTP-ответа в текстовой форме и возвращает выходные данные в буфер со стороны вызывающего.
G.8.3.5. Данные cookie HTTP #
Расширение utl_http предоставляет функции и процедуры для управления cookie.
-
add_cookies(#cookiescookie_table,request_contextrequest_context_keydefault null) Эта процедура добавляет cookie, поддерживаемые расширением utl_http.
-
clear_cookies(#request_contextrequest_context_keydefault null) Эта процедура удаляет все cookie с которые в настоящее время работает расширение utl_http.
-
get_cookie_count(#request_contextrequest_context_keydefault null) returnsint4 Эта функция возвращает объём cookie, с которым и в настоящее время работает расширение utl_http для всех веб-серверов.
-
get_cookies(#cookiescookie_table,request_contextrequest_context_keydefault null) returnscookie_table Эта функция возвращает полный объём cookie, с которым в настоящее время работает расширение utl_http для всех веб-серверов.
G.8.3.6. Условия возникновения ошибок #
Расширение utl_http предоставляет функции для получения информации об ошибках.
-
get_detailed_sqlcode() returns#int4 Получает код
SQLCODEс описанием последнего выданного исключения (см. Таблицу G.96).-
get_detailed_sqlerrm() returns#text Получает код
SQLERRMс описанием последнего выданного исключения (см. Таблицу G.96).
G.8.4. Пример #
DO $$
DECLARE
request utl_http.req;
response utl_http.resp;
text_body text;
BEGIN
CALL utl_http.set_body_charset('WIN1251');
request := utl_http.begin_request('https://postgrespro.ru/', 'GET');
CALL utl_http.set_authentication(request, 'admin', 'qwerty', 'Basic', FALSE);
response := utl_http.get_response(request);
CALL utl_http.read_text(response, text_body);
text_body = substring(text_body FROM 720 FOR 245);
RAISE NOTICE '%', text_body;
END$$;Схему utl_http можно явно задать в параметре search_path и опускать в теле запроса:
SET search_path =utl_http, public;
Тогда пример выше будет выглядеть так:
DO $$
DECLARE
request req;
response resp;
text_body text;
BEGIN
CALL set_body_charset('WIN1251');
request := begin_request('https://postgrespro.ru/docs/enterprise/17/utl-http', 'GET');
CALL set_authentication(request, 'admin', 'qwerty', 'Basic', FALSE);
response := get_response(request);
CALL read_text(response, text_body);
text_body = substring(text_body FROM 720 FOR 245);
RAISE NOTICE '%', text_body;
END$$;