HTTP API

来自 PostgreSQL 维基
跳转到导航跳转到搜索

HTTP API 的优势在于可以通过不支持 PostgreSQL 协议的工具更容易地访问,例如 curl、Web 浏览器、新的编程语言等。

它对 NoSQL 阵营也很有吸引力,他们通常希望*简单*访问。特别是当与 PostgreSQL 新的内置 JSON 类型结合使用时,这些类型可以在 JSON 格式的结果中作为直接嵌套的子对象返回,无需转义。

HTTP+REST 在移动应用程序中更容易使用。目前,如果您想编写一个与 PostgreSQL 交互的 Android 应用程序,例如,您需要通过一个您在某个地方托管的 Web API 中间层来完成。消除这一要求将是一件好事(当然,它不会解决直接公开数据库的安全挑战)。

HTTP REST API 可以使遍历数据库变得非常容易,使其易于发现和探索。

此页面是对 PostgreSQL 扩展的早期草案提案,允许客户端使用 HTTP 而不是 PostgreSQL 专有的协议 (FEBE) 访问数据库。

RESTful URL 与 RPC URL

API 主要遵循 RESTful 原则,许多数据库对象被建模为具有自己 URL 的资源。但是这并不总是合适的;例如,运行查询显然是一个 RPC 操作,这些端点被标记为 RPC 操作(而不是被视为某种资源)。

所有类似 RPC 的操作都应使用 POST HTTP 动词。

会话概念

PostgreSQL 的 FE/BE 协议使用具有强会话概念的长生命周期 TCP/IP 连接。用户会话具有状态,包括可能打开的事务、一堆会话特定的 GUC、任何打开的游标、零个或多个准备好的语句等。

RESTful API 往往是无状态的,但在与 PostgreSQL 交互时这并不实用。在可能的情况下保持尽可能无状态是可取的,但也必须有一种方法将请求链接到特定后端的状态。由于会话极其敏感(想想“SET ROLE”、“SET SESSION AUTHORIZATION”),因此必须确保无法劫持会话。

尚未确定将请求安全、高效、简单地链接到后端会话的设计。待办事项。

一种可能的方法

默认情况下,每个请求都获得自己的会话,如果发生错误,则具有自动提交行为。

但是,连接可以通过以下方式请求会话行为:

  1. 使用 POST 到 /sessions 创建会话将返回一个会话 ID;会话与 TCP 连接相关联。
  2. 在同一 TCP 连接上的后续请求中添加一个标头 X-PostgreSQL-Session-ID: ...
  3. 如果 TCP 连接关闭,则关闭会话并回滚,或者可以使用 POST /sessions/<id>?commit=true|false 特定地结束会话

--Dobesv (讨论) 2013 年 9 月 2 日 17:03 (UTC)

一致性

特定请求方法(如 GETPUT 等)在不同类型对象上的含义应尽可能保持一致。

下面的规范建议在模式上使用 GET 返回模式的 DDL。GET 将是用于请求所有对象的对象的 SQL 定义的动词吗?它应该是吗,因为结果可能非常大?响应是否包含子对象,或者只是对象本身的定义?

API 用户应该知道在不查看特定动词在特定对象上的作用的情况下该期待什么,并且应该能够仅使用来自服务器的响应来遍历数据库结构的树。

如何表示和通信子资源

当请求一个对象时,我们是否应该在响应中提供一个子列表(正如这里大多数 JSON 示例所示)?这很容易并且易于发现,但意味着子对象的发现是特定于响应格式的;例如,您必须解析 JSON 才能获取子对象。

另一种方法是使用 HTTP Link 标头。这些在使用 curl 等工具时并不那么明显,但独立于正文的响应格式。它们允许使用 HEAD 请求来遍历图,而根本不获取正文内容。

同时使用这两种方法始终是一个选项,但这程度的重复在数据库访问协议中并不理想。

父子关系

GET 默认是否应该包含子项,还是不包含?如果包含,它是否应该只包含子项名称列表,还是包含子项的完整递归定义?

