46

I would like to show client another page after data has been collected from previous page. But I have trouble redirect the new URL on the server side. Here is my logic:

  1. submit user input with POST action to server;
  2. server run function saveChoice() to save user input into a database;
  3. After user input is saved, server send a new URL to client;
  4. By the time the client GET the new URL, server reads the database and get saved data out

And I am stuck on step 3 (here is an example of the flow):

type Stuff struct{ List []string } func checkcheck(w http.ResponseWriter, r *http.Request) { sinfo := Stuff{ List: some_slice } t, err := template.New("").Parse(tpl_ds) checkErr(err) err = r.ParseForm() checkErr(err) err = t.Execute(w, sinfo) checkErr(err) if r.Method == "POST" { saveChoice(r.Form["choices"]) /* step 3: make user open another URL */ } } 

And here is the template:

<html> <script> $(function () { $('form').on('submit', function (e) { e.preventDefault(); $.ajax({ type: 'post', data: $('form').serialize(), }); }); }); </script> <body> <form method="POST"> {{range .List}} <input type="checkbox" name="choices" value="{{.}}"> <span>{{.}}</span><br> {{end}} <input type="submit" value="Submit"> </form> </body> </html> 

May I know how I can redirect to a new page?

p.s. If I put URL on button, then server is not going to run saveChoice()

1
  • Actually the effective part is to add if r.Method=="GET" like Aruna said, which prevents the error of redirecting 2 pages Commented Mar 11, 2016 at 17:03

2 Answers 2

70

The http status 303 is the appropriate response here. So redirect the request with it.

if r.Method == "POST" { saveChoice(r.Form["choices"]) http.Redirect(w, r, newUrl, http.StatusSeeOther) } 

And if your newUrl is supposed to return a proper html page to the browser, you don't need to use ajax. Use an html form.

<form action="/postHandler" method="post"> {{range .List}} <input type="checkbox" name="choices" value="{{.}}"> <span>{{.}}</span><br> {{end}} <input type="submit" value="Submit"> </form> 

Notice action of the form is defined as /postHandler. Put the name of the endpoint that runs your saveChoice function there.

So to avoid http: multiple response.WriteHeader calls error you get use this code.

 func checkcheck(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { sinfo := Stuff{ List: some_slice } t, err := template.New("").Parse(tpl_ds) checkErr(err) err = r.ParseForm() checkErr(err) err = t.Execute(w, sinfo) checkErr(err) } if r.Method == "POST" { saveChoice(r.Form["choices"]) http.Redirect(w, r, newUrl, http.StatusSeeOther) } } 

Otherwise, the server attempts to render both the form and the redirected url which will result in mutiple calls to the response writer.

Sign up to request clarification or add additional context in comments.

10 Comments

At first it shows an error so I have to do preventDefault on the button
Kyle please post the javascript/html code you use with this button as well.
Kyle if the newUrl is supposed to return a proper html page, don't use ajax. Just let the form submit. Then the redirection will work.
I tried without the code and still doesn't work. And if I let the button or form action to redirect before I have data uploaded to server, then saveChoice() won't run. Let me see if I can put more code on so you can take a look at details. Thanks for the helps!
Kyle, what is the url of the post request that runs saveChoice? Could you show the code that defines this endpoint?
|
3
package main import ( "net/http" "html/template" ) type data struct { List string } func main() { http.HandleFunc("/", check) } func check(w http.ResponseWriter, r * http.Request) { if r.Method == "GET" { sinfo: = data { List: "Here is a list of the files Located with in", } var tpl_ds = "index.html" //t, err := template.New("").Parse(tpl_ds) t: = template.Must(template.ParseFiles(tpl_ds)) r.ParseForm() t.Execute(w, sinfo) } if r.Method == "POST" { saveChoice(r.Form["choices"]) http.Redirect(w, r, newUrl, http.StatusSeeOther) } } 

1 Comment

This does not answer the entire question but it leads to the answer. I hope this helps.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.