如何在golang中处理同一个处理程序中的多个POST请求?

huangapple go评论79阅读模式
英文:

How to handle multiple POST requests in same handler in golang?

问题

我有两个表单在signup.html文件中,我想执行它们。

  1. 第一个表单重定向到/login,但不将数据插入数据库。
  2. 第二个表单既不插入数据,也不重定向到注册页面。

如果我将两个表单的action都设置为相同的链接,那么它会将数据插入数据库。如何在一个函数中执行多个POST请求并重定向到多个页面?

谢谢!

controllers.go

func Signup(w http.ResponseWriter, r *http.Request) error {
    if r.Method == "GET" {
        return SignupTmpl.Execute(w, nil)
    } else if r.Method == "POST" && http.MethodPost == "Register" {
        register := models.RegisterUser{
            Name:     r.FormValue("name"),
            Email:    r.FormValue("email"),
            Password: r.FormValue("password"),
        }
        values := [3]string{register.Name, register.Email, register.Password}
        database.InsertRegister(values)
        return LoginTmpl.Execute(w, nil)
    } else if r.Method == "POST" && http.MethodPost == "Newsletter" {
        Newsletter(w, r)
        return SignupTmpl.Execute(w, nil)
    }
    return nil
}

signup.html

// 注册表单
<form class="form" method="post" action="/login">
    ...
    <input type="submit" value="Register">
</form>

// 新闻订阅表单
<form class="newsletter" method="post" action="/signup">
    ...
    <input type="submit" value="Newsletter">
</form>
英文:

I have two forms in the signup.html file that I want to execute.

  1. The first form redirects to /login but does not insert the data into the database.
  2. The second form neither inserts the data nor does it redirect to the Signup page.

If I set both action equal to the same link then it inserts the data into the database. How to execute multiple POST requests and redirects to multiple pages in a
single function?

Thank you!

controllers.go

func Signup(w http.ResponseWriter, r *http.Request) error {
	if r.Method == &quot;GET&quot; {
		return SignupTmpl.Execute(w, nil)
	} else if r.Method == &quot;POST&quot; &amp;&amp; http.MethodPost == &quot;Register&quot; {
		register := models.RegisterUser{
			Name:     r.FormValue(&quot;name&quot;),
			Email:    r.FormValue(&quot;email&quot;),
			Password: r.FormValue(&quot;password&quot;),
		}
		values := [3]string{register.Name, register.Email, register.Password}
		database.InsertRegister(values)
		return LoginTmpl.Execute(w, nil)
	} else if r.Method == &quot;POST&quot; &amp;&amp; http.MethodPost == &quot;Newsletter&quot; {
        Newsletter(w, r)
		return SignupTmpl.Execute(w, nil)
    }
	return nil
}

signup.html

// Signup form
&lt;form class=&quot;form&quot; method=&quot;post&quot; action=&quot;/login&quot;&gt;
    ...
    &lt;input type=&quot;submit&quot; value=&quot;Register&quot;&gt;
&lt;/form&gt;

// Newsletter form
&lt;form class=&quot;newsletter&quot; method=&quot;post&quot; action=&quot;/signup&quot;&gt;
    ...
    &lt;input type=&quot;submit&quot; value=&quot;Newsletter&quot;&gt;
&lt;/form&gt;

答案1

得分: 1

&gt; ```
&gt; http.MethodPost == &quot;Register&quot;
&gt; ... 
&gt; http.MethodPost == &quot;Newsletter&quot;
&gt; ```

这些比较没有意义。[`http.MethodPost` 是一个常量][1],它包含了 HTTP POST 请求的动词("POST")。常量变量比硬编码的值更受欢迎,因为与硬编码的字符串不同,拼写错误会导致编译时错误。

&gt;```
&gt;&lt;input type=&quot;submit&quot; value=&quot;Newsletter&quot;&gt;
&gt;```

如果你想要访问这个输入标签的值,你需要给它一个 `name`:

&gt;     &lt;input type=&quot;submit&quot; name=&quot;operation&quot; value=&quot;Newsletter&quot;&gt;

然后你可以检查表单的值:

if r.Method == "GET" {
return SignupTmpl.Execute(w, nil)
} else if r.Method == "POST" {
if r.FormValue("operation") == "Register" {
...
} else if r.FormValue("operation") == "Newsletter" {
...
}
}


我个人会为所有这些操作编写不同的处理程序,然后将它们指向不同的 URL。大部分处理程序逻辑都是路由,可以通过不同的处理程序免费完成。但你现在的做法也可以 - 只需确保:
1) 给需要后续引用的输入字段命名
2) 不要将 'POST' 与 'POST' 进行比较,而是将命名的输入字段值与预期值进行比较

  [1]: https://pkg.go.dev/net/http#pkg-constants
英文:

>
&gt; http.MethodPost == &quot;Register&quot;
&gt; ...
&gt; http.MethodPost == &quot;Newsletter&quot;
&gt;

These comparisons make no sense. http.MethodPost is a constant which contains the verb for HTTP Post requests ("POST"). Constant variables are preferred to hard coded values because unlike a hard coded string, a typeo will cause a compile time error.

>
&gt;&lt;input type=&quot;submit&quot; value=&quot;Newsletter&quot;&gt;
&gt;

If you want to be able to access the value of this input tag, you need to give it a name:

> <input type="submit" name="operation" value="Newsletter">

Then you can check that form value:

if r.Method == &quot;GET&quot; {
   return SignupTmpl.Execute(w, nil)
} else if r.Method == &quot;POST&quot; {
   if r.FormValue(&quot;operation&quot;) == &quot;Register&quot; {
      ...
   } else if r.FormValue(&quot;operation&quot;) == &quot;Newsletter&quot; {
      ...
   }
}

I personally would write a different handler for all these operations and then point them at a different URL. Most of your handler logic is routing, and that can be done for free with different handlers. But what you're doing is fine - just make sure :

  1. name input fields you need to refer to later
  2. don't compare 'POST' to 'POST', compare the named input field value to the expected value

huangapple
  • 本文由 发表于 2021年12月18日 23:35:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/70404735.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定