F.79. 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 обычно используется следующим образом:

  1. Запрос создаётся функцией begin_request.

  2. Задаются параметры запроса, подробнее они описаны в Подразделе F.79.3.3.

  3. Ответ обрабатывается функцией get_response.

  4. Полученный ответ обрабатывается с использованием процедур из Подраздел F.79.3.4.

F.79.1. Установка #

Расширение utl_http включено в состав Postgres Pro Enterprise как стандартное расширение. Чтобы задействовать utl_http, создайте расширение с помощью следующего запроса:

CREATE EXTENSION utl_http;

F.79.2. Типы данных #

Расширение utl_http предоставляет несколько типов данных:

  • Тип req представляет собой HTTP-запрос.

    CREATE TYPE req AS (
       url           varchar(32767),
       method        varchar(64),
       http_version  varchar(64)
    );

    Таблица F.61. Параметры req

    ПараметрОписание
    urlURL-адрес HTTP-запроса. Задаётся после создания запроса функцией begin_request.
    methodМетод, который будет применяться для ресурса, определяемого URL-адресом. Он задаётся после создания запроса функцией begin_request
    http_versionВерсия HTTP-протокола, используемая для отправки запроса. Она задаётся после создания запроса функцией begin_request.

  • Тип resp представляет собой HTTP-ответ.

    CREATE TYPE resp AS (
       status_code	 integer,
       reason_phrase varchar(256),
       http_version	 varchar(64)
    );

    Таблица F.62. Параметры 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;

    Таблица F.63. Поля типов 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.

F.79.3. Функции и процедуры utl_http #

Обратите внимание, что параметр request_context в функциях и процедурах ниже сохраняется для совместимости при миграции из Oracle и не влияет на результат.

F.79.3.1. Простые HTTP-запросы #

Функции request_function и request_pieces_function берут URL-адрес в виде строки, подключаются к указанному в ней сайту и возвращают данные (обычно HTML), полученные с этого сайта.

request(url text, proxy text default null) returns text #

Получает веб-страницу и возвращает не более первых 2000 байт этой страницы.

request_pieces(url text, max_pieces int default 32767, proxy text default null) returns text #

Эта функция возвращает таблицу PL/pgSQL, состоящую из фрагментов данных по 2000 байт, полученных по заданному URL-адресу. Элементы таблицы, возвращаемые request_pieces, представляют собой последовательные фрагменты данных, полученные в результате HTTP-запроса к этому URL-адресу.

F.79.3.2. Параметры сеанса #

Расширение utl_http предоставляет функции и процедуры для работы с конфигурацией и поведением по умолчанию при выполнении HTTP-запросов в сеансе пользователя базы данных. Когда запрос создаётся, он наследует параметры по умолчанию в отношении поддержки cookie, перенаправления, набора символов тела сообщения и тайм-аута передачи текущего сеанса. Когда создаётся ответ на запрос, он наследует эти параметры из запроса.

set_response_error_check(enable bool default false) #

Эта процедура определяет, будет ли функция get_response выдавать исключение, когда веб-сервер возвращает код состояния, указывающий на ошибку — код состояния в диапазоне 4xx или 5xx.

get_response_error_check(enable bool) #

Эта процедура проверяет, установлена ли проверка ошибок ответа.

set_transfer_timeout(timeout int4 default 60) #

Эта процедура устанавливает значение тайм-аута по умолчанию для всех будущих HTTP-запросов, который должен соблюдаться расширением utl_http перед чтением HTTP-ответа с веб-сервера или прокси-сервера. Это значение тайм-аута можно использовать, чтобы избежать блокировки программ при загрузке веб-серверов или интенсивном сетевом трафике во время получения получении веб-страниц с веб-серверов. Значение тайм-аута по умолчанию — 60 секунд.

get_transfer_timeout(timeout int4) #

Эта процедура получает значение тайм-аута по умолчанию для всех будущих HTTP-запросов.

set_detailed_excp_support(enable bool default false) #

Эта процедура определяет, выдаёт ли расширение utl_http подробное исключение. По умолчанию она выдаёт исключение REQUEST_FAILED при сбое HTTP-запроса. Используйте get_detailed_sqlcode и get_detailed_sqlerrm для получения более подробной информации об ошибке.

Доступные исключения перечислены в Таблице F.64.

Таблица F.64. Исключения 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_request HTTP-прокси возвращает код состояния в диапазоне 4xx при выполнении HTTPS-запроса через прокси.get_response, begin_request, когда включена выдача подробных исключений
HTTP_SERVER_ERROR29269Код состояния ответа из get_response указывает на то, что произошла ошибка сервера (код состояния в диапазоне 5xx). Из функции begin_request HTTP-прокси возвращает код состояния в диапазоне 5xx при выполнении HTTPS-запроса через прокси.get_response, begin_request, когда включена выдача подробных исключений
REQUEST_FAILED29273Ошибка выполнения запросаЛюбой интерфейс HTTP-запроса или ответа, если отключена выдача подробных исключений

get_detailed_excp_support(enable bool) #

Эта процедура проверяет, выдаст ли utl_http подробное исключение или нет.

F.79.3.3. HTTP-запросы #

Расширение utl_http предоставляет функции и процедуры для запуска HTTP-запроса, работы с атрибутами и отправки информации запроса на веб-сервер. Когда запрос создаётся, он наследует параметры по умолчанию в отношении поддержки cookie, перенаправления, набора символов тела сообщения и тайм-аута передачи текущего сеанса. Параметры можно изменить, вызвав интерфейс запроса.

