Golang的HTML GET表单方法的值没有被填充。

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

Golang html GET form method values are not getting populated

问题

我有一个服务器代码和一个HTML表单用于搜索字符串。服务器处理程序获取字符串并进行搜索。但是我在这里遇到了两个问题。

  1. 方法名始终为GET,即使我将其设置为POST。

  2. 我无法在服务器端接收到表单值。

服务器代码如下:

  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "html/template"
  6. "io/ioutil"
  7. "log"
  8. "net"
  9. "net/http"
  10. "regexp"
  11. // "bytes"
  12. )
  13. var (
  14. addr = flag.Bool("addr", false, "find open address and print to final-port.txt")
  15. )
  16. type Page struct {
  17. Title string
  18. Body []byte
  19. }
  20. type UserInfo struct {
  21. Title string
  22. UserId string
  23. UserName string
  24. }
  25. func (p *Page) save() error {
  26. filename := "projects/" + p.Title + ".txt"
  27. return ioutil.WriteFile(filename, p.Body, 0600)
  28. }
  29. func loadPage(title string) (*Page, error) {
  30. filename := "projects/" + title + ".txt"
  31. body, err := ioutil.ReadFile(filename)
  32. if err != nil {
  33. return nil, err
  34. }
  35. return &Page{Title: title, Body: body}, nil
  36. }
  37. //Home page handler
  38. //Hard coding the user name
  39. func homeHandler(w http.ResponseWriter, r *http.Request, title string) {
  40. p := &UserInfo{Title: "Project Tube", UserId: "dxa132330", UserName: "Dinesh Appavoo"}
  41. renderTemplate(w, "home", p)
  42. }
  43. //Search project handler
  44. func searchHandler(w http.ResponseWriter, r *http.Request, title string) {
  45. fmt.Println("method:", r.Method) //get request method
  46. r.ParseForm()
  47. if r.Method == "GET" {
  48. form_data := r.FormValue("form_data")
  49. fmt.Println("Form Data : ", form_data)
  50. fmt.Println("Form Data 1: ", r.Form)
  51. for _, val := range r.FormValue("search_string") {
  52. fmt.Println("Search string: ", val)
  53. }
  54. } else {
  55. r.ParseForm()
  56. fmt.Println("Search string:", r.FormValue("search_string"))
  57. }
  58. p := &UserInfo{Title: "Project Tube", UserId: "dxa132330", UserName: "Dinesh Appavoo"}
  59. renderTemplate(w, "searchproject", p)
  60. }
  61. var templates = template.Must(template.ParseFiles("home.html", "editproject.html", "viewproject.html", "searchproject.html", "header.html", "footer.html"))
  62. func renderTemplate(w http.ResponseWriter, tmpl string, p interface{}) {
  63. //If you use variables other than the struct u r passing as p, then "multiple response.WriteHeader calls" error may occur. Make sure you pass
  64. //all variables in the struct even they are in the header.html embedded
  65. if err := templates.ExecuteTemplate(w, tmpl+".html", p); err != nil {
  66. http.Error(w, err.Error(), http.StatusInternalServerError)
  67. }
  68. }
  69. //URL validation
  70. var validPath = regexp.MustCompile("^/(home|editproject|saveproject|viewproject|searchproject)/(|[a-zA-Z0-9]+)$")
  71. func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
  72. return func(w http.ResponseWriter, r *http.Request) {
  73. m := validPath.FindStringSubmatch(r.URL.Path)
  74. if m == nil {
  75. http.NotFound(w, r)
  76. return
  77. }
  78. fn(w, r, m[2])
  79. }
  80. }
  81. func main() {
  82. flag.Parse()
  83. TestConn()
  84. http.HandleFunc("/home/", makeHandler(homeHandler))
  85. http.HandleFunc("/searchproject/", makeHandler(searchHandler))
  86. http.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.Dir("resources"))))
  87. if *addr {
  88. l, err := net.Listen("tcp", "127.0.0.1:0")
  89. if err != nil {
  90. log.Fatal(err)
  91. }
  92. err = ioutil.WriteFile("final-port.txt", []byte(l.Addr().String()), 0644)
  93. if err != nil {
  94. log.Fatal(err)
  95. }
  96. s := &http.Server{}
  97. s.Serve(l)
  98. return
  99. }
  100. http.ListenAndServe(":8080", nil)
  101. }

我在searchHandler函数中遇到了问题。我的HTML代码如下:

  1. {{ template "header.html" . }}
  2. <br><br>
  3. <div class="container">
  4. <form action="/searchproject" method="GET">
  5. <div class="form-group">
  6. <input type="text" class="form-control" name="search_string">
  7. </div>
  8. <button type="submit" class="btn btn-success">Search</button>
  9. </form>
  10. </div>

