gpt4 book ai didi

racket - Racket 中的表单验证

转载 作者:行者123 更新时间:2023-12-02 09:05:05 26 4
gpt4 key购买 nike

我是 Racket 的新手,尽管到目前为止我已经设法使用 servlet 并让一些东西发挥作用。我现在想做的是验证一个简单的用户名/密码 POST 请求。我已经通过“web-server/formlets”模块成功做到了这一点,但 formlet-process 函数迫使我使用以下模式命名所有输入:input_0input_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_0 键中包含用户名,在 input_1 键中包含密码,因此我的 HTML 模板被迫将“用户名”输入为 input_0,“密码”输入为 input_1(否则 formlet-process 会报错):

<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>

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

https://docs.racket-lang.org/web-server/formlets.html

所以我决定退后一步,尝试自己进行处理,结果是:

https://docs.racket-lang.org/web-server/http.html?q=request-bindings%2Fraw#%28mod-path._web-server%2Fhttp%2Fbindings%29

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

提前致谢!

最佳答案

从最后一个问题开始,手动提取绑定(bind)的正确方法(web-server/formlet 在内部使用)是 request-bindings/raw与对 binding:formbinding:file 结构进行操作的实用函数相结合,例如 bindings-assq-all。文档绝对应该更改以更清楚地指向未弃用的 API。

就 formlet 而言,输入名称的模式是 formlet 抽象设计的一部分,但您不希望直接与之交互。也许您已经知道这一点,但是,由于您提到了 formlet-process 而不是 formlet-display,我想知道您是否可能偶然发现了 web-server/formlets 无需看到所有背景(这很容易做到!)。有一个academic paper详细描述了设计,但我会尝试在这里进行一些介绍(使用论文中的示例)。

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

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

这有点抽象,所以下面是使用 formlet 获取用户名和密码的示例:

#lang web-server/insta

(require web-server/formlets)

(define (start request)
(define-values [username password]
(get-username+password-from-user))
(redirect/get)
(response/xexpr
`(html (head (title "You Logged In")
(meta ([charset "utf-8"]))
(meta ([name "viewport"]
[content "width=device-width,initial-scale=1"])))
(body (h1 "You Logged In")
(p (b "Your username: ") ,username)
;; obviously don't do this for real:
(p (b "Your password: ") ,password)))))


(define login-formlet
(formlet
(#%# (p (label "Username: "
,{=> (to-string
(required
(text-input
#:attributes '([required "required"]))))
username}))
(p (label "Password: "
,{=> (to-string
(required
(password-input
#:attributes '([required "required"]))))
password}))
(p (input ([type "submit"]
[value "Log In"]))))
(values username password)))

(define (get-username+password-from-user)
(send/formlet
login-formlet
#:wrap
(λ (rendered-form)
`(html (head (title "Please Log In")
(meta ([charset "utf-8"]))
(meta ([name "viewport"]
[content "width=device-width,initial-scale=1"])))
(body (h1 "Please Log In")
,rendered-form)))))

关于racket - Racket 中的表单验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60094572/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com