跳到主要内容
FormFlow

在发送之前用预检拦下不合格的提交

在填写人还在页面上时,就向表单本身索要判定。预检检查请求结构、Origin 和严格模式架构,不存储任何记录,也从不保证真实提交一定被接受。

本文由机器翻译。 阅读英文原文

A dark FormFlow plate titled 'Ask before Send.' with a checklist reading Shape, Origin and Strict schema ready, and 'No side effects' kept.

一次被拒绝的提交,代价是这个产品唯一无法挽回的东西:一个人本来还在页面上,然后不在了。FormFlow 把每一次拒绝都保留成你可以处理的一条记录,表单的健康信号也会统计这些拒绝。预检是这套判定中唯一在“发送”之前运行的部分。它随 v1.0.0 一同到来。

预检回答什么

向 /api/v1/f/{token}/preflight 发送一个 POST,请求体是表单本来会发送的那些回答,格式为 JSON,路径中带上表单的公开令牌。该接口返回接收接口会对这些回答作出的判定,但并不真的作出。传入页面自身的 Origin 请求头,就会按提交接口完全相同的方式检查。契约写在 API 参考里。

响应有四个键:ok、errors、checked 和 policy。errors 是一个以字段名为键、以句子列表为值的对象;即使为空也仍是对象,好让生成的调用方能索引它。checked 指出实际问了什么——结构、origin 和架构;在托管页面上 origin 缺席,因为 FormFlow 提供的页面不受你的允许来源名单约束。

在填写人还在页面上时调用

一次 fetch 就够了。下面是这次调用的形状;把它挂到你页面本来就信任的事件上,比如离开某个字段。

const endpoint = 'https://formflow.digital/api/v1/f/YOUR_FORM_TOKEN/preflight'

async function preflight(answers) {
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
    body: JSON.stringify(answers),
  })

  // A 429 or an outage is not a verdict. Say nothing rather than something wrong.
  if (!response.ok) return null

  const { ok, errors, checked, policy } = await response.json()
  return ok ? [] : Object.entries(errors)
}

把返回的句子显示在它所指的那个字段旁边。不要在你自己的代码里重述规则:这个接口的意义在于,填写人读到的句子就是接口本来会使用的句子,用的是表单的语言,而不是你的 JavaScript 的语言。

读懂响应

键

它包含什么

ok

仅当没有任何东西拒绝这些回答时为 true

errors

每个字段名一条,每条都是句子列表

checked

问了什么:结构、origin、架构

policy.revision

判定所用的策略版本

policy.fingerprint

标识那份确切策略的指纹

errors 里有两个键不是字段。origin 承载允许来源名单的拒绝,而 submission 承载属于整个表单而不是某一条回答的拒绝,比如表单已关闭。把 policy 块记进日志:版本与指纹合起来标识判定所用的确切策略,这正是当这里通过、那里却被拒绝时你需要的东西。

它不检查什么

它只问决策中真正是表单配置纯函数的那一半。它不运行垃圾评分,不索取 Turnstile 挑战,也完全不看文件字段——预检不携带任何字节,所以已声明的图片既不检查也不承诺。它不存记录、不消耗配额、不投递任何东西。

但它确实在限流之内。预检与提交接口共用 token|IP 桶和整个团队的请求桶,所以一阵突发可能返回 429 与 Retry-After。429 是缺席的判定,不是拒绝;页面应当保持沉默,而不是编造一个错误。

它放在哪里

FormFlow 为被拒绝的提交提供的其他每一种机制,都在一个人被拒绝之后才运行:拒绝台账、健康信号、拒绝面、找回收件箱。只有这一个在之前运行。把它当作两次判定中的第一次,而绝不是唯一一次。

  • 通过不是承诺。由 POST 决定,而它在决定时会带上预检没有问的一切。

  • 如果两次调用之间改了表单,答案也会跟着变。响应里的策略版本才是判定你的那一份。

  • 文件字段不被检查,所以绝不要因为一次预检就告诉填写人他的图片已被接受。

  • errors 以字段名为键,但 origin 和 submission 不是字段;把它们显示在表单顶部。

  • 任何持有表单公开令牌的人都能调用它。它不能证明调用者是谁,也不是秘密。

把你的第一个表单指向 FormFlow。

无需搭建后端,无需托管前端。

免费开始