这对模式来说尤其棘手,因为 模式可能在一个或多个子项创建时创建,或者这些子项可能在稍后添加。表、函数等是模式 DDL 本身的一部分吗?还是不是?还是只有在它们在 CREATE SCHEMA 语句中与模式同时创建时?

我的观点是:GET 应该默认包含子项列表,但不包含它们的定义,并且模式内的对象是子项,无论如何定义它都不是模式的一部分。

以“public”模式为例,该模式包含表“customer”和“booking”,视图“customer_summary”和函数“safe_delete_customer”,GET 可以返回(如果 GET 返回 SQL)

CREATE SCHEMA public;

或者

CREATE SCHEMA public
  CREATE TABLE customer(
    .. blah ..
  )
  CREATE TABLE booking(
    .. blah ..
  )
  CREATE VIEW customer_summary AS SELECT * FROM customer,
  CREATE FUNCTION safe_delete_customer(customer_id) RETURNS void AS $$
     ... blah ...
  $$ language 'plpgsql';

两种方法都是有效的。我认为这两种方法都难以使用,并使 API 变得不切实际。(CR)

我认为默认值应该可能是最常见/最有用的,然后可以选择自定义它。但是,我不确定最有用/最合适的默认值是什么。--Dobesv (讨论) 2013 年 9 月 2 日 17:03 (UTC)

易于处理响应

我(CR)强烈反对 GET 返回 SQL 语言文本,例如在模式上使用 GET 返回该模式的 SQL DDL。SQL 难以解析和处理;如果客户端需要,他们应该明确地请求它。默认值应该是易于处理的结构化 JSON,其中列出了一个对象及其属性,以及(取决于 children 查询参数)可能包含所有子项的列表或包含所有子项及其属性的递归列表。

以下是如何返回类似于上面的 GET 的内容:

{
  'type': 'schema',
  'name': 'public',
  'owner:' 'joebloggs',
  'children': ['customer', 'booking', 'customer_summary', 'safe_delete_customer']
}

这使客户端能够快速有效地了解他们需要知道的内容。参数可以修改响应,例如

  • ?acls=true 用于在结构化的 JSON 子对象中列出 ACL(*不*是 Pg ACL 文本)
  • children=tables,views 只列出表和视图,而不是函数、序列等
  • children=nonechildren=
  • 类似于 child_detail=all 用于包含子项的完整 JSON 定义,而不仅仅是名称。需要一种方法来获取整个树或第一级,而无需针对 n 个子项进行 n 次查询。
  • 除了“children”数组之外,还可以添加另一个条目,将子项名称映射到子项类型。“children”数组应该保持简单数组,以与其他接口保持一致。

请注意,子项名称是相对 URI。

返回 DDL/SQL(至少作为一种选择)的原因是,这已经是所有现有工具(如 pg_dump 和 psql)的标准 I/O 格式,因此将其输出并传输到不支持 JSON 的另一个工具可能很有用,反之亦然。我可以看到 JSON 响应对想要扫描模式的 API 客户端(如 ORM 工具)的价值。我不确定哪种方法更常用,但 JSON 似乎也是一个不错的默认值。--Dobesv (讨论) 2013 年 9 月 2 日 17:03 (UTC)

身份验证

身份验证机制的设计必须避免创建对跨站点请求伪造 (XSRF) 和其他常见 HTTP 漏洞的漏洞。

如果使用 cookie 或 HTTP Basic/Digest/Cert 身份验证或任何其他可能由浏览器自动呈现凭据的身份验证方法,则需要请求伪造保护。

有关详细信息,请参阅 防止 CSRF 攻击

如果这些安全性较低登录方法不支持,至少在最初阶段,生活可能更简单。--Dobesv (讨论) 2013 年 9 月 2 日 17:03 (UTC)

URL

服务器根目录

URL: /

服务器元数据/版本可在此处获取。

子项:数据库

使用适当的查询参数/Accept 标头,这可能会生成服务器的 pg_dumpall 备份。

CR:IMO,针对服务器根目录的 GET 应该生成关于服务器的 JSON 结构化信息。

GET /

