F.49. pgsql-http PostgreSQL HTTP клиент#
F.49. pgsql-http PostgreSQL HTTP клиент #
F.49.2. Примеры #
URL кодирование строки.
SELECT urlencode('my special string''s & things?');
urlencode ------------------------------------- my+special+string%27s+%26+things%3F (1 row)
URL кодирование ассоциативного массива JSON.
SELECT urlencode(jsonb_build_object('name','Colin & James','rate','50%'));
urlencode ------------------------------------- name=Colin+%26+James&rate=50%25 (1 row)
Выполните GET-запрос и просмотрите содержимое.
SELECT content FROM http_get('http://httpbun.org/ip');
content ----------------------------- {"origin":"24.69.186.43"} (1 row)
Выполните GET-запрос с заголовком Authorization.
SELECT content::json->'headers'->>'Authorization' FROM http(( 'GET', 'http://httpbun.org/headers', ARRAY[http_header('Authorization','Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9')], NULL, NULL )::http_request);
content ---------------------------------------------- Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 (1 row)
Прочитайте поля status
и content
из объекта http_response
.
SELECT status, content_type FROM http_get('http://httpbun.org/');
status | content_type --------+-------------------------- 200 | text/html; charset=utf-8 (1 row)
Показать все заголовки http_header
в объекте http_response
.
SELECT (unnest(headers)).* FROM http_get('http://httpbun.org/');
field | value ------------------+-------------------------------------------------- Server | nginx Date | Wed, 26 Jul 2023 19:52:51 GMT Content-Type | text/html Content-Length | 162 Connection | close Location | https://httpbun.org server | nginx date | Wed, 26 Jul 2023 19:52:51 GMT content-type | text/html x-powered-by | httpbun/3c0dc05883dd9212ac38b04705037d50b02f2596 content-encoding | gzip
Используйте команду PUT для отправки простого текстового документа на сервер.
SELECT status, content_type, content::json->>'data' AS data FROM http_put('http://httpbun.org/put', 'some text', 'text/plain');
status | content_type | data --------+------------------+----------- 200 | application/json | some text
Используйте команду PATCH для отправки простого JSON-документа на сервер.
SELECT status, content_type, content::json->>'data' AS data FROM http_patch('http://httpbun.org/patch', '{"this":"that"}', 'application/json');
status | content_type | data --------+------------------+------------------ 200 | application/json | '{"this":"that"}'
Используйте команду DELETE для запроса удаления ресурса.
SELECT status, content_type, content::json->>'url' AS url FROM http_delete('http://httpbun.org/delete');
status | content_type | url --------+------------------+--------------------------- 200 | application/json | http://httpbun.org/delete
В качестве ярлыка для отправки данных в GET-запросе передайте аргумент данных JSONB.
SELECT status, content::json->'args' AS args FROM http_get('http://httpbun.org/get', jsonb_build_object('myvar','myval','foo','bar'));
Для отправки POST-запроса на URL с использованием данных вместо параметров, встроенных в URL, закодируйте данные в формате JSONB в качестве данных запроса.
SELECT status, content::json->'form' AS form FROM http_post('http://httpbun.org/post', jsonb_build_object('myvar','myval','foo','bar'));
Чтобы получить доступ к двоичному содержимому, вы должны преобразовать содержимое из
представления по умолчанию varchar
в
представление bytea
с использованием функции
text_to_bytea
. Использование приведения по умолчанию
varchar::bytea
не сработает, так как приведение
остановится при первом встреченном байте со значением ноль (что часто встречается
в двоичных данных).
WITH http AS ( SELECT * FROM http_get('https://httpbingo.org/image/png') ), headers AS ( SELECT (unnest(headers)).* FROM http ) SELECT http.content_type, length(text_to_bytea(http.content)) AS length_binary, headers.value AS length_headers FROM http, headers WHERE field ilike 'Content-Type';
content_type | length_binary | length_headers --------------+---------------+---------------- image/png | 8090 | 8090
Аналогично, при использовании POST для отправки двоичного содержимого bytea
в сервис, используйте функцию bytea_to_text
для подготовки содержимого.
Для доступа только к заголовкам вы можете выполнить HEAD-запрос. Это не будет следовать перенаправлениям.
SELECT http.status, headers.value AS location FROM http_head('http://google.com') AS http LEFT OUTER JOIN LATERAL (SELECT value FROM unnest(http.headers) WHERE field = 'Location') AS headers ON true;
status | location --------+------------------------ 301 | http://www.google.com/
F.49.3. Концепции #
Каждый HTTP-запрос состоит из http_request
и http_response
.
Composite type "public.http_request" Column | Type | Modifiers --------------+-------------------+----------- method | http_method | uri | character varying | headers | http_header[] | content_type | character varying | content | character varying | Composite type "public.http_response" Column | Type | Modifiers --------------+-------------------+----------- status | integer | content_type | character varying | headers | http_header[] | content | character varying |
Утилитарные функции, http_get()
,
http_post()
, http_put()
,
http_delete()
и
http_head()
являются просто обертками вокруг основной
функции, http(http_request)
, которая возвращает
http_response
.
Поле headers
для запросов и ответов является
массивом Tantor SE типа
http_header
, который представляет собой простой кортеж.
Composite type "public.http_header" Column | Type | Modifiers --------+-------------------+----------- field | character varying | value | character varying |
Как видно из примеров, вы можете развернуть массив кортежей
http_header
в результирующий набор, используя
Tantor SE
функцию unnest()
на массиве. Оттуда вы
выбираете конкретный заголовок, который вас интересует.
F.49.4. Функции #
http_header(field VARCHAR, value VARCHAR)
возвращаетhttp_header
http(request http_request)
returnshttp_response
http_get(uri VARCHAR)
returnshttp_response
http_get(uri VARCHAR, data JSONB)
возвращаетhttp_response
http_post(uri VARCHAR, content VARCHAR, content_type VARCHAR)
возвращаетhttp_response
http_post(uri VARCHAR, data JSONB)
возвращаетhttp_response
http_put(uri VARCHAR, content VARCHAR, content_type VARCHAR)
возвращаетhttp_response
http_patch(uri VARCHAR, content VARCHAR, content_type VARCHAR)
возвращаетhttp_response
http_delete(uri VARCHAR, content VARCHAR, content_type VARCHAR))
возвращаетhttp_response
http_head(uri VARCHAR)
returnshttp_response
http_set_curlopt(curlopt VARCHAR, value varchar)
возвращаетboolean
http_reset_curlopt()
returnsboolean
http_list_curlopt()
возвращаетsetof(curlopt text, value text)
urlencode(string VARCHAR)
возвращаетtext
urlencode(data JSONB)
возвращаетtext
F.49.5. Опции CURL #
Выберите опции CURL, доступные для установки с помощью функции http_set_curlopt(curlopt VARCHAR, value varchar)
.
Например,
-- Set the PROXYPORT option SELECT http_set_curlopt('CURLOPT_PROXYPORT', '12345'); -- List all currently set options SELECT * FROM http_list_curlopt();
Установит опцию порта прокси для времени жизни соединения с базой данных. Вы можете сбросить все опции CURL до их значений по умолчанию, используя функцию http_reset_curlopt()
.
Использование этого расширения в качестве фонового автоматизированного процесса без надзора (например, в качестве триггера) может иметь непредвиденные последствия для других серверов. Считается хорошей практикой предоставлять контактную информацию в своих запросах, чтобы администраторы могли связаться с вами в случае выхода ваших HTTP-вызовов из-под контроля.
Определенные политики API (например, политика User-Agent Викимедиа) могут требовать даже обмена определенной контактной информацией с каждым запросом. Другие могут запрещать (с помощью robots.txt
) определенным агентам, которых они не распознают.
Для таких случаев вы можете установить опцию CURLOPT_USERAGENT
.
SELECT http_set_curlopt('CURLOPT_USERAGENT', 'Examplebot/2.1 (+http://www.example.com/bot.html) Contact abuse@example.com'); SELECT status, content::json ->> 'user-agent' FROM http_get('http://httpbun.org/user-agent');
status | user_agent --------+----------------------------------------------------------- 200 | Examplebot/2.1 (+http://www.example.com/bot.html) Contact abuse@example.com
F.49.6. Сохранение активности и таймауты #
Рекомендуется использовать подход http_reset_curlopt()
,
описанный выше. Глобальные переменные, перечисленные ниже, будут
устаревать и постепенно удаляться.
По умолчанию каждый запрос использует новое соединение и гарантирует, что соединение закрывается, когда запрос завершается. Это поведение снижает вероятность использования системных ресурсов (сокетов), поскольку расширение работает в течение продолжительного времени.
Высокопроизводительные приложения могут захотеть включить keep-alive и сохранение соединения для снижения задержки и увеличения пропускной способности. Следующая переменная GUC изменяет поведение расширения http для поддержки соединений как можно дольше:
http.keepalive = 'on'
По умолчанию установлен временный тайм-аут выполнения запроса в 5 секунд. Если требуется другое время ожидания, можно использовать следующую переменную GUC для его установки в миллисекундах:
http.timeout_msec = 200
F.49.7. Почему это плохая идея #
“Что произойдет, если веб-страница займет много времени для возврата?” Ваш SQL-запрос просто будет ждать, пока это не произойдет. Убедитесь, что ваш веб-сервис быстро отказывает. Или (опасно по-другому) выполните ваш запрос в pg_background.
“Что если веб-страница возвращает мусор?” Ваш SQL-запрос должен проверить наличие мусора перед выполнением каких-либо действий с данными.
“Что если веб-страница никогда не вернется?” Установите короткий таймаут, или отправьте отмену запроса, или просто ждите бесконечно.
“Что, если пользователь запрашивает страницу, которую не следует запрашивать?” Ограничьте доступ к функциям или просто не устанавливайте такое расширение, где пользователи могут получить к нему доступ.