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

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

Golang html GET form method values are not getting populated

问题

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

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

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

服务器代码如下:

package main

import (
	"flag"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"regexp"
	// "bytes"
)

var (
	addr = flag.Bool("addr", false, "find open address and print to final-port.txt")
)

type Page struct {
	Title string
	Body  []byte
}

type UserInfo struct {
	Title    string
	UserId   string
	UserName string
}

func (p *Page) save() error {
	filename := "projects/" + p.Title + ".txt"
	return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
	filename := "projects/" + title + ".txt"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return &Page{Title: title, Body: body}, nil
}

//Home page handler
//Hard coding the user name
func homeHandler(w http.ResponseWriter, r *http.Request, title string) {
	p := &UserInfo{Title: "Project Tube", UserId: "dxa132330", UserName: "Dinesh Appavoo"}
	renderTemplate(w, "home", p)
}

//Search project handler
func searchHandler(w http.ResponseWriter, r *http.Request, title string) {
	fmt.Println("method:", r.Method) //get request method
	r.ParseForm()
	if r.Method == "GET" {
		form_data := r.FormValue("form_data")
		fmt.Println("Form Data : ", form_data)
		fmt.Println("Form Data  1: ", r.Form)
		for _, val := range r.FormValue("search_string") {
			fmt.Println("Search string: ", val)
		}

	} else {
		r.ParseForm()
		fmt.Println("Search string:", r.FormValue("search_string"))
	}
	p := &UserInfo{Title: "Project Tube", UserId: "dxa132330", UserName: "Dinesh Appavoo"}
	renderTemplate(w, "searchproject", p)
}

var templates = template.Must(template.ParseFiles("home.html", "editproject.html", "viewproject.html", "searchproject.html", "header.html", "footer.html"))

func renderTemplate(w http.ResponseWriter, tmpl string, p interface{}) {

	//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
	//all variables in the struct even they are in the header.html embedded
	if err := templates.ExecuteTemplate(w, tmpl+".html", p); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

//URL validation
var validPath = regexp.MustCompile("^/(home|editproject|saveproject|viewproject|searchproject)/(|[a-zA-Z0-9]+)$")

func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		m := validPath.FindStringSubmatch(r.URL.Path)
		if m == nil {
			http.NotFound(w, r)
			return
		}
		fn(w, r, m[2])
	}
}

func main() {
	flag.Parse()
	TestConn()
	http.HandleFunc("/home/", makeHandler(homeHandler))
	http.HandleFunc("/searchproject/", makeHandler(searchHandler))
	http.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.Dir("resources"))))

	if *addr {
		l, err := net.Listen("tcp", "127.0.0.1:0")
		if err != nil {
			log.Fatal(err)
		}
		err = ioutil.WriteFile("final-port.txt", []byte(l.Addr().String()), 0644)
		if err != nil {
			log.Fatal(err)
		}
		s := &http.Server{}
		s.Serve(l)
		return
	}

	http.ListenAndServe(":8080", nil)
}

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

{{ template "header.html" . }}
<br><br>
<div class="container">
    <form action="/searchproject" method="GET">
        <div class="form-group">
            <input type="text" class="form-control" name="search_string">
        </div>
        <button type="submit" class="btn btn-success">Search</button>
    </form>
</div>

服务器控制台日志如下:

method: GET
Form Data :
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,