... response ...

{
    'type' : 'server_root',
    'version' : 940,
    'version_human' : '9.4.0',
    'description' : 'PostgreSQL 9.4.0 Server',
    'children' : [ 'db' ]
}

数据库

URL: /databases

(CR:“/db” 而不是“/databases”?这将出现很多次。)

获取数据库列表。

使用适当的查询参数,它可以用于获取所有数据库的 pg_dump。

CR: IMO A pg_dump 是一个 RPC 操作,应该由一个 POST 请求 /?dumpall 并以 JSON 格式的参数作为 payload 来请求;它不应该是简单的 GET,因为有许多不同的方式可以调用它。它不应该在 /db 上调用,而应该在根目录上调用,因为 dumpall 不仅仅是关于数据库的。

CR: 响应可能看起来像

{
    'type' : 'databasess',
    'name' : 'db',
    'children' : [ 'postgres', 'template1', 'template0', 'mydb' ]
}

只要进行数据库转储是幂等的并且不会更改数据库,我认为无论选项数量多少,GET 都是最合适的。您是否知道数据库转储会更改数据库的方式?--Dobesv (talk) 2013 年 9 月 2 日 17:03 (UTC)

数据库

URL: /databases/:database_name


带有 Accept 的 GET 返回数据库的转储。查询参数

使用适当的查询参数可能可以用作获取数据库的 pg_dump。

CR: IMO A GET 应该返回一个 JSON 响应,显示数据库信息及其模式列表,以及用于添加/删除详细信息的查询参数,例如

GET /db/mydbname

... response ...

{
   'type' : 'database',
   'name' : 'mydbname',
   'owner' : 'joebloggs',
   'children' : ['schemas/public', 'schemas/pg_catalog', 'schemas/myschema']
}

请注意,“children” 始终应该是 URI,在这种情况下,模式名称将必须对 URI 进行编码,例如 "my/schema/name" 变成 "my%2Fschema%2Fname",因此 "schemas/my%2Fschema%2Fname"。 丑陋,但我们总能拥有另一个名为例如 'schemas' 的键,其中包含未转义的名称;最重要的是,“children” 键始终包含用于遍历数据库结构的有效相对 URI。

我认为 pg_dump 不应该是一个 GET,我认为它是一个 RPC 操作,应该像例如

POST /db/mydbname?dump
{
  'schema_only' : false,
  'inserts' : true
}

一个用于选择 pg_dump 的 accept 标头是不够的,因为人们需要以不同的方式运行转储。

在我看来,将选项作为 URL 查询参数传递比作为 JSON 主体传递更容易。并且 POST 将意味着创建对象,或者至少修改数据库,我认为转储不是这种情况。--Dobesv (talk) 2013 年 9 月 2 日 17:03 (UTC)

查询数据库

URL: /databases/:database_name/query

此数据库上 SQL 查询的 RPC 端点。POST SQL,根据 Accept 标头以特定格式获取响应。使用数据库的默认模式,或可以在 SQL 中更改模式。

CR: 考虑将 SQL 包裹在 JSON 中以允许在行外使用查询参数,每个查询的 GUC 设置等。想想

POST /mydb/query
{
   type: 'sqlquery',
   query : 'SELECT * FROM mytable WHERE userid = :userid',
   params : {
       'userid' : ['integer', 400]
   },
   query_gucs : {
       'work_mem' : '1M',
       'statement_timeout' : 5000,
       'search_path' : 'public,myschema'
   },
}

我个人认为,不应该接受原始 SQL 作为 POST,它应该*必须*位于 JSON 容器中。 速度稍微慢一点,但更加灵活,并且 HTTP 接口很可能无论如何都会在进程之外。

这作为一个选项很有用,但我认为接受直接 SQL 对人们更有用。我不知道人们多久将这些选项附加到他们的 SQL 查询中。--Dobesv (talk) 2013 年 9 月 2 日 17:03 (UTC)

模式

URL: /databases/:database_name/schemas/:schema_name

GET 返回模式的 DDL 模式定义

