F.48. pgsql-http PostgreSQL HTTP клиент#
F.48. pgsql-http PostgreSQL HTTP клиент #
F.48.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://httpbin.org/ip');
content ----------------------------- {"origin":"24.69.186.43"} (1 row)
Выполните GET-запрос с заголовком Authorization.
SELECT content::json->'headers'->>'Authorization' FROM http(( 'GET', 'http://httpbin.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://httpbin.org/');
status | content_type --------+-------------------------- 200 | text/html; charset=utf-8 (1 row)
Показать все заголовки http_header
в объекте http_response
.
SELECT (unnest(headers)).* FROM http_get('http://httpbin.org/');
field | value ----------------------------------+------------------------------- Connection | close Server | meinheld/0.6.1 Date | Tue, 09 Jan 2018 18:40:30 GMT Content-Type | text/html; charset=utf-8 Content-Length | 13011 Access-Control-Allow-Origin | * Access-Control-Allow-Credentials | true X-Powered-By | Flask X-Processed-Time | 0.0208520889282 Via | 1.1 vegur
Используйте команду PUT для отправки простого текстового документа на сервер.
SELECT status, content_type, content::json->>'data' AS data FROM http_put('http://httpbin.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://httpbin.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://httpbin.org/delete');
status | content_type | url --------+------------------+--------------------------- 200 | application/json | http://httpbin.org/delete
В качестве ярлыка для отправки данных в GET-запросе передайте аргумент данных JSONB.
SELECT status, content::json->'args' AS args FROM http_get('http://httpbin.org/get', jsonb_build_object('myvar','myval','foo','bar'));
Для отправки POST-запроса на URL с использованием данных вместо параметров, встроенных в URL, закодируйте данные в формате JSONB в качестве данных запроса.
SELECT status, content::json->'form' AS form FROM http_post('http://httpbin.org/post', jsonb_build_object('myvar','myval','foo','bar'));
Для доступа к двоичному содержимому необходимо преобразовать содержимое из стандартного представления varchar
в представление bytea
с помощью функции textsend
. Использование стандартного приведения varchar::bytea
не сработает, так как приведение остановится при обнаружении байта со значением ноль (что часто встречается в двоичных данных).
WITH http AS ( SELECT * FROM http_get('http://httpbin.org/image/png') ), headers AS ( SELECT (unnest(headers)).* FROM http ) SELECT http.content_type, length(textsend(http.content)) AS length_binary, headers.value AS length_headers FROM http, headers WHERE field = 'Content-Length';
content_type | length_binary | length_headers --------------+---------------+---------------- image/png | 8090 | 8090
Для доступа только к заголовкам вы можете выполнить 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 --------+----------------------------------------------------------- 302 | http://www.google.ch/?gfe_rd=cr&ei=ACESWLy_KuvI8zeghL64Ag
F.48.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.48.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.48.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 [email protected]'); SELECT status, content::json ->> 'user-agent' FROM http_get('http://httpbin.org/user-agent');
status | user_agent --------+----------------------------------------------------------- 200 | Examplebot/2.1 (+http://www.example.com/bot.html) Contact [email protected]
F.48.6. Сохранение активности и таймауты #
Рекомендуется использовать подход http_reset_curlopt()
,
описанный выше. Глобальные переменные, перечисленные ниже, будут
устаревать и постепенно удаляться.
По умолчанию каждый запрос использует новое соединение и гарантирует, что соединение закрывается, когда запрос завершается. Это поведение снижает вероятность использования системных ресурсов (сокетов), поскольку расширение работает в течение продолжительного времени.
Высокопроизводительные приложения могут захотеть включить keep-alive и сохранение соединения для снижения задержки и увеличения пропускной способности. Следующая переменная GUC изменяет поведение расширения http для поддержки соединений как можно дольше:
http.keepalive = 'on'
По умолчанию установлен временный тайм-аут выполнения запроса в 5 секунд. Если требуется другое время ожидания, можно использовать следующую переменную GUC для его установки в миллисекундах:
http.timeout_msec = 200
F.48.7. Почему это плохая идея #
“Что произойдет, если веб-страница займет много времени для возврата?” Ваш SQL-запрос просто будет ждать, пока это не произойдет. Убедитесь, что ваш веб-сервис быстро отказывает. Или (опасно по-другому) выполните ваш запрос в pg_background.
“Что если веб-страница возвращает мусор?” Ваш SQL-запрос должен проверить наличие мусора перед выполнением каких-либо действий с данными.
“Что если веб-страница никогда не вернется?” Установите короткий таймаут, или отправьте отмену запроса, или просто ждите бесконечно.
“Что, если пользователь запрашивает страницу, которую не следует запрашивать?” Ограничьте доступ к функциям или просто не устанавливайте такое расширение, где пользователи могут получить к нему доступ.