package main
import (
&quot;flag&quot;
&quot;fmt&quot;
&quot;html/template&quot;
&quot;io/ioutil&quot;
&quot;log&quot;
&quot;net&quot;
&quot;net/http&quot;
&quot;regexp&quot;
//&quot;bytes&quot;
)
var (
addr = flag.Bool(&quot;addr&quot;, false, &quot;find open address and print to final-port.txt&quot;)
)
type Page struct {
Title string
Body  []byte
}
type UserInfo struct {
Title string
UserId   string
UserName string
}
func (p *Page) save() error {
filename := &quot;projects/&quot; + p.Title + &quot;.txt&quot;
return ioutil.WriteFile(filename, p.Body, 0600)
}
func loadPage(title string) (*Page, error) {
filename := &quot;projects/&quot; + title + &quot;.txt&quot;
body, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &amp;Page{Title: title, Body: body}, nil
}
//Home page handler
//Hard coding the user name
func homeHandler(w http.ResponseWriter, r *http.Request, title string) {
p := &amp;UserInfo{Title: &quot;Project Tube&quot;,UserId: &quot;dxa132330&quot;, UserName: &quot;Dinesh Appavoo&quot;}
renderTemplate(w, &quot;home&quot;, p)
}
//Search project handler
func searchHandler(w http.ResponseWriter, r *http.Request, title string) {
fmt.Println(&quot;method:&quot;, r.Method) //get request method
r.ParseForm()
if r.Method == &quot;GET&quot; {
form_data := r.FormValue(&quot;form_data&quot;)
fmt.Println(&quot;Form Data : &quot;,form_data)
fmt.Println(&quot;Form Data  1: &quot;,r.Form)
for _,val := range r.FormValue(&quot;search_string&quot;) {
fmt.Println(&quot;Search string: &quot;, val)
}
} else {
r.ParseForm()
fmt.Println(&quot;Search string:&quot;, r.FormValue(&quot;search_string&quot;))
}
p := &amp;UserInfo{Title: &quot;Project Tube&quot;,UserId: &quot;dxa132330&quot;, UserName: &quot;Dinesh Appavoo&quot;}
renderTemplate(w, &quot;searchproject&quot;, p)
}
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;))
func renderTemplate(w http.ResponseWriter, tmpl string, p interface{}) {
//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 
//all variables in the struct even they are in the header.html embedded 
if err := templates.ExecuteTemplate(w, tmpl+&quot;.html&quot;, p); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
//URL validation
var validPath = regexp.MustCompile(&quot;^/(home|editproject|saveproject|viewproject|searchproject)/(|[a-zA-Z0-9]+)$&quot;)
func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
m := validPath.FindStringSubmatch(r.URL.Path)
if m == nil {
http.NotFound(w, r)
return
}
fn(w, r, m[2])
}
}
func main() {
flag.Parse()
TestConn()
http.HandleFunc(&quot;/home/&quot;, makeHandler(homeHandler))
http.HandleFunc(&quot;/searchproject/&quot;, makeHandler(searchHandler))
http.Handle(&quot;/resources/&quot;, http.StripPrefix(&quot;/resources/&quot;, http.FileServer(http.Dir(&quot;resources&quot;))))
if *addr {
l, err := net.Listen(&quot;tcp&quot;, &quot;127.0.0.1:0&quot;)
if err != nil {
log.Fatal(err)
}
err = ioutil.WriteFile(&quot;final-port.txt&quot;, []byte(l.Addr().String()), 0644)
if err != nil {
log.Fatal(err)
}
s := &amp;http.Server{}
s.Serve(l)
return
}
http.ListenAndServe(&quot;:8080&quot;, nil)
}

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

{{ template &quot;header.html&quot; . }}
&lt;br&gt;&lt;br&gt;
&lt;div class=&quot;container&quot;&gt;
&lt;form action=&quot;/searchproject&quot; method=&quot;GET&quot;&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;search_string&quot;&gt;
&lt;/div&gt;
&lt;button type=&quot;submit&quot; class=&quot;btn btn-success&quot;&gt;Search&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;

server console log is as follows,

method: GET
Form Data :
Form Data  1:  map[]

Could anyone help me on this? Thanks.

答案1

得分: 2

这是你要翻译的内容:

那是一个微妙的问题。

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

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

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

package main

import (
	"fmt"
	"net/http"
)

func searchHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Printf("%+v\n", r)
	fmt.Fprintln(w, "OK")
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, SEARCH_PAGE)
}

func main() {
	http.HandleFunc("/", homeHandler)
	http.HandleFunc("/searchproject", searchHandler)
	http.ListenAndServe(":8080", nil)
}

const SEARCH_PAGE = `
<html>
<body>
    <form action="searchproject" method="POST">
            <input type="text" name="search_string">
            <input type="submit" value="Search">
    </form>
</body>
</html>
`
英文:

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 :

package main
import (
&quot;fmt&quot;
&quot;net/http&quot;
)
func searchHandler(w http.ResponseWriter, r *http.Request) {
fmt.Printf(&quot;%+v\n&quot;, r)
fmt.Fprintln(w, &quot;OK&quot;)
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, SEARCH_PAGE)
}
func main() {
http.HandleFunc(&quot;/&quot;, homeHandler)
http.HandleFunc(&quot;/searchproject&quot;, searchHandler)
http.ListenAndServe(&quot;:8080&quot;, nil)
}
const SEARCH_PAGE = `
&lt;html&gt;
&lt;body&gt;
&lt;form action=&quot;searchproject&quot; method=&quot;POST&quot;&gt;
&lt;input type=&quot;text&quot; name=&quot;search_string&quot;&gt;
&lt;input type=&quot;submit&quot; value=&quot;Search&quot;&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
`

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:

确定