服务器控制台日志如下:

  1. method: GET
  2. Form Data :
  3. Form Data 1: map[]

有人可以帮我解决这个问题吗?谢谢。

英文:

I have a server code and a html form to search a string. Server handler gets the string and search for the same. But I am facing two issues here.

1.Method name is always GET even after I made it as POST.

2.I am Not able to receive the form value in the server end

Server code is here,

  1. package main
  2. import (
  3. &quot;flag&quot;
  4. &quot;fmt&quot;
  5. &quot;html/template&quot;
  6. &quot;io/ioutil&quot;
  7. &quot;log&quot;
  8. &quot;net&quot;
  9. &quot;net/http&quot;
  10. &quot;regexp&quot;
  11. //&quot;bytes&quot;
  12. )
  13. var (
  14. addr = flag.Bool(&quot;addr&quot;, false, &quot;find open address and print to final-port.txt&quot;)
  15. )
  16. type Page struct {
  17. Title string
  18. Body []byte
  19. }
  20. type UserInfo struct {
  21. Title string
  22. UserId string
  23. UserName string
  24. }
  25. func (p *Page) save() error {
  26. filename := &quot;projects/&quot; + p.Title + &quot;.txt&quot;
  27. return ioutil.WriteFile(filename, p.Body, 0600)
  28. }
  29. func loadPage(title string) (*Page, error) {
  30. filename := &quot;projects/&quot; + title + &quot;.txt&quot;
  31. body, err := ioutil.ReadFile(filename)
  32. if err != nil {
  33. return nil, err
  34. }
  35. return &amp;Page{Title: title, Body: body}, nil
  36. }
  37. //Home page handler
  38. //Hard coding the user name
  39. func homeHandler(w http.ResponseWriter, r *http.Request, title string) {
  40. p := &amp;UserInfo{Title: &quot;Project Tube&quot;,UserId: &quot;dxa132330&quot;, UserName: &quot;Dinesh Appavoo&quot;}
  41. renderTemplate(w, &quot;home&quot;, p)
  42. }
  43. //Search project handler
  44. func searchHandler(w http.ResponseWriter, r *http.Request, title string) {
  45. fmt.Println(&quot;method:&quot;, r.Method) //get request method
  46. r.ParseForm()
  47. if r.Method == &quot;GET&quot; {
  48. form_data := r.FormValue(&quot;form_data&quot;)
  49. fmt.Println(&quot;Form Data : &quot;,form_data)
  50. fmt.Println(&quot;Form Data 1: &quot;,r.Form)
  51. for _,val := range r.FormValue(&quot;search_string&quot;) {
  52. fmt.Println(&quot;Search string: &quot;, val)
  53. }
  54. } else {
  55. r.ParseForm()
  56. fmt.Println(&quot;Search string:&quot;, r.FormValue(&quot;search_string&quot;))
  57. }
  58. p := &amp;UserInfo{Title: &quot;Project Tube&quot;,UserId: &quot;dxa132330&quot;, UserName: &quot;Dinesh Appavoo&quot;}
  59. renderTemplate(w, &quot;searchproject&quot;, p)
  60. }
  61. var templates = template.Must(template.ParseFiles(&quot;home.html&quot;, &quot;editproject.html&quot;, &quot;viewproject.html&quot;, &quot;searchproject.html&quot;, &quot;header.html&quot;, &quot;footer.html&quot;))
  62. func renderTemplate(w http.ResponseWriter, tmpl string, p interface{}) {
  63. //If you use variables other than the struct u r passing as p, then &quot;multiple response.WriteHeader calls&quot; error may occur. Make sure you pass
  64. //all variables in the struct even they are in the header.html embedded
  65. if err := templates.ExecuteTemplate(w, tmpl+&quot;.html&quot;, p); err != nil {
  66. http.Error(w, err.Error(), http.StatusInternalServerError)
  67. }
  68. }
  69. //URL validation
  70. var validPath = regexp.MustCompile(&quot;^/(home|editproject|saveproject|viewproject|searchproject)/(|[a-zA-Z0-9]+)$&quot;)
  71. func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
  72. return func(w http.ResponseWriter, r *http.Request) {
  73. m := validPath.FindStringSubmatch(r.URL.Path)
  74. if m == nil {
  75. http.NotFound(w, r)
  76. return
  77. }
  78. fn(w, r, m[2])
  79. }
  80. }
  81. func main() {
  82. flag.Parse()
  83. TestConn()
  84. http.HandleFunc(&quot;/home/&quot;, makeHandler(homeHandler))
  85. http.HandleFunc(&quot;/searchproject/&quot;, makeHandler(searchHandler))
  86. http.Handle(&quot;/resources/&quot;, http.StripPrefix(&quot;/resources/&quot;, http.FileServer(http.Dir(&quot;resources&quot;))))
  87. if *addr {
  88. l, err := net.Listen(&quot;tcp&quot;, &quot;127.0.0.1:0&quot;)
  89. if err != nil {
  90. log.Fatal(err)
  91. }
  92. err = ioutil.WriteFile(&quot;final-port.txt&quot;, []byte(l.Addr().String()), 0644)
  93. if err != nil {
  94. log.Fatal(err)
  95. }
  96. s := &amp;http.Server{}
  97. s.Serve(l)
  98. return
  99. }
  100. http.ListenAndServe(&quot;:8080&quot;, nil)
  101. }

