F.62. pgsql-http — HTTP-клиент для Tantor SE#
F.62. pgsql-http — HTTP-клиент для Tantor SE #
Версия: 1.6.0
F.62.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.62.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 в результирующий набор с помощью функции unnest() массива в Tantor SE. После этого вы выбираете нужный вам заголовок.
F.62.4. Функции #
http_header(field VARCHAR, value VARCHAR)возвращаетhttp_headerhttp(request http_request)returnshttp_responsehttp_get(uri VARCHAR)returnshttp_responsehttp_get(uri VARCHAR, data JSONB)возвращаетhttp_responsehttp_post(uri VARCHAR, content VARCHAR, content_type VARCHAR)возвращаетhttp_responsehttp_post(uri VARCHAR, data JSONB)возвращаетhttp_responsehttp_put(uri VARCHAR, content VARCHAR, content_type VARCHAR)возвращаетhttp_responsehttp_patch(uri VARCHAR, content VARCHAR, content_type VARCHAR)возвращаетhttp_responsehttp_delete(uri VARCHAR, content VARCHAR, content_type VARCHAR))возвращаетhttp_responsehttp_head(uri VARCHAR)returnshttp_responsehttp_set_curlopt(curlopt VARCHAR, value varchar)возвращаетbooleanhttp_reset_curlopt()returnsbooleanhttp_list_curlopt()возвращаетsetof(curlopt text, value text)urlencode(string VARCHAR)возвращаетtexturlencode(data JSONB)возвращаетtext
F.62.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.62.6. Сохранение активности и таймауты #
Рекомендуется использовать подход http_reset_curlopt(),
описанный выше. Глобальные переменные, перечисленные ниже, будут
устаревать и постепенно удаляться.
По умолчанию каждый запрос использует новое соединение и гарантирует, что соединение закрывается, когда запрос завершается. Это поведение снижает вероятность использования системных ресурсов (сокетов), поскольку расширение работает в течение продолжительного времени.
Высокопроизводительные приложения могут захотеть включить keep-alive и сохранение соединения для снижения задержки и увеличения пропускной способности. Следующая переменная GUC изменяет поведение расширения http для поддержки соединений как можно дольше:
http.keepalive = 'on'
По умолчанию установлен временный тайм-аут выполнения запроса в 5 секунд. Если требуется другое время ожидания, можно использовать следующую переменную GUC для его установки в миллисекундах:
http.timeout_msec = 200
F.62.7. Почему это плохая идея #
“Что произойдет, если веб-страница займет много времени для возврата?” Ваш SQL-запрос просто будет ждать, пока это не произойдет. Убедитесь, что ваш веб-сервис быстро отказывает. Или (опасно по-другому) выполните ваш запрос в pg_background.
“Что если веб-страница возвращает мусор?” Ваш SQL-запрос должен проверить наличие мусора перед выполнением каких-либо действий с данными.
“Что если веб-страница никогда не вернется?” Установите короткий таймаут, или отправьте отмену запроса, или просто ждите бесконечно.
“Что, если пользователь запрашивает страницу, которую не следует запрашивать?” Ограничьте доступ к функциям или просто не устанавливайте такое расширение, где пользователи могут получить к нему доступ.