CR: 完全反对 GET 返回 DDL。应该返回包含模式信息和子节点的描述性 JSON。对于 SQL DDL,可能应该是带有 accept 标头的 GET,甚至带有参数的 RPC 风格的 POST。请参阅上面关于 API 一致性的讨论,了解为什么我认为在这里 GET 返回 SQL 是一种不好的做法。

使用模式查询

URL: /databases/:database_name/schemas/:schema_name/query

使用此模式作为默认值的 SQL 查询的 RPC 端点。POST SQL 并根据 Accept 标头以特定格式获取响应。

CR: 鉴于 Pg 中的模式是搜索路径,这到底意味着什么?将 search_path 设置为 "theschema,pg_catalog" 吗? 只是在前面加上 "theschema" 吗? 我想知道在 /schemas 下查询是否完全必要,或者是否可以通过在数据库级别将 search_path GUC 传递给查询来更好地满足需求,如上所述。

我想我不知道。像 pgAdmin 这样的工具在您浏览到模式并运行一些 SQL 时通常会做什么?--Dobesv (talk) 2013 年 9 月 2 日 17:06 (UTC)

URL: /databases/:database_name/schemas/:schema_name/tables/:table_name

GET 返回表的 DDL(以及可选的索引,如果查询参数)。

PUT 提供新的 DDL

CR: GET 应该返回*描述性*信息,而不是难以解析以获取任何有用信息 SQL DDL。 或许使用 accept 标头获取 SQL,或使用 POST 请求它。GET 应该响应,例如

{
    type : 'table',
    name : 'thetablename',
    owner : 'freddy',
    database: 'mydb',
    schema: 'public',
    tablespace: 'default',
    children: [ 
        'rows',
        'columns/id', 'columns/username',
        'constraints/username_must_be_unique',
        'constraints/username_is_lowercase'
    ],
    columns : {
       id: { index: 0, type: 'integer', default: 'nextval(\'thetablename_id_seq\')', nullable: false },
       username: { index: 1, type: 'text', nullable: true },
    },
    indexes : {
       thetablename_id_idx: { on: ['id'], index_type : 'btree', unique: true, schema: 'public', tablespace: 'default', uri: '/db/mydb/schemas/public/rels/thetablename_id_idx' },
       thetablename_username_unique_idx: { on: ['username'], index_type: 'btree', unique: true, schema: 'public', tablespace: 'default', uri: '/db/mydb/schemas/public/rels/thetablename_username_idx'}
    },
    constraints: {
       username_must_be_unique: { constraint_type: 'unique', on: ['username'], implementing_index: 'thetablename_username_unique_idx' },
       username_is_lowercase: { constraint_type: 'check', expression: 'lower(username) == username', where: 'id <> 0' }
    }
}

您明白了。 这是一个计算机可读的,您可以从中获取大量有用的信息,并了解一些事情,例如,“用户名列是文本列,可以为空,但如果存在,则值必须是唯一的”,而不仅仅是一些难以解析的 SQL。

在 'indexes'、'constraints' 等中可能应该是对象而不是数组,因为它们没有自然顺序,并且不应包含除名称之外的任何内容,除非查询参数要求递归信息关于子节点。 列具有自然顺序,但可以通过序数索引给出,使它们保持一致。 上面的响应将使用参数 "?child_detail=true" 生成。 如果省略,则将产生的只是子节点列表(其中每个子节点当然可以随后被查询)

{
    type : 'table',
    name : 'thetablename',
    database: 'mydb',
    schema: 'public',
    tablespace: 'default',
    children: [ 
        'rows',
        'columns/id', 'columns/username',
        'constraints/username_must_be_unique',
        'constraints/username_is_lowercase'
    ]
}

请注意,由于索引是与表分开的对象,并且甚至不一定在同一个模式中,因此我没有将它们列入 'children' 中。


此外,IMO "/schema/myschema/tables" 是错误的,因为它应该透明地显示您看到的是表还是视图。 "/schema/myschema/relations" 可能更合适。 需要匹配 Pg 命名空间规则:表不能与视图同名,并且位于同一个命名空间中,但(例如)函数可以与表同名。

