http - 在 GO 中的 http 处理函数之间传递数据

标签 http go

我有一个 http 处理函数,只有当该电子邮件尚未被接收时,它才会将电子邮件保存到数据库中。如果电子邮件已被占用或某些其他数据无效,我想重定向回表单并通知用户发生错误的位置。

func validate(w http.ResponseWriter, r *http.Request) {

    //query database to check if data r.FormValues were
    //valid

    //IF form values were not valid redirect back to the
    //registration form and  pass on data indicating the
    //form data was not valid
    {
        http.Redirect(w, r, "/register", http.StatusFound)
    }

}

究竟如何将数据从 func validate() 发送到 func register()?是否可以向 r* http.Request 添加某种结构,以便在调用 http.Redirect() 时将其传递给 func register()?

最佳答案

在您的示例中,如果您的表单提交定向到 validate() 处理程序,该处理程序将发回 HTTP 响应(这将是重定向),浏览器将再次调用 /注册。您的 validate() 处理程序和您的 register() 处理程序之间没有连接,*http.Request 值将与浏览器发出另一个 HTTP 请求,因此将创建另一个 *http.Request 值并在第二次调用时传递。

您可以在重定向 URL 中指定参数,例如重定向到 /register?someParam=someValue 但这只是不必要的往返并且使事情复杂化。

一个更简单的解决方案是不分离表单呈现和验证(在处理程序级别)。同一个处理程序可以处理这两者,因此 2 个处理程序之间不需要共享数据。

例子:

func register(w http.ResponseWriter, r *http.Request) {
    // Params for rendering the page
    m := map[string]interface{}{}

    // Is form submitted?
    if r.FormValue("submitRegister") != "" {
        // check submitted values
        // E.g. check email, let's say it's already in use:
        email := r.FormValue("Email")
        if alreadyInUse {
            m["Error"] = "Email already in use!"
        }

        if m["Error"] == "" {
            // If all values are OK, create user, and redirect:
            http.Redirect(w, r, "/home", http.StatusFound)
            return // AND return!
        }

        // Store submitted values in params, so when we render
        // the registration form again, we fill submitted params as initial values,
        // so user don't have to fill everything again (expect maybe the password)
        m["Email"] = email
    }

    // Either no submit or validation errors
    // Render the registration form, using submitted values as initial ones
    // Also if m["Error"] is set, render the error above the form
    registerTempl.Execute(w, m)
}

当然你可以把它分解成函数,你可以有一个单独的 validate() 函数,但是表单提交仍然必须指向与你的注册页面相同的路径(例如 /注册):

func register(w http.ResponseWriter, r *http.Request) {
    // Params for rendering the page
    m := map[string]interface{}{}

    // Is form submitted?
    if r.FormValue("submitRegister") != "" {
        validate(w, r, m)
        if m["Error"] == "" {
            return // AND return!
        }
    }

    // Either no submit or validation errors
    // Render the registration form, using submitted values as initial ones
    // Also if m["Error"] is set, render the error above the form
    registerTempl.Execute(w, m)
}

func validate(w http.ResponseWriter, r *http.Request, m map[string]interface{}) {
    // check submitted values
    // E.g. check email, let's say it's already in use:
    email := r.FormValue("Email")
    if alreadyInUse {
        m["Error"] = "Email already in use!"
    }

    if m["Error"] == "" {
        // If all values are OK, create user, and redirect:
        http.Redirect(w, r, "/home", http.StatusFound)
        return
    }

    // Store submitted values in params, so when we
    // render the registration form again, we fill submitted params as initial values,
    // so user don't have to fill everything again (expect maybe the password)
    m["Email"] = email
}

关于http - 在 GO 中的 http 处理函数之间传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36215571/

相关文章:

java - http服务器中的请求响应处理是异步完成的吗?

go - go-ethereum `bind.NewTransactor()` 的巨大持久内存分配?

javascript - Axios GET 请求不起作用

http - 多个 Vary HTTP header 或一个组合?

node.js - Content-Length header 是压缩字节还是未压缩字节的字节大小?

Golang 多模板缓存

regex - 去吧,正则表达式 : very challenging regex on Characters

api - Azure 管理 Rest API 身份验证 token

go - 运行go env时,显示的GOPATH与我在环境变量中设置的内容有所不同吗?

sorting - 根据值(结构的属性)对 map 进行排序