I am facing issues in the searchHandler function. And my html code is here

  1. {{ template &quot;header.html&quot; . }}
  2. &lt;br&gt;&lt;br&gt;
  3. &lt;div class=&quot;container&quot;&gt;
  4. &lt;form action=&quot;/searchproject&quot; method=&quot;GET&quot;&gt;
  5. &lt;div class=&quot;form-group&quot;&gt;
  6. &lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;search_string&quot;&gt;
  7. &lt;/div&gt;
  8. &lt;button type=&quot;submit&quot; class=&quot;btn btn-success&quot;&gt;Search&lt;/button&gt;
  9. &lt;/form&gt;
  10. &lt;/div&gt;

server console log is as follows,

  1. method: GET
  2. Form Data :
  3. Form Data 1: map[]

Could anyone help me on this? Thanks.

答案1

得分: 2

这是你要翻译的内容:

那是一个微妙的问题。

非常微妙地,你在searchproject的URL末尾加了一个斜杠,导致服务器发出301重定向。

表单通过POST(或GET)到/searchproject,服务器非常友好地告诉浏览器应该去/searchproject/(添加了斜杠!),浏览器以GET方式执行并在此过程中丢失了表单数据。

这个示例应该满足你的需求:

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. )
  6. func searchHandler(w http.ResponseWriter, r *http.Request) {
  7. fmt.Printf("%+v\n", r)
  8. fmt.Fprintln(w, "OK")
  9. }
  10. func homeHandler(w http.ResponseWriter, r *http.Request) {
  11. fmt.Fprintln(w, SEARCH_PAGE)
  12. }
  13. func main() {
  14. http.HandleFunc("/", homeHandler)
  15. http.HandleFunc("/searchproject", searchHandler)
  16. http.ListenAndServe(":8080", nil)
  17. }
  18. const SEARCH_PAGE = `
  19. <html>
  20. <body>
  21. <form action="searchproject" method="POST">
  22. <input type="text" name="search_string">
  23. <input type="submit" value="Search">
  24. </form>
  25. </body>
  26. </html>
  27. `
英文:

Thats a subtle problem you have there.

Very subtly you have a trailing slash on the searchproject url that causes a 301 redirect to be issued from the server.

The form does the POST (or GET) to /searchproject and the server, quite kindly says that the browser should go to /searchproject/ (trailing slash added !), which the browser does as a GET and looses the form data in the process.

This example does what you need I think :

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;net/http&quot;
  5. )
  6. func searchHandler(w http.ResponseWriter, r *http.Request) {
  7. fmt.Printf(&quot;%+v\n&quot;, r)
  8. fmt.Fprintln(w, &quot;OK&quot;)
  9. }
  10. func homeHandler(w http.ResponseWriter, r *http.Request) {
  11. fmt.Fprintln(w, SEARCH_PAGE)
  12. }
  13. func main() {
  14. http.HandleFunc(&quot;/&quot;, homeHandler)
  15. http.HandleFunc(&quot;/searchproject&quot;, searchHandler)
  16. http.ListenAndServe(&quot;:8080&quot;, nil)
  17. }
  18. const SEARCH_PAGE = `
  19. &lt;html&gt;
  20. &lt;body&gt;
  21. &lt;form action=&quot;searchproject&quot; method=&quot;POST&quot;&gt;
  22. &lt;input type=&quot;text&quot; name=&quot;search_string&quot;&gt;
  23. &lt;input type=&quot;submit&quot; value=&quot;Search&quot;&gt;
  24. &lt;/form&gt;
  25. &lt;/body&gt;
  26. &lt;/html&gt;
  27. `

huangapple
  • 本文由 发表于 2015年3月12日 15:33:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/29004147.html
匿名

发表评论

匿名网友

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

确定