索引

URL: /databases/:database_name/schemas/:schema_name/table/:table_name/indexes/:index_name

GET 返回表的 DDL 模式定义

CR: 如上所述,反对返回 DDL。 这应该以 json 格式返回索引信息,例如

{
    type: 'index',
    name: 'the_table_id_idx',
    owner: 'freddy',
    database: 'mydb',
    schema: 'public',
    tablespace: 'default',
    target_table: {
       uri: '/db/dbname/schemas/public/the_table',
       name: 'the_table',
       schema: 'public',
    },
    columns: ['id'],
    index_type: 'btree',
    unique: true
}

表行

URL: /databases/:database_name/schemas/:schema_name/tables/:table_name/rows

GET 使用查询参数和 URL 构建 SQL SELECT 语句并返回结果。查询参数

  • cols - SELECT 列列表
  • where - 指定条件
  • group_by - 指定分组
  • order_by - 指定排序

POST 使用主体中的行数据基于 Content-Type 构建 SQL INSERT 或 COPY。 当 Content-Type 为 sql 时,使用 INSERT。 如果 Content-Type 为 csv 或 text,则使用 COPY 语义。

DELETE 使用查询参数 where(与上面的 GET 相同)构建 SQL DELETE。

CR: 上述每个参数块(例如 'where' 或 'order_by')几乎都必须是一个可以接受任意表达式的 SQL 片段,那么与使用常规 SQL 查询并让人们使用现有的查询生成器设施相比,将它们分开是否有用? 您如何在查询参数中表示 "col1 DESC NULLS FIRST, col2 ASC" *而不* 仅仅将其作为原始 SQL 片段?

CR: 似乎您想要在 table/rows 接口上实现一个简单的“CRUD”风格的 API。 如果是这样,GET on rows/ 应该返回所有主键的列表,而 GET on rows/[key] 应该返回该行的所有数据。 我*强烈反对*使用 SQL 片段作为查询参数过滤器的想法,因为您绝对是在招致可怕的 SQL 注入问题。

GET /db/mydb/schemas/public/tables/tblname/rows

... response ...

{
   type: 'rows',
   table: 'tblname',
   schema: 'public',
   database: 'mydb',
   children: [ '1', '4', '8', '27' ]
}

然后,您可以使用对子节点的常规 GET、PUT 来替换它们,您可以对 rows/ 使用 POST 来创建新的子节点等。 CRUD。 对于批量或高强度操作来说,速度可能很慢且效率低下,但干净、简单,不涉及 SQL,并且易于实现。

任何更复杂的操作都可能最好使用 SQL 完成。 在将来,也许可以使用更适合机器的查询语言(可能是基于 json/xml/whatever 的),但我认为您*无法*安全地实现 WHERE、HAVING、ORDER BY 等,而没有结构化的查询语言。 将 SQL 片段转储进去是一个瞬间的安全漏洞。

CR: 还值得考虑矩阵参数在 CRUD 风格访问中的实用性。 请参阅 RESTEasy 文档中的矩阵参数

URL: /databases/:database_name/schemas/:schema_name/tables/:table_name/row (?)

上面 rows 的变体,其中,如果获取、插入或删除的行数 != 1,则返回错误并回滚可能已进行的任何更改。

CR: 这与 API 其他部分的结构不一致,并且不是 REST。 应该改为使用 GET rows/[id] 来获取行,PUT rows/[id] 来替换/编辑,DELETE rows/[id] 来删除,以及 POST rows 包含新行的所有数据来创建,正如标准 RESTful 设计那样。

登录角色

URL: /logins

  • GET: 登录角色列表
  • POST: 添加新的登录角色

CR: 应该是 /roles?login=true。 使用 "/logins" 会混淆命名空间,因为同一个对象可以出现在 "/logins" 和 "/groups" 中(请记住,登录角色可以有成员),并且并非所有角色都是组*或*登录角色。 我强烈建议将 "/logins" 和 "/groups" 合并为 "/roles"。

登录角色

