pg_net:异步网络
pg_net API 还在测试阶段。函数签名可能会改变。
🌐 The pg_net API is in beta. Functions signatures may change.
pg_net 使 Postgres 可以在 SQL 中进行异步的 HTTP/HTTPS 请求。它与 http 扩展的不同之处在于,它默认就是异步的。这在阻塞函数(例如触发器)中非常有用。
它无需服务器不断轮询数据库的变化,而是让数据库主动通知外部资源重要事件。
🌐 It eliminates the need for servers to continuously poll for database changes and instead allows the database to proactively notify external resources about significant events.
启用扩展 #
🌐 Enable the extension
- 在仪表板中转到数据库页面。
- 点击侧边栏的 扩展。
- 搜索“pg_net”并启用这个扩展。
http_get#
创建一个 HTTP GET 请求并返回请求的 ID。HTTP 请求在事务提交之前不会启动。
🌐 Creates an HTTP GET request returning the request's ID. HTTP requests are not started until the transaction is committed.
签名 #
🌐 Signature [#get-signature]
这是一个 Postgres 安全定义者 函数。
🌐 This is a Postgres SECURITY DEFINER function.
net.http_get( -- url for the request url text, -- key/value pairs to be url encoded and appended to the `url` params jsonb default '{}'::jsonb, -- key/values to be included in request headers headers jsonb default '{}'::jsonb, -- the maximum number of milliseconds the request may take before being canceled timeout_milliseconds int default 2000) -- request_id reference returns bigint strict volatile parallel safe language plpgsql使用情况 #
🌐 Usage [#get-usage]
select net.http_get('https://news.ycombinator.com') as request_id;request_id---------- 1(1 row)http_post#
创建一个带有 JSON 内容的 HTTP POST 请求,并返回请求的 ID。HTTP 请求只有在事务提交后才会开始。
🌐 Creates an HTTP POST request with a JSON body, returning the request's ID. HTTP requests are not started until the transaction is committed.
主体的字符集编码与数据库的 server_encoding 设置相匹配。
🌐 The body's character set encoding matches the database's server_encoding setting.
签名 #
🌐 Signature [#post-signature]
这是一个 Postgres 安全定义者 函数
🌐 This is a Postgres SECURITY DEFINER function
net.http_post( -- url for the request url text, -- body of the POST request body jsonb default '{}'::jsonb, -- key/value pairs to be url encoded and appended to the `url` params jsonb default '{}'::jsonb, -- key/values to be included in request headers headers jsonb default '{"Content-Type": "application/json"}'::jsonb, -- the maximum number of milliseconds the request may take before being canceled timeout_milliseconds int default 2000) -- request_id reference returns bigint volatile parallel safe language plpgsql使用 #
🌐 Usage [#post-usage]
select net.http_post( url:='https://httpbin.org/post', body:='{"hello": "world"}'::jsonb ) as request_id;request_id---------- 1(1 row)http_delete#
创建一个 HTTP DELETE 请求,并返回请求的 ID。HTTP 请求直到事务提交后才会开始。
🌐 Creates an HTTP DELETE request, returning the request's ID. HTTP requests are not started until the transaction is committed.
签名 #
🌐 Signature [#post-signature]
这是一个 Postgres 安全定义者 函数
🌐 This is a Postgres SECURITY DEFINER function
net.http_delete( -- url for the request url text, -- key/value pairs to be url encoded and appended to the `url` params jsonb default '{}'::jsonb, -- key/values to be included in request headers headers jsonb default '{}'::jsonb, -- the maximum number of milliseconds the request may take before being canceled timeout_milliseconds int default 2000) -- request_id reference returns bigint strict volatile parallel safe language plpgsql security definer使用 #
🌐 Usage [#delete-usage]
select net.http_delete( 'https://dummy.restapiexample.com/api/v1/delete/2' ) as request_id;---------- 1(1 row)分析回应 #
🌐 Analyzing responses
等待的请求存储在 net.http_request_queue 表中。执行后,它们会被删除。
🌐 Waiting requests are stored in the net.http_request_queue table. Upon execution, they are deleted.
CREATE UNLOGGED TABLE net.http_request_queue ( id bigint NOT NULL DEFAULT nextval('net.http_request_queue_id_seq'::regclass), method text NOT NULL, url text NOT NULL, headers jsonb NOT NULL, body bytea NULL, timeout_milliseconds integer NOT NULL )一旦有响应返回,默认情况下,它会在 net._http_response 表中存储 6 个小时。
🌐 Once a response is returned, by default, it is stored for 6 hours in the net._http_response table.
CREATE UNLOGGED TABLE net._http_response ( id bigint NULL, status_code integer NULL, content_type text NULL, headers jsonb NULL, content text NULL, timed_out boolean NULL, error_msg text NULL, created timestamp with time zone NOT NULL DEFAULT now() )可以用以下查询来观察这些响应:
🌐 The responses can be observed with the following query:
select * from net._http_response;这些数据也可以在 net 模式下通过 Supabase 仪表板的 SQL 编辑器 进行查看
🌐 The data can also be observed in the net schema with the Supabase Dashboard's SQL Editor
调试请求 #
🌐 Debugging requests
检查请求数据 #
🌐 Inspecting request data
Postman Echo API 会返回一个与请求内容相同的响应。你可以用它来查看发送的数据。
🌐 The Postman Echo API returns a response with the same body and content as the request. It can be used to inspect the data being sent.
向回声 API 发送一个 POST 请求
🌐 Sending a post request to the echo API
select net.http_post( url := 'https://postman-echo.com/post', body := '{"key1": "value", "key2": 5}'::jsonb ) as request_id;检查回声 API 响应内容,确保它包含正确的主体
🌐 Inspecting the echo API response content to ensure it contains the right body
select "content"from net._http_responsewhere id = <request_id>-- returns information about the request-- including the body sent: {"key": "value", "key": 5}另外,通过将请求封装在一个数据库函数中,发送的行数据可以被记录或返回以供检查和调试。
🌐 Alternatively, by wrapping a request in a database function, sent row data can be logged or returned for inspection and debugging.
create or replace function debugging_example (row_id int)returns jsonb as $$declare -- Store payload data row_data_var jsonb;begin -- Retrieve row data and convert to JSON select to_jsonb("<example_table>".*) into row_data_var from "<example_table>" where "<example_table>".id = row_id; -- Initiate HTTP POST request to URL perform net.http_post( url := 'https://postman-echo.com/post', -- Use row data as payload body := row_data_var ) as request_id; -- Optionally Log row data or other data for inspection in Supabase Dashboard's Postgres Logs raise log 'Logging an entire row as JSON (%)', row_data_var; -- return row data to inspect return row_data_var;-- Handle exceptions here if neededexception when others then raise exception 'An error occurred: %', SQLERRM;end;$$ language plpgsql;-- calling functionselect debugging_example(<row_id>);检查失败的请求 #
🌐 Inspecting failed requests
查找所有失败的请求
🌐 Finds all failed requests
select *from net._http_responsewhere "status_code" >= 400 or "error_msg" is not nullorder by "created" desc;配置 #
🌐 Configuration
必须使用 pg_net v0.12.0 或更高版本才能重新配置
Supabase 从 v0.12.0+ 开始支持重新配置 pg_net。对于最新版本,可以在 常规设置 中启动 Postgres 升级。
🌐 Supabase supports reconfiguring pg_net starting from v0.12.0+. For the latest release, initiate a Postgres upgrade in the General Settings.
这个扩展被配置为可以可靠地每秒执行最多 200 个请求。响应消息只会存储 6 小时,以防不必要的堆积。默认行为可以通过重写配置变量来修改。
🌐 The extension is configured to reliably execute up to 200 requests per second. The response messages are stored for only 6 hours to prevent needless buildup. The default behavior can be modified by rewriting config variables.
获取当前设置 #
🌐 Get current settings
select "name", "setting"from pg_settingswhere "name" like 'pg_net%';更改设置 #
🌐 Alter settings
你必须在系统级别更改 pg_net 设置。
🌐 You must change the pg_net settings at the system level.
更改这些设置需要超级用户权限。联系支持以获得你想要更改的参数的所需权限,例如:
🌐 Changing these settings requires superuser privileges. Contact Support to have the required permission granted for the parameter you want to change, e.g.:
grant alter system on parameter pg_net.ttl to postgres;一旦权限被分配,在系统级别应用设置并重启后台工作程序:
🌐 Once the privilege is assigned, apply the setting at the system level and restart the background worker:
alter system set pg_net.ttl to '24 hours';select net.worker_restart();示例 #
🌐 Examples
调用 Supabase Edge 函数 #
🌐 Invoke a Supabase Edge Function
向 Supabase Edge Function 发送带有认证头和 JSON 请求体的 POST 请求:
🌐 Make a POST request to a Supabase Edge Function with auth header and JSON body payload:
select net.http_post( url:='https://project-ref.supabase.co/functions/v1/function-name', headers:='{"Content-Type": "application/json", "apikey": "<SUPABASE_PUBLISHABLE_KEY>"}'::jsonb, body:='{"name": "pg_net"}'::jsonb ) as request_id;用 pg_cron#
🌐 Call an endpoint every minute with pg_cron
pg_cron 扩展让 Postgres 可以变成自己的 cron 服务器。借助它,你可以以最小一分钟的精度定期调用接口。
🌐 The pg_cron extension enables Postgres to become its own cron server. With it you can schedule regular calls with up to a minute precision to endpoints.
select cron.schedule( 'cron-job-name', '* * * * *', -- Executes every minute (cron syntax) $$ -- SQL query select "net"."http_post"( -- URL of Edge function url:='https://project-ref.supabase.co/functions/v1/function-name', headers:='{"apikey": "<SUPABASE_PUBLISHABLE_KEY>"}'::jsonb, body:='{"name": "pg_net"}'::jsonb ) as "request_id"; $$);在触发器中执行 pg_net #
🌐 Execute pg_net in a trigger
当触发事件发生时,向外部端点发起一次调用。
🌐 Make a call to an external endpoint when a trigger event occurs.
-- function called by triggercreate or replace function <function_name>() returns trigger language plpgSQLas $$begin -- calls pg_net function net.http_post -- sends request to postman API perform "net"."http_post"( 'https://postman-echo.com/post'::text, jsonb_build_object( 'old_row', to_jsonb(old.*), 'new_row', to_jsonb(new.*) ), headers:='{"Content-Type": "application/json"}'::jsonb ) as request_id; return new;END $$;-- trigger for table updatecreate trigger <trigger_name> after update on <table_name> for each row execute function <function_name>();一次发送多行表格 #
🌐 Send multiple table rows in one request
with "selected_table_rows" as ( select -- Converts all the rows into a JSONB array jsonb_agg(to_jsonb(<table_name>.*)) as JSON_payload from <table_name> -- good practice to LIMIT the max amount of rows)select net.http_post( url := 'https://postman-echo.com/post'::text, body := JSON_payload ) AS request_idFROM "selected_table_rows";更多示例可以在扩展的GitHub页面上看到
🌐 More examples can be seen on the Extension's GitHub page
权限 #
🌐 Permissions
默认情况下,net 模式会授予 USAGE 给 PUBLIC。因此,anon 和 authenticated 会继承对 net.http_request_queue、net._http_response 及其相关序列的直接对象级访问权限(例如 SELECT)。
🌐 By default, the net schema grants USAGE to PUBLIC. As a result, anon and authenticated
inherit direct object-level access (for example, SELECT) on net.http_request_queue,
net._http_response, and their associated sequences.
这不会把请求数据暴露给未认证或客户端的用户,有两个原因:
🌐 This doesn't expose request data to unauthenticated or client-side users, for two reasons:
net不能通过 Data API 访问,所以匿名/可公开的密钥无法通过 API 访问或修改它的对象。anon和authenticated是NOLOGIN角色,所以他们不能建立直接的数据库连接。
故障排除 #
🌐 Troubleshooting
安全顾问可能会报告 pg_net 已安装在 public 架构中。Postgres 将该扩展定义为不可迁移,所以 alter extension pg_net set schema extensions 不能移动它。相反,需要删除该扩展并在 extensions 架构中创建它:
🌐 The Security Advisor might report that pg_net is installed in the public schema. Postgres defines the extension as non-relocatable, so alter extension pg_net set schema extensions can't move it. Instead, drop the extension and create it in the extensions schema:
删除 pg_net 会移除其扩展拥有的对象,包括 net.http_request_queue 和 net._http_response。如果请求队列是空的,则不会丢失任何待处理的请求。如果队列中有待处理的 HTTP 请求,这些请求会被删除,不会被发送。存储的响应也会被删除。在继续操作之前,请保留你需要的任何响应数据。
🌐 Dropping pg_net removes its extension-owned objects, including net.http_request_queue and net._http_response. If the request queue is empty, no pending requests are lost. If the queue contains pending HTTP requests, those requests are deleted and aren't sent. Stored responses are also deleted. Preserve any response data you need before continuing.
在 SQL 编辑器 中运行以下命令:
🌐 Run the following commands in the SQL Editor:
-- Ensure the target schema existscreate schema if not exists extensions;-- Drop the existing extensiondrop extension pg_net;-- Re-create the extension in the extensions schemacreate extension pg_net with schema extensions;限制 #
🌐 Limitations
- 为了提高速度和性能,请求和响应会存储在未记录表中,这些表在系统崩溃或非正常关闭时不会被保留。
- 默认情况下,响应数据只会保存 6 小时
- 只能使用 JSON 数据进行 POST 请求,不支持其他数据格式
- 设计最多处理每秒200个请求。提高速率可能会导致不稳定
- 不支持PATCH/PUT请求
- 一次只能处理一个数据库。默认使用
postgres数据库。
资源 #
🌐 Resources