交易记录#

之后 用户模拟 ,每个对 API resource 在事务内部运行。交易的顺序如下:

START TRANSACTION; -- <Access Mode> <Isolation Level>
-- <Transaction-scoped settings>
-- <Main Query>
END; -- <Transaction End>

访问模式#

访问模式决定了交易是否可以修改数据库。有两个可能的值:只读和读写。

不可能在只读事务中修改数据库。PostgREST使用这一事实在GET和HEAD请求中强制执行HTTP语义。请考虑以下事项:

CREATE SEQUENCE callcounter_count START 1;

CREATE VIEW callcounter AS
SELECT nextval('callcounter_count');

自.以来 callcounter VIEW修改了序列,使用GET或HEAD调用它将导致错误:

curl "http://localhost:3000/callcounter"
HTTP/1.1 405 Method Not Allowed

{"code":"25006","details":null,"hint":null,"message":"cannot execute nextval() in a read-only transaction"}

表和视图的访问模式#

访问模式打开 表和视图 由HTTP方法确定。

Http方法

访问模式

去拿,海德

只读

发布、修补、放置、删除

读写

功能上的访问模式#

作为RPC的功能 此外,还取决于功能 volatility

访问模式

Http方法

VOLATILE

STABLE

IMMUTABLE

去拿,海德

只读

只读

只读

POST

读写

只读

只读

备注

  • 波动性标记是关于函数行为的承诺。PostgreSQL将允许您将修改数据库的函数标记为 IMMUTABLESTABLE 没有失败过。但是,由于只读事务,该函数在PostgREST下将失败。

  • 这个 期权方法 方法不会启动事务,因此它在这里不相关。

隔离级别#

每个事务都使用PostgreSQL默认隔离级别:已提交读。除非您修改 default_transaction_isolation 用于模拟的角色或功能。

ALTER ROLE webuser SET default_transaction_isolation TO 'repeatable read';

每个 webuser 获取其使用 default_transaction_isolation 设置为可重复读取。

或更改每个函数调用的隔离级别。

CREATE OR REPLACE FUNCTION myfunc()
RETURNS text as $$
  SELECT 'hello';
$$
LANGUAGE SQL
SET default_transaction_isolation TO 'serializable';

事务作用域设置#

PostgREST使用与事务生存期相关的设置。这些可用于获取有关HTTP请求的数据。或修改HTTP响应。

你可以通过以下方式获得这些 current_setting

-- request settings use the ``request.`` prefix.
SELECT
  current_setting('request.<setting>', true);

您可以将它们设置为 set_config

-- response settings use the ``response.`` prefix.
SELECT
  set_config('response.<setting>', 'value1' ,true);

请求头、Cookie和JWT声明#

PostgREST将标头、cookie和标头存储为JSON。要获得它们,请执行以下操作:

-- To get all the headers sent in the request
SELECT current_setting('request.headers', true)::json;

-- To get a single header, you can use JSON arrow operators
SELECT current_setting('request.headers', true)::json->>'user-agent';

-- value of sessionId in a cookie
SELECT current_setting('request.cookies', true)::json->>'sessionId';

-- value of the email claim in a jwt
SELECT current_setting('request.jwt.claims', true)::json->>'email';

重要

  • 标头名称是小写的。例如,如果请求发送 User-Agent: x 这将可以通过以下方式获得 current_setting('request.headers', true)::json->>'user-agent'

  • 这个 role 在……里面 request.jwt.claims 缺省值为 DB-anon-角色

  • 提交事务后,设置不会变为空,而是设置为空字符串 ''

    • 这是PostgreSQL认为的预期行为。有关更多详细信息,请参阅 this discussion

    • 为了避免这种不一致,您可以创建包装函数,如下所示:

    CREATE FUNCTION my_current_setting(text) RETURNS text
    LANGUAGE SQL AS $$
      SELECT nullif(current_setting($1, true), '');
    $$;
    

请求路径和方法#

路径和方法存储为 text

SELECT current_setting('request.path', true);

SELECT current_setting('request.method', true);

请求角色和搜索路径#

因为. 用户模拟 ,PostgREST制定了标准 role 。你可以通过不同的方式获得这一点:

SELECT current_role;

SELECT current_user;

SELECT current_setting('role', true);

此外,它还设置了 search_path 基于 DB-架构数据库额外搜索路径

响应标头#