URL: /logins/:name

  • GET: 获取有关单个登录角色的信息
  • PUT: 更新登录角色
  • DELETE: 删除登录角色

CR: 如上所述,应该是 /roles/:name。 我同意此设计元素的其余部分。 POST /logins 应该创建一个新角色。

组角色

URL: /groups

  • GET: 组角色列表
  • POST: 创建新的组角色

CR: 如上所述,这应该与 "/logins" 合并为 "/roles"。

组角色

URL: /groups/:name

  • GET: 有关此组角色的信息
  • PUT: 更新此组角色
  • DELETE: 删除此角色

CR: AS /logins/:name

LOB

URL: /databases/:database/lobs

  • POST: 上传一个具有新生成 oid 的新大型对象

URL: /databases/:database/lobs/:oid

  • GET: 获取大型对象主体
  • PUT: 更新大型对象主体
  • DELETE: 删除大型对象

数据格式

HTTP 服务器应考虑支持 XML、JSON 和 SQL 输出格式。 它根据 HTTP 请求的“Accept”标头或 URI 扩展名确定要使用的输出格式。 它根据 HTTP 请求的“Content-Type”标头或 Content-Disposition 标头中的文件名扩展名确定输入格式。

CR: 使用扩展名和 Accepts 都会使安全规则和扫描程序难以执行其工作。 看看 Microsoft Internet Explorer 忽略 MIME 类型并偏爱文件扩展名所发生的事情。 我认为使用文件扩展名不是一个好主意。 只需使用 MIME 以及 accepts 标头/Content-type。

SQL

SQL 输出应与您在 pg_dump 中看到的输出匹配。待办事项:示例

XML

待设计...

  • SQL Server 在其 XML 输出方面非常灵活,因此您可以生成结构化的 XML,而不仅仅是行集合
  • 需要弄清楚我们是否可以以及如何为此使用现有的 XML 架构和格式

JSON

待设计...

  • 我们是否需要结构化的输出,或者只是一个行集合?
  • 我们可以选择将行输出为数组或映射... 我们应该允许两者吗? 用户如何最好地指定他们想要的?

SQL MIME 类型

目前没有为 SQL 源代码注册 MIME 类型。 类似于 SQL 的 MIME 类型应视为 application/vnd.postgresql.sql,包括但不限于

  • application/sql
  • text/sql
  • application/x-sql
  • text/x-sql

版本控制

为 PostgreSQL 数据模型定义的字段可能会随着时间的推移而改变。 MIME 类型可以包含架构的版本,该版本应与 PostgreSQL 的版本相关联。 例如

Accept: application/vnd.postgresql.login-role+json;version=9.3

意味着客户端只希望接收与 PG 9.3 数据模型兼容的 JSON 响应。

文件扩展名

将后缀应用于 URI(例如 .sql、.csv 或 .html)会覆盖提供的 Accept: 标头(如果有),使用与该后缀匹配的 content type。 当 Content-Type 为 text/plain 或 application/octet-stream 时,我们将查看 Content-Disposition 标头中文件名(如果有)的文件扩展名,并根据该扩展名覆盖 Content-Type。

  • .sql -> application/vnd.postgresql.sql
  • .csv -> text/csv
  • .html -> text/html

CR:危险,参见 Internet Explorer。 为什么要有此功能? 它有什么用? 它解决了什么问题?

一些需要考虑的功能

  • 能够在查询响应中添加 EXPLAIN ANALYZE 和其他计时/性能信息
  • 支持 SPDY 协议(如果我们有粗/安全管道,则可能没有加密/压缩)
  • 分区 ID(可能在请求中指定集群节点或分区)
  • 虚拟主机(根据 Host 标头直接请求完全不同的数据库服务器)
  • 如何可靠且安全地将请求与后端会话状态相关联
    • 如果每个 HTTP 连接都像普通会话连接一样处理,并在连接丢失时立即回滚怎么办? 您需要在客户端应用程序设计中考虑这一点。 虽然可行; 许多现有的 JavaScript 应用程序就是这样做的。

基于数据库过程的方法

