Racket中的表单验证

Racket中的表单验证,racket,web-development-server,Racket,Web Development Server,我是一个新手,虽然到目前为止我已经设法和servlet打交道,但几乎没有什么事情可以做。我现在想做的是验证一个简单的用户名/密码POST请求。我已经通过“web服务器/formlet”模块成功地实现了这一点,但是formlet进程功能迫使我使用以下模式命名所有输入:input\u 0,input\u 1,等等。对于表单中的每个输入元素,我都感到尴尬和不便。我不理解不允许用户覆盖formlet处理的HTML输入的自动命名背后的原因: (define (get-username/password r

我是一个新手,虽然到目前为止我已经设法和servlet打交道,但几乎没有什么事情可以做。我现在想做的是验证一个简单的用户名/密码POST请求。我已经通过“web服务器/formlet”模块成功地实现了这一点,但是
formlet进程
功能迫使我使用以下模式命名所有输入:
input\u 0
input\u 1
,等等。对于表单中的每个输入元素,我都感到尴尬和不便。我不理解不允许用户覆盖formlet处理的HTML输入的自动命名背后的原因:

(define (get-username/password request)
  (define login-formlet
    (formlet
      (#%# ,{input-string . => . username}
           ,{input-string . => . password})
      (values username password)))

  (formlet-process login-formlet request))
上述函数期望POST请求在
input\u 0
键中包含用户名,在
input\u 1
键中包含密码,因此我的HTML模板被迫将“用户名”输入命名为
input\u 0
,将“密码”命名为
input\u 1
(否则
formlet process
将投诉):


请登录
用户名:
密码:
登录

如果有方法覆盖自动命名,我找不到它(希望我没有错过文档中的任何内容!):

因此,我决定退后一步,尝试自己进行处理,并降落在:

但是文档本身不鼓励使用它(没有指出一种替代的原始安全方法!),因为可能很难从中获得经过消毒的值。所以我的问题是:是否有一种内置的方法可以正确、安全地从POST请求中提取/处理经过消毒的值,而不需要在Racket中使用内置或简单的函数?我真正感兴趣的是而不是,这取决于任何第三方软件包或模块,而是Racket已经提供了什么


提前谢谢

从您的最后一个问题开始,手动提取绑定的正确方法(web服务器/formlets内部使用)与在
binding:form
binding:file
结构上操作的实用函数相结合,如
bindings assq all
。文档肯定应该更改,以便更清楚地指向未弃用的API

就formlet而言,输入名称的模式是formlet抽象设计的一部分,但您不希望直接与之交互。也许您已经知道这一点,但是,由于您提到的是
formlet进程
,而不是
formlet显示
,我想知道您是否在没有看到所有背景的情况下(这很容易做到!)偶然发现了
web服务器/formlet。这里有一个详细描述设计的例子,但我将尝试在这里进行一点讨论(使用本文中的一个示例)

假设您想要创建一个表单组件来请求用户输入日期。您需要为两个不同的任务编写代码:生成HTML和处理提交的请求。然而,这些任务是密切相关的。如果更改生成的HTML(可能包含多个输入元素),通常需要对处理代码进行相应的更改。我们需要一种方法来帮助保持显示和处理代码的同步。此外,一旦您设计了一个优秀的日期组件,您可能希望以相同的形式多次使用它:也许您甚至希望构建一个日期范围组件。因为HTML输入元素由唯一的ID标识,所以您需要一些抽象方法来使代码可重用

Formlet为这些问题提供了解决方案。formlet封装了呈现和处理代码,使它们保持同步。为了让您的formlets真正封装某些功能单元,
web服务器/formlets
库生成所有ID

这有点抽象,下面是一个使用Formlet获取用户名和密码的示例:

#lang web服务器/insta
(需要web服务器/Formlet)
(定义(启动请求)
(定义值[用户名密码]
(从用户处获取用户名+密码))
(重定向/获取)
(回复/xexpr)
`(html(标题“您已登录”)
(元([charset“utf-8”]))
(元([名称“视口”]
[内容“宽度=设备宽度,初始刻度=1”])
(正文(h1“您已登录”)
(你的用户名:),用户名)
显然,这不是真的:
(p(b“您的密码:”),密码()()))
(定义登录表单)
(表格
(#%#)(p)(标签“用户名:”
,{=>(到字符串)
(必选)
(文本输入)
#:属性“([required”required“]))
用户名})
(p)标签“密码:
,{=>(到字符串)
(必选)
(密码输入)
#:属性“([required”required“]))
密码})
(p)输入([输入“提交”]
[值“登录”]))
(值用户名密码)))
(定义(从用户处获取用户名+密码)
(发送/发送表单)
登录表单
#:包裹
(λ(渲染形式)
`(html(标题“请登录”)
(元([charset“utf-8”]))
(元([名称“视口”]
[内容“宽度=设备宽度,初始刻度=1”])
(正文(h1“请登录”)
,呈现形式(()()))

FWIW继续教程还有一节关于Formlet的内容:@liberalartist感谢您的回答!我理解formlet文件在处理表单时必须是一种新颖的方法,但是我仍然觉得它在做出不能被推翻的决策时是不灵活的。我可能只想呈现一个表单,或者只是验证它,或者两者都做,但不应该这样做
<html>
    <head>
        <title>Please login</title>
    </head>
    <body>
        <form action="" method="post">
            <label for="username">Username:</label>
            <input type="text" name="input_0" required>
            <label for="password">Password:</label>
            <input type="password" name="input_1" required>
            <button type="submit" value="Login">Login</button>
        </form>
        <div>
            <p></p>
        </div>
    </body>
</html>