您可以设置 response.headers 若要向HTTP响应添加标头,请执行以下操作。例如,下面的语句将向响应添加缓存头:

-- tell client to cache response for two days

SELECT set_config('response.headers',
  '[{"Cache-Control": "public"}, {"Cache-Control": "max-age=259200"}]', true);
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache, no-store, must-revalidate

请注意, response.headers 应设置为 array 单键对象而不是单个多键对象。这是因为像这样的头 Cache-ControlSet-Cookie 设置多个值时需要重复。对象不允许重复的键。

备注

PostgREST提供了标题,如 Content-TypeLocation 等可以用这种方式覆盖。请注意,无论被重写的 Content-Type 响应头,则内容仍将转换为JSON,除非您使用 媒体类型处理程序

响应状态代码#

您可以将 response.status 以覆盖PostgREST提供的默认状态代码。例如,以下函数将替换默认的 200 状态代码。

create or replace function teapot() returns json as $$
begin
  perform set_config('response.status', '418', true);
  return json_build_object('message', 'The requested entity body is short and stout.',
                           'hint', 'Tip it over and pour it out.');
end;
$$ language plpgsql;
curl "http://localhost:3000/rpc/teapot" -i
HTTP/1.1 418 I'm a teapot

{
  "message" : "The requested entity body is short and stout.",
  "hint" : "Tip it over and pour it out."
}

如果状态代码为标准,则PostgREST将完成状态消息( I'm a teapot 在本例中)。

模拟角色设置#

PostgreSQL应用连接角色 (authenticator )设置。此外,PostgREST还应用 impersonated roles 设置为事务作用域设置。这允许对角色进行的操作进行更细粒度的控制。

例如,考虑 statement_timeout 。它允许您中止任何花费超过指定时间的语句。默认情况下,它处于禁用状态。

ALTER ROLE authenticator SET statement_timeout TO '10s';
ALTER ROLE anonymous SET statement_timeout TO '1s';

使用上述设置,所有用户都会获得10秒的全局语句超时 anonymous 用户的超时时间为1秒。

具有特权上下文的设置#

默认情况下,不会应用具有需要权限的上下文的设置。这样我们就不会导致权限错误。有关更多详细信息,请参阅 Understanding Postgres Parameter Context

但是,从PostgreSQL 15开始,您可以通过以下方式授予这些设置的权限:

GRANT SET ON PARAMETER <setting> TO <authenticator>;

功能设置#

除了……之外 模拟角色设置 ,PostgREST还将应用函数设置作为事务作用域设置。这允许函数设置覆盖模拟角色和连接角色设置。

CREATE OR REPLACE FUNCTION myfunc()
RETURNS void as $$
  SELECT pg_sleep(3); -- simulating some long-running process
$$
LANGUAGE SQL
SET statement_timeout TO '4s';

在调用上述函数时(请参见 作为RPC的功能 ),则语句超时将为4秒。

备注

目前,只有 statement_timeout 应用于函数。

主查询#

通过请求生成主查询 表和视图作为RPC的功能 。所有生成的查询都使用预准备语句 (DB-准备好的语句 )。

交易结束#

如果事务没有失败,它将始终以提交结束。除非 DB-TX-END 配置为在任何情况下或有条件地使用 交易结束首选项 。这对于测试目的很有用。

正在中止事务#

任何数据库故障(如失败的约束)都将导致事务回滚。你也可以 RAISE an error inside a function 以引起回滚。

预请求#

预请求是一个可以在 事务作用域设置 都已设置,并且在 主查询 。它通过以下方式启用 数据库-请求前

这提供了修改设置或引发异常以阻止请求完成的机会。

通过预请求设置标头#

例如,让我们为来自Internet Explorer(6或7)浏览器的所有请求添加一些缓存头。

create or replace function custom_headers()
returns void as $$
declare
  user_agent text := current_setting('request.headers', true)::json->>'user-agent';
begin
  if user_agent similar to '%MSIE (6.0|7.0)%' then
    perform set_config('response.headers',
      '[{"Cache-Control": "no-cache, no-store, must-revalidate"}]', false);
  end if;
end; $$ language plpgsql;

-- set this function on postgrest.conf
-- db-pre-request = custom_headers

现在,当您对表或视图发出GET请求时,您将获得缓存头。

curl "http://localhost:3000/people" -i \
 -H "User-Agent: Mozilla/4.01 (compatible; MSIE 6.0; Windows NT 5.1)"