不一定是矛盾的,但在我的想法中,与对模式和数据的通用 REST 访问相比,公开数据库过程是一种更安全的方法。

我的想法是,它将如何工作

  1. PostgreSQL 的扩展使主服务器进程监听另一个端口(443)以进行 HTTPS 连接。
  2. 主服务器进程为每个传入连接派生一个正常(但为 HTTPS)的客户端会话来处理。
  3. 在加密握手之后,负责的进程会解析第一个传入的 HTTP 请求。

对于通过 HTTPS 连接传入的每个 HTTP 请求

  1. 负责的 PostgreSQL 进程执行在通用配置中指定的 SQL,并将解析后的 HTTP 请求作为输入,以选择目标数据库和模式,以及要调用的身份验证和请求处理程序过程。
    • 典型的映射可能是从域名 (<key>.example.com) 或第一个 URI 路径元素 (example.com/<key>) 的第一部分到数据库、模式、authn_proc_name、request_handler_proc_name 元组。
  2. 调用选定的身份验证过程,并期望它返回一个用于正常 PostgreSQL 访问控制的用户名。
    • 这将允许应用程序实现自己的安全性,例如双向身份验证。
    • 指定一个回退过程以在失败的情况下生成 HTTP 响应也可能得到支持。
    • 最好提供基于 HTTP digest、cookie 和客户端证书的身份验证的示例过程集。
  3. 在身份验证后,调用与选定的数据库和模式关联的请求处理程序过程。 它应该使用 HTTP 请求信息生成 HTTP 响应对象,可能通过将调用传递给分层应用程序中的进一步过程。
    • 一个典型的映射到实际的“业务过程”可能是使用 URI 中的下一个路径元素来指定要调用的另一个过程的名称,并将后续的路径元素作为位置参数传递,或者将 GET 和 POST 参数作为键值对传递。
  4. 返回的 HTTP 响应对象被序列化为通过 HTTPS 连接发送给客户端的 HTTP 响应。

后续请求可能需要进行相同的处理,包括数据库选择和身份验证,因为任何请求都可能指向不同的数据库,并且分别对每个请求进行身份验证符合 HTTP 的无状态性和传统。

一旦 HTTPS TCP 连接断开或关闭,会话就会像普通会话一样结束; 事务中任何未提交的更改都会回滚。

这种方法在本质上与众不同,因为它使 PostgreSQL 成为一个独立的应用程序平台,包括一个完全可编程的 Web GUI。 应该可以选择一种或两种方法,即 REST 模式和数据访问,以及这种应用程序风格的访问,如果两种方法都实现了,则应将其公开。

示例请求处理程序过程应该阐明使用 HTTP 请求部分来选择一个要调用的“业务过程”以及其中的一些参数的想法,以及如何根据请求的类型(而不是业务逻辑)将“业务过程”的结果转换为不同的输出格式 (HTML/JSON/XML/CSV),并将其格式化为适当的布局。

这种基于过程调用的方法可用于实现整个数据库系统的通用 REST 公开,但反之则不行。 同样,这些过程可以比只依赖于通用 PostgreSQL ACL 的扁平方法提供更多关于谁可以查看或执行什么的控制。

--Korpiq 21:11, 28 September 2012 (UTC)

我原则上喜欢这个想法,但在实践中,我很好奇它的影响。 通常,数据库是一种特殊用途的组件,具有其自身的资源和扩展方法。 我认为,如果有人真正利用此系统的全部功能将他们的整个 Web 应用程序逻辑构建到数据库服务器中,那么他们可能会遇到问题,如果/当他们需要扩展时,因为数据库和应用程序层耦合在一起。 任何没有在数据库中构建 Web 应用程序逻辑的人,都会因为在脚本语言中解析/验证请求而不是在编译的 C 代码中解析/验证请求而付出性能损失的代价。 数据库层是一个可能罕见的地方,人们会将每个请求的毫秒级开销视为一个问题。

--Dobesv (talk) 16:39, 2 September 2013 (UTC)

实现

此维基中的许多想法现已在 PostgREST 中实现。