begin_request(url text, method text default 'GET', http_version text default null, request_context request_context_key default null) returns req #

Эта функция начинает новый HTTP-запрос.

set_header(r req, name text, value text) #

Эта процедура устанавливает заголовок HTTP-запроса для будущего запроса.

set_authentication(r req, username text, password text, scheme text default 'Basic', for_proxy boolean default false) #

Эта процедура устанавливает информацию о HTTP-аутентификации в заголовке HTTP-запроса. Веб-серверу эта информация нужна для авторизации запроса.

set_body_charset(r req, charset name default null) #

Эта процедура устанавливает набор символов, когда тип носителя — text, но набор символов не указан в заголовке Content-Type и может принимать одну из следующих форм:

  • Устанавливает набор символов по умолчанию для тела всех будущих HTTP-запросов.

    set_body_charset(
      charset    IN name DEFAULT NULL)
  • Устанавливает набор символов тела запроса.

    set_body_charset(
    	r					INOUT req,
      charset    IN name DEFAULT NULL)

Эта процедура определяет поддержку 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(r req, max_redirects int4 default 3) #

Эта процедура устанавливает максимальное количество раз, когда utl_http должен следовать инструкции HTTP-перенаправления в HTTP-ответах на запросы в get_response. По умолчанию — 3.

set_proxy(proxy text, no_proxy_domains text) #

Эта процедура устанавливает прокси-сервер, который будет использоваться для HTTP-запросов или других протоколов.

write_raw(r req, data bytea) #

Эта процедура записывает двоичные данные в тело HTTP-запроса для будущего запроса.

write_text(r req, data text) #

Эта процедура записывает текстовые данные в тело HTTP-запроса для будущего запроса.

end_request(r req) #

Эта процедура завершает HTTP-ответ путём сброса параметров запроса.

F.79.3.4. HTTP-ответы #

Расширение utl_http предоставляет функции и процедуры для управления HTTP-ответом, полученным из get_response, и получения информации об ответе от веб-сервера. Когда создаётся ответ на запрос, он наследует параметры поддержки cookie, перенаправления, набора символов тела сообщения и тайм-аута передачи из запроса. Вызвав интерфейс ответа, можно изменить только набор символов тела.

end_response(r resp) #

Эта процедура завершает HTTP-ответ путём сброса параметров запроса.

get_authentication(r resp, scheme text, realm text, for_proxy bool default false) #

Эта процедура получает информацию о HTTP-аутентификации, необходимую для принятия запроса веб-сервером, как указано в заголовке HTTP-ответа.

get_header(r resp, n int4, name text, value text) #

Эта процедура возвращает n-е имя заголовка HTTP-ответа и значение, возвращаемое в ответе.

get_header_by_name(r resp, name text, value text, n int4 default 1) #

Эта процедура возвращает значение заголовка HTTP-ответа, возвращаемое в ответе, по заданному имени заголовка.

get_header_count(r resp) returns int4 #

Эта функция возвращает количество заголовков HTTP-ответа, возвращаемых в ответе.

get_response(r req, return_info_response bool default false) returns resp #

Эта функция завершает HTTP-запрос и ответ: читает HTTP-ответ и обрабатывает строку состояния и заголовки ответа. Код состояния, описание причины и версия HTTP-протокола сохраняются в записи ответа.

read_raw(r resp, data bytea, len int4 default null) #

Эта процедура считывает тело HTTP-ответа в двоичной форме и возвращает выходные данные в буфер со стороны вызывающего.

read_line(r resp, data text, remove_crlf bool default false) #

Эта процедура считывает тело HTTP-ответа в текстовой форме до конца строки, и возвращает выходные данные в буфер со стороны вызывающего.

read_text(r resp, data text, len int4 default null) #

Эта процедура считывает тело HTTP-ответа в текстовой форме и возвращает выходные данные в буфер со стороны вызывающего.

F.79.3.5. Данные cookie HTTP #

Расширение utl_http предоставляет функции и процедуры для управления cookie.

add_cookies(cookies cookie_table, request_context request_context_key default null) #

Эта процедура добавляет cookie, поддерживаемые расширением utl_http.

clear_cookies(request_context request_context_key default null) #

Эта процедура удаляет все cookie с которые в настоящее время работает расширение utl_http.

Эта функция возвращает объём cookie, с которым и в настоящее время работает расширение utl_http для всех веб-серверов.

get_cookies(cookies cookie_table, request_context request_context_key default null) returns cookie_table #

Эта функция возвращает полный объём cookie, с которым в настоящее время работает расширение utl_http для всех веб-серверов.

F.79.3.6. Условия возникновения ошибок #

Расширение utl_http предоставляет функции для получения информации об ошибках.

get_detailed_sqlcode() returns int4 #

Получает код SQLCODE с описанием последнего выданного исключения (см. Таблицу F.64).

get_detailed_sqlerrm() returns text #

Получает код SQLERRM с описанием последнего выданного исключения (см. Таблицу F.64).

F.79.4. Пример #

DO $$
DECLARE
    request         req;
    response        resp;
    text_body       text;
BEGIN
    CALL SET_BODY_CHARSET('WIN1251');
    request := begin_request('http://localhost2/', '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$$;